Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Центр помощи > [С++]Работа с текстом


Автор: klest 25.7.2011, 16:36
Есть файл logfile.txt из него нужно выбрать ("C:\Documents and Settings\Admin\Мои документы\Visual Studio 2005\Projects\C++21.Week1\C++21.Week1") такого типа подстроки находящиеся в кавычках при этом удалить одинаковые и записать их в отдельный файл. 

Т.е. должно получиться:

"C:\Documents and Settings\Admin\Мои документы\Visual Studio 2005\Projects\C++21.Week1\C++21.Week1"

"C:\Documents and Settings\Admin\Мои документы\Visual Studio 2005\Projects\C++21.Week1\C++21.Week1\C++21.Week1.vcproj"

"C:\Documents and Settings\Admin\Мои документы\Visual Studio 2005\Projects\C++21.Week1\C++21.Week1.sln" и т.д.

Подскажите пожалуйста как это реализовать на С++!!!

Автор: DeMoNN 26.7.2011, 14:42
Самый простой способ исключать одинаковые строки - использовать хеш-таблицу. Выдираешь строки, считаешь хеш, смотришь, есть ли он в хеш-таблице, если нет, то выводишь в файл и ставишь пометку в таблице.

Если же проблема именно в выдирании строк, то тут все просто - легко заметить, что эти подстроки встречаются в каждой строке и начинаются с 15-й кавычки, так что просто считываешь символы из файла по одному, отсчитаваешь 14 кавычек и начинаешь сохранять строку в переменной и попутно считать хеш. Как только встречаешь очередную кавычку - перестаешь, делаешь описанные выше действия с хеш-таблицей и переходишь к следующей строке. Делаешь так до конца файла.

Если не знаешь, как реализовывать хеш-таблицу:
заводишь достаточно большой булевый массив, берешь хеш от строки и берешь его по модулю длины массива, это и будет индексом текущей строки в этом массиве. Если пометка есть - строка встречалась, если нет - не встречалась. Можно взять несколько массивов разного размера (лучше, если это будут взаимно простые числа). Тут сам тогда сообразишь, как проверять наличие строки.

Обычный полиномиальный хеш тут вполне подойдет.

Автор: klest 27.7.2011, 08:10
Спасибо! Попытаюсь теперь все это реализовать)))

Автор: Silent 27.7.2011, 12:07
а я всегда map для таких дел использовал, дешево и сердито:
Код

std::map<std::string, int> a;
std::string word;

while (std::getline(std::cin, word))    
   a[word]++;

for (std::map<std::string, int>::iterator it = a.begin(); it != a.end(); it++)
   printf("%s", it->first);

Автор: klest 28.7.2011, 16:27
В связи с отсутствием опыта программирования, не получается написать код. Кто-нибудь может написать хотя-бы половину кода с пояснением чтобы можно было дальше разобраться?        

Автор: DeMoNN 28.7.2011, 20:39
Код немножко говнистый, но рабочий:
Код

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

using namespace std;

ifstream fin("logfile.txt"); //твой файл
ofstream fout("result.txt"); //результат работы программы
string s; //сохраняем текущую подстроку сюда
string line; //текущая строка
char c; //текущий считываемый символ
int qn; //число кавычек
int ht[8][23]; //hash-таблица
int htn[8] = {2,3,5,7,11,13,17,23}; //для hash-таблицы
int i;
unsigned int hash, p; //хеш

int main()
{
    while (getline(fin, line)) { //пока не дойдем до конца файла
        qn = 0;
        i = 0;
        s = "";
        hash = 0;
        while (qn < 15) { //отсчитываем 14 кавычек
            c = line[i++]; //считываем очередной символ
            qn += (c == '"'); //если с - кавычка, то увеличиваем qn
        }
        c = line[i++];
        p = 3; //любое число, большее единицы
        while (c != '"') {
            s += c; //добавляем символ в строку
            hash += p*c; //считаем хеш
            p *= p;
            c = line[i++]; //считываем очередной символ
        }
        bool good = false;
        for (int j = 0; j < 8; j++) //проверяем наличие строки в хеш-таблице
            if (ht[j][hash%htn[j]] == 0) {
                good = true;
                break;
            }

        if (good) { //если строки нет в hash-таблице
            for (int j = 0; j < 8; j++) //добавляем ее
                ht[j][hash%htn[j]] = 1;
            fout << '"' << s << '"' << endl; //выводим строку
        }
    }

    fout.close();

    return 0;
}

Автор: klest 29.7.2011, 08:42
Спасибо огромное!!! Программа работает, только при запуске появляется вот эта ошибка. Ни знаешь, что это за ошибка? 

Автор: Silent 29.7.2011, 10:13
klest, не слушай DeMoNN'а, это самый натуральный г..нокод - через полгода, глянув на него, понять логику кода невозможно. Я бы сделал так:
Код

#include <fstream>
#include <string>
#include <map>
#include <sstream>
using namespace std;

map <string, bool> paths;
string line, item;

int main()
{
    ifstream fin  ("logfile.txt");
    ofstream fout ("output.txt");
    while (getline(fin, line))
    {
        stringstream ss(line);
        for (int i = 0; i < 6; i++) 
            getline(ss, item, ',');
        paths[item] = true;
//        paths[_strupr(&item[0])] = true;
    }

    for (map<string, bool>::iterator it = paths.begin(); it != paths.end(); it++)
        fout << it->first << endl;
    return 0;
}

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

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)