Hi,

I've been given the following task:

1. Read some .h header files from a few different folder in different directories.
2. Extract only the functions in the files and store all of them into a single text file.
3. Repeat the step 1 and 2 again but extract info from different files and store them in
another different text file.
4. Compare the functions in the text files. (Both the function name and their parameters)


I'm using the function fopen() to open the file and have to specify the path for each of the file one by one (there are more than 200 files!). Is there any way for me to automatically browse through all the files in a specific folder then proceed to another? Some suggest me to include the "dirent.h" header but it show ""fatal error C1083: Cannot open include file: 'dirent.h': No such file or directory".

The Step 2 i'm using string to read the char in the files and store them in string which are later on copy into a List.

Hi,

I'm still struggling to scan all the directories of the files. Tried to use the FindFirstFile() and FindNextFile() and the FindData() and PathAppend(). But having problem to understand the variuos type of data type i havent seen before such as TCHAR LPTSTR LPCTSTR and etc. Any refference that might help? Or can you please show me some example?

Thanks.

Hi,

  1. This is the code i get some where online. Why i get an error message stating that " error C3861: '_T': identifier not found"?

  2. and where actually i should place the wildcard for me to search files of certain type (for exp: .h)?

  3. Sorry if i ask any stupid question cause i'm still new in C++ programming.

-----

#include <iosteream>
#include <Shlwapi.h> // for PathAppend()
using namespace std;

void EnumerateFolderFS(LPCTSTR path)
{
   TCHAR searchPath[MAX_PATH];
   // a wildcard needs to be added to the end of the path, e.g. "C:\*"
   lstrcpy(searchPath, path);
   PathAppend(searchPath, _T("*")); // defined in shell lightweight API (v4.71)

   WIN32_FIND_DATA ffd; // file information struct
   HANDLE sh = FindFirstFile(searchPath, &ffd);
   if(INVALID_HANDLE_VALUE == sh) return; // not a proper path i guess

   // enumerate all items; NOTE: FindFirstFile has already got info for an item
   do {
      cout << "Name = " << ffd.cFileName << endl;
      cout << "Type = " << ( (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
                             ? "dir\n" : "file\n" );
      cout << "Size = " << ffd.nFileSizeLow << endl;
   } while (FindNextFile(sh, &ffd));

   FindClose(sh);
}

Edited 3 Years Ago by Dani: Formatting fixed

>>This is the code i get some where online. Why i get an error message stating that " error C3861: '_T': identifier not found"?

You have to include tchar.h

>>2. and where actually i should place the wildcard for me to search files of certain type (for exp: .h)?

In the FindFirst() function call. Unless you want UNICODE support I'd replace TCHAR and _T macros to make the code more readable.

char searchPath[MAX_PATH];
strcpy(searchPath, "c:\\*.h");
...

Hi, Ancient Dragon

Did you try to compile? It will still have syntax errors:

1. 'strcpy' : cannot convert parameter 2 from 'LPCTSTR' to 'const char *'

2. 'PathAppendW' : cannot convert parameter 1 from 'char [260]' to 'LPWSTR'

3. 'FindFirstFileW' : cannot convert parameter 1 from 'char [260]' to 'LPCWSTR'

Do you need to use UNICODE? If not, turn it of, and all your problems will be gone. (as AD mentioned)
If you do need it:
Change this: strcpy(searchPath, "c:\\*.h"); to this: strcpy(searchPath, L"c:\\*.h"); Do the same with all the 'const char *' (== text between " ") and you're done.

>>strcpy(searchPath, L"c:\\*.h");
That doesn't work because strcpy() requires char*, not wchar_t* Instead use _tcscpy() _tcscpy(searchPath, _T("c:\\*.h")); Note that _tcscpy() is a macro defined in tchar.h which translates to either strcpy() when UNICODE is undefined or wcscpy() for UNICODE.

I'm not sure but is it like this?
Anyway what is the letter 'L' for?

#include <iostream>
#include <Shlwapi.h> // for PathAppend()
#include <tchar.h>
using namespace std;

void EnumerateFolderFS(LPCTSTR path)
{
   TCHAR searchPath[MAX_PATH];

   // a wildcard needs to be added to the end of the path, e.g. "C:\*"
   lstrcpy(searchPath, L"C:\\*.h");
   PathAppend(searchPath, _T("*")); // defined in shell lightweight API (v4.71)

   WIN32_FIND_DATA ffd; // file information struct
   HANDLE sh = FindFirstFile(searchPath, &ffd);
   if(INVALID_HANDLE_VALUE == sh) return; // not a proper path i guess

   // enumerate all items; NOTE: FindFirstFile has already got info for an item
   do {
      cout << L"Name = " << ffd.cFileName << endl;
      cout << L"Type = " << ( (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
                             ? L"dir\n" : L"file\n" );
      cout << L"Size = " << ffd.nFileSizeLow << endl;
   } while (FindNextFile(sh, &ffd));

   FindClose(sh);
}

But it still shows three errors:

1. HelloWorld.obj : error LNK2019: unresolved external symbol __imp__PathAppendW@8 referenced in function "void __cdecl EnumerateFolderFS(wchar_t const *)" (?EnumerateFolderFS@@YAXPB_W@Z)

2. MSVCRTD.lib(crtexe.obj) : error LNK2019: unresolved external symbol _main referenced in function ___tmainCRTStartup

3. C:\Documents and Settings\skong3\Desktop\HelloWorld\Debug\HelloWorld.exe : fatal error LNK1120: 2 unresolved externals

you almost have it. PathAppend() is not needed in your example.

void EnumerateFolderFS(LPCTSTR path)
{
   TCHAR searchPath[MAX_PATH];

   // a wildcard needs to be added to the end of the path, e.g. "C:\*"
   lstrcpy(searchPath, _T("C:\\*.h"));
   //PathAppend(searchPath, _T("*")); // defined in shell lightweight API (v4.71)

>>2. MSVCRTD.lib(crtexe.obj) : error LNK2019: unresolved external symbol _main referenced in function ___tmainCRTStartup
You created a console program but coded a windows GUI program using WinMain().

Well, the syntax problem is solved now but nothing happen. The statement <if(INVALID_HANDLE_VALUE == sh)> return a true value which trigger the return.

#include <iostream>
#include <Shlwapi.h> // for PathAppend()
#include <tchar.h>
using namespace std;

void EnumerateFolderFS(LPCTSTR path)
{
   TCHAR searchPath[MAX_PATH];

   // a wildcard needs to be added to the end of the path, e.g. "C:\*"
   lstrcpy(searchPath, path);

   WIN32_FIND_DATA ffd; // file information struct
   HANDLE sh = FindFirstFile(searchPath, &ffd);
   if(INVALID_HANDLE_VALUE == sh) return; // not a proper path i guess

   // enumerate all items; NOTE: FindFirstFile has already got info for an item
   do {
      cout << L"Name = " << ffd.cFileName << endl;
      cout << L"Type = " << ( (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
                             ? L"dir\n" : L"file\n" );
      cout << L"Size = " << ffd.nFileSizeLow << endl;
   } while (FindNextFile(sh, &ffd));

   FindClose(sh);
}

int main()
{
    EnumerateFolderFS(L"C:\\Myfile\\*.h");

    return 0;
}

Edited 3 Years Ago by Dani: Formatting fixed

Ok. What did you use as input (the path)?

btw: GetLastError() can give you additional information on why the function failed.

Hi,

Now i can get the output for the type and size of the files but i cant see the name. The name is display as "0012 FA54". Actually all these don't matter. The important is i need to scan through the folders to get the PATH of the files since i'll need to open the file to read later on.

1. How can i make the file name readable?
2. Is there any way for me to convert the path into string? I can't really append the path (LPCTSTR data type) to the ffd.cFileName (WCHAR data type).
3. I try to use the GetLastError() but fail to include the "windows.h" header.

Here's my code so far:

#include <iostream>
#include <Shlwapi.h> // for PathAppend()
#include <tchar.h>
#include <conio.h>
#include <windows.h>

using namespace std;

void EnumerateFolderFS(LPCTSTR path)
{
   TCHAR searchPath[MAX_PATH];
	
   // a wildcard needs to be added to the end of the path, e.g. "C:\*"
   lstrcpy(searchPath, path);
   //PathAppend(searchPath, _T("*")); // defined in shell lightweight API (v4.71)

   WIN32_FIND_DATA ffd; // file information struct
   HANDLE sh = FindFirstFile(searchPath, &ffd);
   if(INVALID_HANDLE_VALUE == sh) 
   {
	   return; // not a proper path i guess
   }

   
   // enumerate all items; NOTE: FindFirstFile has already got info for an item
   do {
	   cout << "C:\\Documents and Settings\\skong3\\Desktop\\";
      cout << ffd.cFileName << endl;
      cout << "Type = " << ( (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
                             ? "dir\n" : "file\n" );
      cout << "Size = " << ffd.nFileSizeLow << endl << endl;
   } while (FindNextFile(sh, &ffd));


   FindClose(sh);
}

int main()
{
	EnumerateFolderFS(L"C:\\Documents and Settings\\skong3\\Desktop\\*.h");

	getch();    //use this so that the console do not automatically close
	return 0;
}

Thanks.

>>EnumerateFolderFS(L"C:\\Documents and Settings\\skong3
Why are you forcing the string into wchar_t* wide characters? That's what the L does before the string.

Change that line like this and see how it works: EnumerateFolderFS(_TEXT("C:\\Documents and Settings\\skong3\\Desktop\\*.h");") The _TEXT is a macro that make the string either char* or wchar_t* depending on whether you compile your program for UNICODE or not.

Well, it's still the same. The name of the file still show "0012 FA54" .
Any way, I think it will good if i try to understand all those data types first before i try anything else. Never see all that data types before.

>>Never see all that data types before
And you probably won't see them except in windows.h

Here is your program that works on my computer. I changed the path in main() for my computer, and deleted other extraneous/wrong code.

void EnumerateFolderFS(LPCTSTR path)
{
   WIN32_FIND_DATA ffd; // file information struct
   HANDLE sh = FindFirstFile(path, &ffd);
   if(INVALID_HANDLE_VALUE == sh) 
   {
	   return; // not a proper path i guess
   }

   
   // enumerate all items; NOTE: FindFirstFile has already got info for an item
   do {
      cout << ffd.cFileName << endl;
      cout << "Type = " << ( (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
                             ? "dir\n" : "file\n" );
      cout << "Size = " << ffd.nFileSizeLow << "\n\n";
   } while (FindNextFile(sh, &ffd));


   FindClose(sh);
}

int main()
{
	EnumerateFolderFS(_TEXT("D:\\Program Files\\Microsoft Visual Studio 9.0\\VC\\include\\*.h"));

	cin.get();
	return 0;
}

I tried copy the whole piece of code just modifying the path in main() as below: EnumerateFolderFS(_TEXT("C:\\Program Files\\Microsoft Visual Studio 8\\VC\\include\\*.h")); No syntax error and warning but the file name show "0012 FC64" instead.

Hi,

The file name is not readable is it because my ffd.cFileName is in WCHAR data type? I found in another forum. Something related to windows programming. It mention that his ffd.filename is in TCHAR data type. Trt to cast it to TCHAR but only numbers are displayed. Try to cast the ffd.filename into (const char *) as well. But i can only get the first letter of the file name. Which means?

You can not cast wchar_t* to char* because wchar_t data type is normally (but not always) a short int (2 bytes). On *nix machines wchar_t is a long int (4 bytes). Here is one way to make the conversion

do {
       char temp[_MAX_PATH]; // _MAX_PATH is defined as 255
       size_t nconv = 0;
       wcstombs_s(&nconv, temp,_MAX_PATH,ffd.cFileName, wcslen(ffd.cFileName)+1);
       //cout << ffd.cFileName << endl;
       cout << temp << "\n"; 
      cout << "Type = " << ( (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
                             ? "dir\n" : "file\n" );
      cout << "Size = " << ffd.nFileSizeLow << "\n\n";
   } while (FindNextFile(sh, &ffd));
Comments
Knowledgeable
This question has already been answered. Start a new discussion instead.