Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

FindFirstFile matching regexp AND directories

253 views
Skip to first unread message

Denis Miletic

unread,
Mar 3, 2003, 1:44:55 AM3/3/03
to
I'll get right to the point, here is what I have:

void ParseDirectoryTree(
char *Path,
char *MatchFiles,
void (*ProcessFile)(char *Path, WIN32_FIND_DATA *FileData))
{
WIN32_FIND_DATA FileData;
HANDLE FileHandle;
char FullPath[MAX_PATH];
char SubDirPath[MAX_PATH];

sprintf(FullPath, "%s\\%s", Path, MatchFiles);
FileHandle = FindFirstFile(FullPath, &FileData);

if (FileHandle != INVALID_HANDLE_VALUE)
{
do
{
if (FileData.dwFileAttributes ^ FILE_ATTRIBUTE_DIRECTORY)
{
(*ProcessFile)(Path, &FileData);
}
}
while (FindNextFile(FileHandle, &FileData));
FindClose(FileHandle);
}

sprintf(FullPath, "%s\\*.*", Path);
FileHandle = FindFirstFile(FullPath, &FileData);

if (FileHandle != INVALID_HANDLE_VALUE)
{
do
{
if (FileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
if (strcmp(FileData.cFileName, ".") != 0
&& strcmp(FileData.cFileName, "..") != 0)
{
sprintf(SubDirPath, "%s\\%s", Path, FileData.cFileName);
ParseDirectoryTree(SubDirPath, MatchFiles, ProcessFile);
}
}
}
while (FindNextFile(FileHandle, &FileData));
FindClose(FileHandle);
}
}

I don't like the fact that I'm going through all the files twice, so I
was wondering what are my other possibilities (other than using external
regexp library, or hacking up my own). So is there a way to make
FindFirstFile() search files that match a given pattern (say *.c)
AND directories that match any pattern (*.*)? If not is there a
function that would match simple regexp patterns for two strings,
similar to the way FindFirstFile() does it? Cheers.

Boris Dynin

unread,
Mar 3, 2003, 3:58:57 PM3/3/03
to
Hi,

Actually, it's pretty easy to write a basic regexp processor: it's a finite
state machine with just a few states.
As a matter of fact I wrote such a program some time ago. Here it's in case
you are interested.
Please notice that the code below WAS NOT thoroughly tested.

Boris

MAIN.CPP>>>>>>>>>>>>>>>>>>>>

#include <stdlib.h>
#include <stdio.h>

#include "regexp.h"

void Usage()
{
printf("Usage: REGEXP.EXE regexpStr filenameStr\n");
exit(2);
}
void main(int argc, char *argv[])
{
if ( argc != 3 )
{
Usage();
}

bool bMatch = MatchRegExp(argv[1],argv[2]);

printf(bMatch ? "Match\n" : "No match\n");
}

<<<<<<<MAIN.CPP

REGEXP.H>>>>>>>>>>>>>>>>
/*
Handles regular expressions like: aaa*bbb?ccc.ddd.fff

The wildcards are:
* - any char sequence of length>=0
? - any single character
For simplicity, wildcard chars aren't allowed to come back to back:
for example, a**b or a*?b aren't allowed.
*/


bool MatchRegExp
(
const char* strRegExp /*regexp string*/,
const char* strFilename /*filename string*/
);
<<<<<<<<<<<<<<REGEXP.H

REGEXP.CPP>>>>>>>>>>>>>>>>
enum RGState
{
e_inAsterisk,
e_inQuestionMark,
e_inPlainText,
e_error,
e_match
};

bool MatchRegExp
(
const char* strRegExp /*regexp string*/,
const char* strFilename /*filename string*/
)
{
RGState state = e_inPlainText;
int idxCharRegExp = 0;
int idxCharFileName = 0;
while (state != e_error && state != e_match)
{
switch (state)
{
case e_inPlainText:
if ( strFilename[idxCharFileName] == '\0' &&
( strRegExp[idxCharRegExp] == '\0' ||
strRegExp[idxCharRegExp] == '*' &&
strRegExp[idxCharRegExp+1] == '\0' ) )
{
state = e_match;
}
else
{
switch (strRegExp[idxCharRegExp])
{
case '\0':
state = e_error;
break;
case '*':
state = e_inAsterisk;
break;
case '?':
state = e_inQuestionMark;
break;
default:
if ( strRegExp[idxCharRegExp] == strFilename[idxCharFileName] )
{ // match so far
idxCharRegExp++;
idxCharFileName++;
}
else
{ // no match
state = e_error;
break;
}
break;
}; // switch ...
} // if ...
break;

case e_inAsterisk:
if ( strRegExp[idxCharRegExp+1] == '\0' &&
strFilename[idxCharFileName] == '\0' )
{
state = e_match;
}
else if ( strRegExp[idxCharRegExp+1] == strFilename[idxCharFileName] )
{
state = e_inPlainText;
idxCharRegExp++;
}
else
{
idxCharFileName++;
}
break;

case e_inQuestionMark:
if ( strRegExp[idxCharRegExp+1] == '\0' &&
strFilename[idxCharFileName] == '\0' )
{
state = e_match;
}
else
{
state = e_inPlainText;
idxCharRegExp++;
idxCharFileName++;
}
break;
}; // switch ...
} // while ...

return (state == e_match);
}


<<<<<<<<<<<<<<REGEXP.CPP


"Denis Miletic" <denisM...@zg.hinet.hr> wrote in message
news:MPG.18cd1851d...@news.hinet.hr...

0 new messages