Войти

Показать полную графическую версию : Поиск текста в файлах


student_po
12-08-2009, 11:46
Доброго времени суток. В институте дали задания написать программу, которая должна искать текст в файлах (типа поиска в Windows). Но искать надо несколько строк сразу, в форматах doc, rtf, txt, и все это в графическом режиме.
Помогите с созданием GUI. Просто в C++ новичок. Написать cpp это ладно, а здесь ничего не получается.

Вот набросок (поиска файлов).

#include <iostream.h>
#include <windows.h>
#include<fstream.h>
#include<string.h>
#include<stdio.h>
#define rz 100
main()
{
char path[MAX_PATH],mask[MAX_PATH],ch,line [rz],stxt[MAX_PATH],files[MAX_PATH];
cout<<"Search dir:";
cin.getline(path,260,'\n');
cout<<"Search mask:";
cin.getline(mask,260,'\n');
cout<<"Search:";
cin.getline(stxt,260,'\n');
//Sf
WIN32_FIND_DATA file;
HANDLE hfile;
char fpath[MAX_PATH];
strcpy(fpath,path);
strcat(fpath,"\\");
SetCurrentDirectory(fpath);
strcat(fpath,mask);
hfile=FindFirstFile(fpath,&file);
if(hfile!=INVALID_HANDLE_VALUE)
{
do
{
//St
strcpy(files,file.cFileName);
fstream fo;
fo.open (file.cFileName,ios::in);
while(fo.get(ch))
{
fo.get(line,rz);
if ((strstr(line,stxt))!=NULL)
{
// cout<<line<<'\n';
strcpy(files,file.cFileName);
// cout<<file.cFileName<<'\n';
cout<<files<<'\n';
break;
}
}
cout<<'\n';
fo.close();
}
while(FindNextFile(hfile,&file)!=0);
FindClose(hfile);
}
//end Sf
return 0;
}
//До кондиции довести напильником!!!

Может у кого есть поправки. Или сама программа. Заранее спасибо всем.

P.S. Хочется на Visual C++ 6 и выше до 9. Но если нет, то и на других языках пойдет.

Admiral
12-08-2009, 23:42
Доброго времени суток student_po, не совсем понятно, какого масштаба задание: практика, лаба, расчётно-графическая, другое?
Меня смущает в перечисленных форматах наличие doc и rtf, так как для последних встроенных возможностей языка будет не достаточно. Придётся писать довольно массивный код, дабы получить возможность без проблемного чтения данных файлов (по сути свой Word/WordPad), чего не скажешь про txt.
В технологии поиска можно предусмотреть использование ключевых слов "и" "или" и т.д. или без таких, опираясь на спец символы, вводящие в окно поиска, дабы искать по несколько строк сразу.

Для построения GUI в предполагаемых средствах программирования Visual C++ 6 и выше до 9 во всех этих версия можно построить, используя или чистый Win32 Api, или библиотеку классов MFC.
В версиях 7.Х и выше возможно так же использовать и WinForms (который использует .Net Framework), а начиная с 8й версии и выше можно и Windows Presentation Foundation (тоже использует .Net Framework).
Если окно нужно строить используя WIN32 API, то вот #include <windows.h>
#include <commctrl.h>

#pragma comment(lib, "comctl32.lib")

enum {ID_BUTTON};

HWND hWndListView;

LRESULT CALLBACK WindowFunc(HWND hWnd,UINT message,
WPARAM wParam,LPARAM lParam)
{
switch (message)
{
case WM_CREATE:
CreateWindow(
TEXT("STATIC"),
TEXT("Search by any or all of the criterial below."),
WS_CHILD | WS_VISIBLE,
10,
10,
270,
20,
hWnd,
NULL,
NULL,
NULL);
CreateWindow(
TEXT("STATIC"),
TEXT("All or part of the file name:"),
WS_CHILD | WS_VISIBLE,
10,
45,
250,
20,
hWnd,
NULL,
NULL,
NULL);
CreateWindow(
TEXT("EDIT"),
NULL,
WS_CHILD | WS_VISIBLE | ES_LEFT | ES_MULTILINE ,
10,
65,
270,
20,
hWnd,
NULL,
NULL,
NULL);
CreateWindow(
TEXT("STATIC"),
TEXT("A word or phase in the file:"),
WS_CHILD | WS_VISIBLE,
10,
85,
250,
20,
hWnd,
NULL,
NULL,
NULL);
CreateWindow(
TEXT("EDIT"),
NULL,
WS_CHILD | WS_VISIBLE | ES_LEFT | ES_MULTILINE ,
10,
105,
270,
20,
hWnd,
NULL,
NULL,
NULL);
CreateWindow(
TEXT("STATIC"),
TEXT("Look in:"),
WS_CHILD | WS_VISIBLE,
10,
125,
100,
20,
hWnd,
NULL,
NULL,
NULL);
CreateWindow(
TEXT("EDIT"),
NULL,
WS_CHILD | WS_VISIBLE | ES_LEFT | ES_MULTILINE ,
10,
145,
270,
20,
hWnd,
NULL,
NULL,
NULL);
CreateWindow(
TEXT("BUTTON"),
TEXT("Search"),
BS_PUSHBUTTON | WS_VISIBLE | WS_CHILD | WS_TABSTOP,
200,
200,
80,
30,
hWnd,
NULL,
NULL,
NULL);
break;

case WM_COMMAND:
switch(wParam)
{
case ID_BUTTON:
//MessageBox(NULL, TEXT("Search Results"), TEXT("About"), MB_ICONASTERISK | MB_OK);
ShowWindow(hWndListView,SW_SHOW);
break;
}
break;

case WM_DESTROY:
PostQuitMessage (0);
break;

default:
return DefWindowProc (hWnd,message,wParam,lParam);
}
return 0;
}

int WINAPI WinMain (HINSTANCE hThisInst,HINSTANCE hPrevInst,
LPSTR lpszArgs,int nWinMode)
{
WNDCLASS wcl;
wcl.style = 0;
wcl.lpfnWndProc = WindowFunc;
wcl.cbClsExtra = 0;
wcl.cbWndExtra = 0;
wcl.hInstance = hThisInst;
wcl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
wcl.hCursor = LoadCursor (NULL, IDC_ARROW);
wcl.hbrBackground = (HBRUSH)COLOR_WINDOW;
wcl.lpszMenuName = NULL;
wcl.lpszClassName = TEXT("Search");

if (!RegisterClass (&wcl))
return -1;
HWND hWnd = CreateWindowEx (WS_EX_TOPMOST,
wcl.lpszClassName,
TEXT("Search Results"),
WS_TILEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
HWND_DESKTOP,
NULL,
hThisInst,
NULL);
if (!hWnd)
return -1;

ShowWindow (hWnd,nWinMode);
UpdateWindow (hWnd);
MSG msg;

hWndListView = CreateWindow(
WC_LISTVIEW,
NULL,
WS_CHILD | LVS_REPORT | LVS_EDITLABELS,
300,
10,
250,
220,
hWnd,
NULL,
NULL,
NULL);
#ifdef UNICODE
TCHAR szColumnHeader[3][12] = {TEXT("Name"), TEXT("In Folder"), TEXT("Size")};
#else
char szColumnHeader[3][12] = {TEXT("Name"), TEXT("In Folder"), TEXT("Size")};
#endif
int index;
int iiWidth[3];
LV_COLUMN lvC;

ListView_SetExtendedListViewStyle(hWndListView, LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES);

iiWidth[0] = 60;
iiWidth[1] = 100;
iiWidth[2] = 400;

lvC.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
lvC.fmt = LVCFMT_LEFT;

for(index = 0; index < 3; index++)
{
lvC.iSubItem = index;
lvC.cx = iiWidth[index];
lvC.pszText = szColumnHeader[index];
ListView_InsertColumn(hWndListView,index,&lvC);
}

while(GetMessage(&msg, NULL, 0, 0) > 0)
{
TranslateMessage (&msg);
DispatchMessage (&msg);
}
return msg.wParam;
}По нажатию на кнопку Поиск ("Search") появляется окно с предполагаемым результатом. Кроме того в коде не совсем корректно создаётся собственно это окно (в примере моветон), так как по хорошему его создание и определение ListView_SetExtendedListViewStyle нужно было размещать в case WM_CREATE: а не так как здесь после MSG msg; перед while(GetMessage(&msg, NULL, 0, 0) > 0). На практике между этими двумя строками ничего не должно быть.
Я размесил эго создание между этим двумя строчками, так как хотел продемонстрировать его включение по кнопке. А как включать это окно, если оно расположено на своём месте в case WM_CREATE: я показать не готов (кнопка в case WM_COMMAND: получает не инициализированный hWndListView), возможно другие участники смогу подсказать как это сделать корректно.
Если же окно нужно строить не на Win32 API, тогда, учитывая что версия MSVC от 6 до 9, его нужно строить с использованием библиотек MFC. Это ещё проще, так как это можно сделать визуально, перетягивая соответственные элементы управления.

student_po
23-08-2009, 19:55
Интересный текст :up . Есть над чем задуматся и поработать. Ну в обшем спасибо за программу и поянительное дополнение. :)

ganselo
23-08-2009, 21:13
int SearchText (LPCSTR lpFilename,
LPCSTR lpTextToFind,
bool bCaseSens,
bool bContinueSearch,
void FunctionToCall(HANDLE hFile, DWORD dwOffset, DWORD dwSize))
{
//для начала выясним, скок ж букв в слове, которое найти надо
unsigned int uTextLength = (int)strlen(lpTextToFind);
//и так приступим :) сначала нам надо открыть файл для поиска ;)
HANDLE hFile = CreateFile ( lpFilename, //Это имя нашего файла
GENERIC_READ|GENERIC_WRITE, //Мы его хотим читать и писать
FILE_SHARE_READ, //Разрешим другим прогам наш файл читать
NULL, //И никаких атрибутов безопасности нам не надо
OPEN_EXISTING, //Тек-с...надо открыть существующий файл
//и если этого сделать не выйдет, то вывалится с ошибкой ;)
FILE_FLAG_SEQUENTIAL_SCAN, //А это такой ужжжас ;) Скажем операционке, что хотим
//читать файл от начала и до конца последовательно;)
NULL); //Ну и всяких темплейтов на не надо
//открылся ли файл?
if (hFile == INVALID_HANDLE_VALUE)
{
DWORD dwError = GetLastError ();
AfxMessageBox ("Оппа...Файл-то и не открылся :(");
return 0; //не открылся, ну и фиг с ним, выходим из функции
}

//Терь придумаем небольшую процедурку для поиска текста ;)
char* pszBuffer = new char[uTextLength];
memset (pszBuffer, 0, uTextLength);
DWORD dwBytesRead = 0;
DWORD dwOffset = 0;
unsigned int uCount = 0;
while (dwOffset + uTextLength <= GetFileSize (hFile, NULL))
{
SetFilePointer (hFile, dwOffset, NULL, FILE_BEGIN);
if (ReadFile (hFile, pszBuffer, uTextLength, &dwBytesRead, NULL))
{
if (!bCaseSens) {
if (!memcmp (&pszBuffer[0], &lpTextToFind[0], uTextLength))
if (!bContinueSearch) {
FunctionToCall (hFile, dwOffset, uTextLength);
return 1;
} else {
FunctionToCall (hFile, dwOffset, uTextLength);
uCount++;
}
} else if (!memicmp (&pszBuffer[0], &lpTextToFind[0], uTextLength)) {
if (!bContinueSearch) {
FunctionToCall (hFile, dwOffset, uTextLength);
return 1;
} else {
FunctionToCall (hFile, dwOffset, uTextLength);
uCount++;
}
}
}
dwOffset++;
}

delete [] pszBuffer ;
CloseHandle (hFile); //закрываем наш файлик ;)

return uCount; //Возвращаем количество найденного %)
}

void Funcs (HANDLE hFile, DWORD dwOffset, DWORD dwSize)
{
static char* pszTest = new char [dwSize];
memset (pszTest, 64, dwSize);
DWORD dwBytesWritten;
SetFilePointer (hFile, dwOffset, NULL, FILE_BEGIN);
WriteFile (hFile, pszTest, dwSize, &dwBytesWritten, NULL);
delete [] pszTest
}

void CMFcDlg::OnBnClickedButton1()
{
SearchText ("c:\\123.TxT", "Lord_Baa", true, 0, Funcs);
}


lpFilename - это имя файлика, в котором искать бум.
lpTextToFind - текст поиска.
bool bCaseSend - поиск с учетом регистра букв или без онного...
bool bContinueSearch - будет ли наш поиск продолжен после того, как нашли одно слово
void FunctionToCall(HANDLE hFile, DWORD dwOffset, DWORD dwSize) - будит вызвана если текст найден.
в неё передадим дескриптор файла(hFile), смещение от начала файла до начала слова(dwOffset), и длина слова(dwSize)

P.S. Код взят из инета. Ссылки нема(

Serega_Yaroslavl
24-08-2009, 02:50
Cмотря в какой среде разработки нада написать приложение. В том же Borland C++ Builder есть компонент RichEdit который избавляет от рутийной работы с ртф и дос структурой данных

student_po
04-09-2009, 15:01
Cмотря в какой среде разработки нада написать приложение. »
Visual C++ 6 :)

Admiral
04-09-2009, 23:33
student_po, там тоже возможно использования данного компонента
Using Rich Edit Controls (http://msdn.microsoft.com/en-us/library/bb787877(VS.85).aspx)
Пример создания (http://forum.sources.ru/index.php?showtopic=219764) по-русски.




© OSzone.net 2001-2012