Форум программистов, компьютерный форум CyberForum.ru
Наши страницы

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 13, средняя оценка - 4.69
lizard
0 / 0 / 0
Регистрация: 20.09.2011
Сообщений: 14
#1

поиск файлов по строкам - C++

20.09.2011, 14:43. Просмотров 1785. Ответов 16
Метки нет (Все метки)

Привет всем!

Мне нужно решить следующую задачу:
Найти первый файл в каталоге папок, удовлетворяющий заданной маске и содержащий заданный текст. И отобразить его название. Кое-какой код я написал, однако в процессе выполнения вылетает ошибка EAccesVialation.

Ошибка при выполнении 89 строки: fgets(str, 255, file);

Могли бы Вы помочь разобраться в чем ошибка?

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#include <iostream.h>
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fstream.h>
#include <conio.h>
bool   IsFile(LPCTSTR sPath);
long  GetFindList(LPCTSTR sPath, LPCTSTR sFind, LPCTSTR sText);
bool   IsStrEqualMask(LPCTSTR s, LPCTSTR sFind);
 
 
int main()
{
        char ch;
        char start_dir[MAX_PATH];
        char file_mask[MAX_PATH];
        char text_pattern[255] = { 0 };
 
        do
        {
                 cout<<"Enter directory for search:\r\n";
                 cin>>     start_dir;
 
                        cout<<"Enter mask:\r\n";
                        cin>>file_mask;
                        cout<<"Enter text to find:\r\n";
                        cin>>text_pattern;
                        
                        if(GetFindList(start_dir, file_mask, text_pattern) < 1)
                        cout<<"Files not found\r\n";
 
 
                cout<<"Retry search?\r\nY - yes N - exit\r\n";
                cin>>ch;
        }
        while(ch == 'Y' || ch == 'y');
        return 0;
}
 
 
bool IsFile(LPCTSTR sPath)
{
        bool bFile = false;
        HANDLE hFile = CreateFile
                (
                        sPath, 
                        GENERIC_READ,
                        FILE_SHARE_READ,
                        NULL, 
                        OPEN_EXISTING, 
                        FILE_ATTRIBUTE_NORMAL,
                        NULL
                );
        if(hFile != INVALID_HANDLE_VALUE)
        {
                CloseHandle(hFile);
                bFile = true;
        }
        return bFile;
}
 
 
long GetFindList(LPCTSTR sPath, LPCTSTR sFind, LPCTSTR sText)
{
FILE* file = NULL;
 
       char str[255]={0};
       long nFiles = 0;
        WIN32_FIND_DATA pDATA;
        strcat(strcpy(pDATA.cFileName,sPath),"*.*");
        HANDLE hFile = FindFirstFile(pDATA.cFileName,&pDATA);
        if(hFile != INVALID_HANDLE_VALUE)
        {
                do
                {
                        if(strcmp(pDATA.cFileName,".")  == 0 ||
                           strcmp(pDATA.cFileName,"..") == 0)
                           continue;
                        else
                        {
                                if(pDATA.dwFileAttributes != FILE_ATTRIBUTE_DIRECTORY)
                                if(IsStrEqualMask(pDATA.cFileName, sFind))
                                {
 
                                file = fopen("D:\1\1.txt", "r+");
 
 
        fgets(str, 255, file);
 
        if(!strstr(str,sText)){}
        else{
        cout<<"The first file containing this text is:["<<pDATA.cFileName<<"]\r\n";
                             nFiles++;
                             break;     }
                                           }
                                              }
                                                 }
 
                while(FindNextFile(hFile,&pDATA));
        }
        return nFiles;
}
 
bool IsStrEqualMask(LPCTSTR s, LPCTSTR sFind)
{
        bool bEqual = true;
        char delim[] = " \\,.*";
        char * sMask = new char[strlen(sFind) + 1];
        strcpy(sMask,sFind);
        
        char * buf = strtok(sMask,delim);
        while(buf)
        {
                if(!strstr(s,buf))
                {
                        bEqual = false;
                        break;
                }
                buf = strtok(NULL,delim);
        }
        delete [] sMask;
        return bEqual;
}

p.s. поиск в подпапках и проверка файлов, удовлетворяющих маске на содержание заданной фразы, к сожалению пока не реализованы.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
20.09.2011, 14:43
Здравствуйте! Я подобрал для вас темы с ответами на вопрос поиск файлов по строкам (C++):

Поиск по строкам - C++
Как в матрице N x M реализовать поиск по строкам (начиная с первой строки) кол-ва чисел, которые не равны нулю?? И если это кол-во равно...

Поиск файлов - C++
Вот решил перейти к изучению C++ после Delphi, интерисует как найти все файлы в папке :) Готовый код или ссылки, буду рад всему :)

Поиск файлов С++ - C++
Помогите плиз поправить код!!! Т.е чтоб прога выводила все текстовики в данном каталоге!!! #include&lt;iostream&gt; #include &lt;windows.h&gt; ...

Поиск файлов - C++
Помогите хотя бы в теории понять, возможен ли поиск файлов без использования функций библиотеки windows.h вообще, и как его можно...

Поиск и удаление файлов - C++
Приветствую всех! Есть задача: На диске C: найти файл samantha is gonna kill you.mp3 и его удалить, и нужно делать программно. ...

рекурсивный поиск файлов - C++
Всем привет! Нажно реализовать поиск файлов по маске. Набрасал вот такой код: int search_file(string disk, string mask) { char...

16
Kastaneda
Нарушитель
Эксперт С++
4676 / 2880 / 234
Регистрация: 12.12.2009
Сообщений: 7,314
Записей в блоге: 2
Завершенные тесты: 1
20.09.2011, 14:51 #2
На самом деле ошибка здесь:
C++
1
file = fopen("D:\1\1.txt", "r+");
символ слэш означает экранирование, видишь даже как еденицы подсвечены. Чтоб ввести символ слеш нужно его экранировать опять таки слешем, т.е. вот так:
C++
1
file = fopen("D:\\1\\1.txt", "r+");
теперь видишь как подсвечено?

Добавлено через 2 минуты
т.е. получается, что файл не открылся, из за этого и ошибка при чтении. Поэтому проверяй файл перед чтением/записью
C++
1
2
3
 file = fopen("D:\\1\\1.txt", "r+");
 if(file)
      fgets(str, 255, file);
0
lizard
0 / 0 / 0
Регистрация: 20.09.2011
Сообщений: 14
20.09.2011, 15:07  [ТС] #3
Kastaneda
Действительно, спасибо большое за быстрый ответ.

Надо было сразу делать автоматически перебор, а не к конкретному файлу обращаться.


Теперь задача корректно соединить sPath и pDATA.cFileName и применить эту строку в fopen().
Не подскажите как?
0
Kastaneda
Нарушитель
Эксперт С++
4676 / 2880 / 234
Регистрация: 12.12.2009
Сообщений: 7,314
Записей в блоге: 2
Завершенные тесты: 1
20.09.2011, 15:16 #4
Цитата Сообщение от lizard Посмотреть сообщение
Теперь задача корректно соединить sPath и pDATA.cFileName и применить эту строку в fopen().
Как я понял нужно к строке, хранящейся в sPath, присоеденить строку из pDATA.FileName. Тогда так
C++
1
strcat(pPath, pDATA.FileName);
при этом размер pPath должен быть достаточным, чтобы вместить pPath+pDATA.FileName. Если нет, то можно завести дополнительный массив для этого:
C++
1
2
3
4
char pPath_and_FileName[512];//размер с запасом
strcpy(pPath_and_FileName, pPath);
strcat(pPath_and_FeliName, pDATA.FileName);
file=fopen(pPath_and_FileName, "r+");
1
lizard
0 / 0 / 0
Регистрация: 20.09.2011
Сообщений: 14
20.09.2011, 15:39  [ТС] #5
во втором случае показывает следующую ошибку:

[C++ Error] Unit1.cpp(85): E2316 'FileName' is not a member of '_WIN32_FIND_DATAA'
0
Kastaneda
Нарушитель
Эксперт С++
4676 / 2880 / 234
Регистрация: 12.12.2009
Сообщений: 7,314
Записей в блоге: 2
Завершенные тесты: 1
20.09.2011, 15:43 #6
это я у тебя не внимательно списал, а ты не проверил
правильно будет pDATA.cFileName
0
-=ЮрА=-
Заблокирован
Автор FAQ
20.09.2011, 16:32 #7
Цитата Сообщение от lizard Посмотреть сообщение
Могли бы Вы помочь разобраться в чем ошибка?
- у меня спросить
Поиск файла по шаблону

Цитата Сообщение от lizard Посмотреть сообщение
file = fopen("D:\1\1.txt", "r+");
fgets(str, 255, file);
- накой было код переводить
Список полей WIN32_FIND_DATA
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
typedef struct _WIN32_FIND_DATAA {
    DWORD dwFileAttributes;
    FILETIME ftCreationTime;
    FILETIME ftLastAccessTime;
    FILETIME ftLastWriteTime;
    DWORD nFileSizeHigh;
    DWORD nFileSizeLow;
    DWORD dwReserved0;
    DWORD dwReserved1;
    CHAR   cFileName[ MAX_PATH ];
    CHAR   cAlternateFileName[ 14 ];
#ifdef _MAC
    DWORD dwFileType;
    DWORD dwCreatorType;
    WORD  wFinderFlags;
#endif
} WIN32_FIND_DATAA, *PWIN32_FIND_DATAA, *LPWIN32_FIND_DATAA;
Добавлено через 5 минут
lizard, есть цикл поиска, нужен первый файл удовлетворяющий маске так введи break и strcmp код топика ужастен
0
lizard
0 / 0 / 0
Регистрация: 20.09.2011
Сообщений: 14
20.09.2011, 16:41  [ТС] #8
да уж. тупанул я)

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

C++
1
2
3
4
char sPath_and_FileName[512];
strcpy(sPath_and_FileName, sPath);
strcat(sPath_and_FileName, pDATA.cFileName);
file=fopen(sPath_and_FileName, "r+");


спасибо еще раз (:

Добавлено через 6 минут
Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
есть цикл поиска, нужен первый файл удовлетворяющий маске так введи break
так он и был. строка 95.

Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
strcmp код топика ужастен
можно подробнее объяснить?
0
-=ЮрА=-
Заблокирован
Автор FAQ
20.09.2011, 16:47 #9
lizard, сейчас перепишу, верней восстановлю код + введу рекурсию чтобы все подкаталоги обрабатывал
Цитата Сообщение от lizard Посмотреть сообщение
можно подробнее объяснить?
Цитата Сообщение от lizard Посмотреть сообщение
GetFindList
- это уже готовая функция поиска, какой ещё константный путь в ней пробивать???
Цитата Сообщение от Kastaneda Посмотреть сообщение
file = fopen("D:\\1\\1.txt", "r+");
Ты файл ишещь или открываешь уже наперёд известный?

Добавлено через 1 минуту
Вобщем реализовываю задание - вбиваем каталог и выполняем в нём поиск первого файла удовлетворяющего маске, скоро отпишусь...(как я ShlDialog выбора каталога напугал и будем его руками вводить)
0
lizard
0 / 0 / 0
Регистрация: 20.09.2011
Сообщений: 14
20.09.2011, 16:56  [ТС] #10
Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
Ты файл ишещь или открываешь уже наперёд известный?
да ясное дело что ищем. Я просто отладку делал с реакцией на найденное слово в файле, поэтому ввел адрес на время
0
-=ЮрА=-
Заблокирован
Автор FAQ
20.09.2011, 17:24 #11
Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
Вобщем реализовываю задание - вбиваем каталог и выполняем в нём поиск первого файла удовлетворяющего маске
Вот Си код (SHL-диалог выбора файла не убирал, т.к достаёт вручную вбивать пути на своём компьютере, если есть желание его убрать - убираем, у меня этого желания нет)
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
#include <iostream.h>//i/o
#include <windows.h> //FindFirst(Next)File
#include <shlobj.h>  //Диалог выбора файла
#include <stdio.h>   //sprintf
//Руссификация
ostream& operator<<(ostream &stream,char* s){
    for(char* ps=s; *ps; ps++){
        if(*ps=='ё')
            stream<<char(241);
        else if(*ps=='Ё')
            stream<<char(240);
        else if(*ps>=-64 && *ps<=-17)           
            stream<<char(*ps+64+128);
        else if(*ps<0)
            stream<<char(*ps+64+176);
        else
            stream<<*ps;
    }
    return stream;
}
 
char * SelectFile(HWND hWnd);
bool   IsFile(LPCTSTR sPath);
bool   FindFile(LPCTSTR sPath, LPCTSTR sFind);
bool   IsStrEqualMask(LPCTSTR s, LPCTSTR sFind);
 
int main()
{
    char ch;
    char szFilePath[MAX_PATH];
    char szFindMask[MAX_PATH];
    HWND hWnd = GetForegroundWindow();//Находим дескриптор окна консоли
    do
    {
        if(!strcpy(szFilePath,SelectFile(hWnd)))
            cout<<"Файл не выбран";
        else
        {
            if(IsFile(szFilePath))
            {
                    cout<<"Выбран файл\r\n";
                    szFilePath[strlen(szFilePath) - strlen(strrchr(szFilePath,'\\')) + 1] = '\0'; 
            }
            cout<<"Каталог для поиска:\r\n["<<szFilePath<<"]\r\n";
            cout<<"Введите маску поиска\r\n";
            cin>>szFindMask;
            if(!FindFile(szFilePath, szFindMask))
                cout<<"Поиск не дал результатов\r\n";
        }
        cout<<"Y - Повторить поиск\r\n";
        cin>>ch;
    }
    while(ch == 'Y' || ch == 'y');
    return 0;
}
 
char * SelectFile(HWND hWnd)
{
    ShowWindow(hWnd,SW_HIDE);
    char sPath[MAX_PATH];sPath[0] = '\0';
    LPCITEMIDLIST lpItemDList;
    BROWSEINFO bi = {NULL, NULL, sPath,
       "Выберите файл или каталог",
        BIF_DONTGOBELOWDOMAIN|BIF_BROWSEINCLUDEFILES,
        NULL,
        NULL,
        0
    };
    if((lpItemDList = SHBrowseForFolder(&bi)))
    {
        if(SHGetPathFromIDList(lpItemDList, sPath))
            GetShortPathName((LPCTSTR)sPath,sPath,strlen(sPath));
    }
    ShowWindow(hWnd,SW_SHOW);
    return &sPath[0];
}
 
bool IsFile(LPCTSTR sPath)
{
    bool bFile = false;
    HANDLE hFile = CreateFile
        (
            sPath, 
            GENERIC_READ,
            FILE_SHARE_READ,
            NULL, 
            OPEN_EXISTING, 
            FILE_ATTRIBUTE_NORMAL,
            NULL
        );
    if(hFile != INVALID_HANDLE_VALUE)
    {
        CloseHandle(hFile);
        bFile = true;
    }       
    return bFile;
}
 
 
bool FindFile(LPCTSTR sPath, LPCTSTR sFind)
{
    bool bFind = false;
    char sDir[MAX_PATH];
    WIN32_FIND_DATA pDATA;
    strcat(strcpy(pDATA.cFileName,sPath),"\\*.*");
    HANDLE hFile = FindFirstFile(pDATA.cFileName,&pDATA);
    if(hFile != INVALID_HANDLE_VALUE)
    {
        do
        {
            if(strcmp(pDATA.cFileName,".")  == 0 ||
               strcmp(pDATA.cFileName,"..") == 0)
               continue;
            else
            {
                if(pDATA.dwFileAttributes != FILE_ATTRIBUTE_DIRECTORY)
                if(IsStrEqualMask(pDATA.cFileName, sFind))
                {
                    cout<<"Найден файл :["<<pDATA.cFileName<<"]\r\n";
                    bFind = true;
                    break;
                }
                else
                {
                    //Нашли подкаталог - ныряем в него
                    sprintf(sDir,"%s\\%s",sPath, pDATA.cFileName);
                    if((bFind = FindFile(sDir, sFind)))
                        break;//Если поиск успешен, сразу прекращаем поиск
                }
            }
        }
        while(FindNextFile(hFile,&pDATA));
    }
    return bFind;
}
 
bool IsStrEqualMask(LPCTSTR s, LPCTSTR sFind)
{
    bool bEqual = true;
    //шаблон может содержать ' ' '\\' ',' '.' '*'
    char delim[] = " \\,.*";
    char * sMask = new char[strlen(sFind) + 1];
    strcpy(sMask,sFind);
    
    char * buf = strtok(sMask,delim);
    while(buf)
    {
        if(!strstr(s,buf))
        {
            bEqual = false;
            break;
        }
        buf = strtok(NULL,delim);
    }
    delete [] sMask;
    return bEqual;
}
[Результат работы]
Каталог для поиска:
[D:\МОИДОК~1\0292~1\21EF~1]
Введите маску поиска
*.xls
Найден файл :[Общий баланс(сентябрь)-2011.xls]
Y - Повторить поиск


Добавлено через 1 минуту
Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
if(IsStrEqualMask(pDATA.cFileName, sFind))
* * * * * * * * * * * * * * * * {
* * * * * * * * * * * * * * * * * * * * cout<<"Найден файл :["<<pDATA.cFileName<<"]\r\n";
* * * * * * * * * * * * * * * * * * * * bFind = true;
* * * * * * * * * * * * * * * * * * * * break;
* * * * * * * * * * * * * * * * }
* * * * * * * * * * * * * * * * else
* * * * * * * * * * * * * * * * {
* * * * * * * * * * * * * * * * * * * * //Нашли подкаталог - ныряем в него
* * * * * * * * * * * * * * * * * * * * sprintf(sDir,"%s\\%s",sPath, pDATA.cFileName);
* * * * * * * * * * * * * * * * * * * * if((bFind = FindFile(sDir, sFind)))
* * * * * * * * * * * * * * * * * * * * * * * * break;//Если поиск успешен, сразу прекращаем поиск
* * * * * * * * * * * * * * * * }
if((bFind = FindFile(sDir, sFind))) - рекурсивный обход всех подкаталогов

Добавлено через 10 минут
Вот код аналогичной функциональности позволяющий исключить ShlDialog
C
1
2
3
4
5
6
7
8
9
szFilePath[0] = '\0';
        cout<<"Введите каталог\r\n";
        cin.getline(szFilePath,MAX_PATH);
        if(szFilePath[0] == '\0')
            cout<<"Файл не выбран\r\n";
        else
        {
            if(IsFile(szFilePath))
            {
0
Nameless One
Эксперт С++
5775 / 3425 / 255
Регистрация: 08.02.2010
Сообщений: 7,448
20.09.2011, 17:30 #12
lizard, если пишешь на С++, то логичней вместо char* использовать для строк класс string
0
lizard
0 / 0 / 0
Регистрация: 20.09.2011
Сообщений: 14
20.09.2011, 17:31  [ТС] #13
за рекурсию спасибо.
Но в задании цель не вывести название первого файла удовлетворяющего маске, а вывести название первого файла удовлетворяющего маске и в содержащего заданную слово\фразу. Поэтому и входящий параметр добавился в функцию. И поэтому же там появились строки

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
...
 
char sPath_and_FileName[512];
strcpy(sPath_and_FileName, sPath);
strcat(sPath_and_FileName, pDATA.cFileName);
file=fopen(sPath_and_FileName, "r+");
fgets(str, 255, file);
 
        if(!strstr(str,sText)){}
        else{
        cout<<"The first file containing this text is:["<<pDATA.cFileName<<"]\r\n";
                             nFiles++;
                             break;     }
...
0
Nameless One
Эксперт С++
5775 / 3425 / 255
Регистрация: 08.02.2010
Сообщений: 7,448
20.09.2011, 17:35 #14
Кстати, по теме, глянь исходники find
0
-=ЮрА=-
Заблокирован
Автор FAQ
20.09.2011, 18:32 #15
Цитата Сообщение от lizard Посмотреть сообщение
file=fopen(sPath_and_FileName, "r+");
fgets(str, 255, file);
if(!strstr(str,sText)){}
* * * * else{
- в функцию нужно передавать текст для поиска, а не открывать файл, сейчас подправлю, если честно задание сложно было понять...
0
20.09.2011, 18:32
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
20.09.2011, 18:32
Привет! Вот еще темы с ответами:

Поиск тестовых файлов - C++
Возник такой вопрос: можно ли написать программу, которая будет искать в папке текстовые файлы и выводить их названия на экран. Если можно,...

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

Поиск файлов в директории - C++
Интересно, как можно реализовать вывод всех файлов, которые есть в данной директории? Например, одного формата? Ибо сейчас, при...

Поиск всех файлов - C++
Здравствуйте Задача кода найти все файлы в папке,для их дальнейшего использования Код такой: #define _WIN32_WINNT 0x0400 ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
15
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru