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. Но если нет, то и на других языках пойдет.
Доброго времени суток 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. Это ещё проще, так как это можно сделать визуально, перетягивая соответственные элементы управления.
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. Код взят из инета. Ссылки нема(
vBulletin v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.