Модераторы: bsa
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> замена вложенных циклов 
V
    Опции темы
kachu
Дата 5.6.2013, 15:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 6
Регистрация: 30.5.2012

Репутация: нет
Всего: нет



здравствуйте. 
Нужно было написать программу, а задание следующее: Имеется телефонный справочник в текстовом формате. В каждой строке файла указаны фамилия, имя, адрес, телефон, дата рождения. Поля разделены пробелом. Записать в новый текстовый файл все данные об однофамильцах. Имена всех файлов задаются в командной строке.

программу написал, но очевидно, что первый (внешний) цикл while сработает 1 (один) раз. Подскажите как это можно исправить?

Код

#include <iostream>
#include <fstream>
#include <string>

using namespace std;

int main(int argc, char *argv[])
{
    if (argc != 3) 
    {
        printf("Вы забыли ввести имена файлов\n");
        exit(1);
    }
    else
    {
        char *line1 = new char[255];
        char *line2 = new char[255];
        char *full1 = new char[1000];
        char *full2 = new char[1000];
        int flag = 0;

        ifstream fin(argv[1]);
        ofstream fout(argv[2]);

        while (fin)
        {
            fin >> line1;
            fin.getline(full1,1000);

            
            while (fin)
            {
                
                fin >> line2;
                fin.getline(full2,1000);

                if (strcmp(line1,line2)==0)
                {
                    if (flag == 0) 
                    {
                        fout << line1 << full1 << "\n";
                        flag = 1;
                    }
                    fout << line2 << full2 << "\n";
                }
            }
        }
    }
}

PM MAIL   Вверх
mes
Дата 5.6.2013, 16:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 79
Всего: 250



Цитата(kachu @  5.6.2013,  14:53 Найти цитируемый пост)
 что первый (внешний) цикл while сработает 1 (один) раз

в обоих циклах один и тот же идентификатор условия окончания цикла (fin)


--------------------
PM MAIL WWW   Вверх
kachu
Дата 5.6.2013, 16:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 6
Регистрация: 30.5.2012

Репутация: нет
Всего: нет



mes,  я понимаю, но не знаю как можно не создавая копию этого потока исправить это, т.е. не создавая  ifstream fin2(argv[1]) например.
PM MAIL   Вверх
mes
Дата 5.6.2013, 18:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 79
Всего: 250



Цитата(kachu @  5.6.2013,  15:31 Найти цитируемый пост)
 но не знаю как можно не создавая копию этого потока исправить это, 

сформулировать для начала на словах алгоритм действий..


другими словами: определите, что должен делать Ваш внешний цикл, а что внутренний.. 

Это сообщение отредактировал(а) mes - 5.6.2013, 18:25


--------------------
PM MAIL WWW   Вверх
volatile
Дата 5.6.2013, 18:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 16
Всего: 85



Код

fin.seekg (0, std::ios::beg);


PM MAIL   Вверх
kachu
Дата 5.6.2013, 18:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 6
Регистрация: 30.5.2012

Репутация: нет
Всего: нет



mes, внешний цикл - перебор строк файла, а внутренний - аналогично перебирает строки того же файла и сравнивает строку, полученную во внешнем цикле со всеми остальными строками.
т.е. аналог 
Код

for (int i = 0; i < countoflines; i++)
    for (int j = 0; j < countoflines; j++)
// тут берется i-я строка и сравнивается со всеми j-ми
// но все эти строки в одном файле



volatile, я думал вернуться в начало файла, но опять же не понял как это реализовать.
PM MAIL   Вверх
volatile
Дата 5.6.2013, 19:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 16
Всего: 85



kachu, я бы отсортировал, (если память конечно позволяет) потом одним циклом вывел всех однофамильцев.
Двойным циклом, как вы хотите будут одни и теже выводицца по нескольку раз, если однофамильцев больше двух.



PM MAIL   Вверх
kachu
Дата 5.6.2013, 19:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 6
Регистрация: 30.5.2012

Репутация: нет
Всего: нет



volatile, спасибо за идею, буду пробовать
PM MAIL   Вверх
mes
Дата 5.6.2013, 19:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 79
Всего: 250



Цитата(kachu @  5.6.2013,  17:45 Найти цитируемый пост)
 внешний цикл - перебор строк файла, а внутренний - аналогично перебирает строки того же файла и сравнивает строку, полученную во внешнем цикле со всеми остальными строками.

итого, опираясь на приведенный выше код, Вам нужно два потока от одного источника, при этом поток во внутреннем цикле после истечения должен переокрываться..

Добавлено через 4 минуты и 30 секунд
но предложение от volatile реализуется легче и эффективнее (для файлов "нормальной" длины)  smile 


--------------------
PM MAIL WWW   Вверх
volatile
Дата 5.6.2013, 20:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 16
Всего: 85



Можно вообще просто сделать.
(нехорошо поступаю конечно, что готовый ответ даю smile) 
Код

...
#include <map>
int main(int argc, char *argv[])
{
   // ...
    ifstream fin(argv[1]);
    ofstream fout(argv[2]);

    std::string name;
    typedef std::map <std::string, int> map_t;
    map_t mp;
    
    while (fin >> name)
    {
        ++ mp [name];
        fin.ignore (9999, '\n');
    }
    for (map_t::iterator i = mp.begin(); i != mp.end(); ++ i)
       if (i->second > 1)
          fout << i->first << std::endl;
} 


Это сообщение отредактировал(а) volatile - 5.6.2013, 20:04
PM MAIL   Вверх
mes
Дата 5.6.2013, 20:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 79
Всего: 250



volatile, в простой мапе теряется информация о всех однофамильцах... 

Цитата(kachu @  5.6.2013,  14:53 Найти цитируемый пост)
Записать в новый текстовый файл все данные об однофамильцах.


Добавлено через 1 минуту и 23 секунды
плюс боюсь трудновато будет тс с ходу понять...


--------------------
PM MAIL WWW   Вверх
volatile
Дата 5.6.2013, 20:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 16
Всего: 85



Цитата(mes @  5.6.2013,  20:08 Найти цитируемый пост)
Записать в новый текстовый файл все данные об однофамильцах.

ах, сорри, не обратил внимания...
ну дописывать уже не буду. пусть ТС сам дальше...  smile 
PM MAIL   Вверх
kachu
Дата 6.6.2013, 14:13 (ссылка) |    (голосов:2) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 6
Регистрация: 30.5.2012

Репутация: нет
Всего: нет



volatile, 
mes, 
спасибо Вам. 

по поводу map: нельзя мне использовать, т.к. разрешено использовать только то что даётся преподавателем.

проблему с повторным открытием потока в цикле решил, разобрался всё-таки с seekg. 
использовал такую конструкцию:
Код

while ()
{
i = fin.tellg(); // запоминаем позицию
 while() {}    //работаем

fin.clear();    // сбрасываем флаг
fin.seekg(pos,fin.beg); //возвращаемся к сохраненной позиции
}


всё работает, но замечание 
Цитата(volatile @  5.6.2013,  19:07 Найти цитируемый пост)
Двойным циклом, как вы хотите будут одни и теже выводицца по нескольку раз, если однофамильцев больше двух.

конечно справедливо, но в данном случае можно сдать работу и так.

Это сообщение отредактировал(а) kachu - 6.6.2013, 14:16
PM MAIL   Вверх
volatile
Дата 7.6.2013, 08:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 16
Всего: 85



Цитата(kachu @  6.6.2013,  14:13 Найти цитируемый пост)
while ()
{
i = fin.tellg(); // запоминаем позицию
 while() {}    //работаем

fin.clear();    // сбрасываем флаг
fin.seekg(pos,fin.beg); //возвращаемся к сохраненной позиции
}

kachu, Молодец! Правильно все сделали.
Мне лишь не нравицца алгоритм двойного прохода.
мало того что он не правильный, он еще и очень долгий. сложность O(N^2), что при больших N выльецца в  очень долгий процесс.

Цитата(kachu @  5.6.2013,  15:53 Найти цитируемый пост)
Имеется телефонный справочник в текстовом формате.

Скорей всего, здесь подразумеваецца что справочник отстортирован по фамилиям.
Иначе, задание слишком сложное, для новичка не проходившего стл-овские массивы.


PM MAIL   Вверх
kachu
Дата 8.6.2013, 10:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 6
Регистрация: 30.5.2012

Репутация: нет
Всего: нет



volatile, спасибо за похвалу

по поводу сложности вы видимо правы, из всех заданий это одно помечено "*", и единственное вызвало затруднения
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.0781 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.