1

I've been given the following code:

int _tmain(int argc, _TCHAR* argv[]) {
    _finddata_t dirEntry;
    intptr_t dirHandle;
    dirHandle = _findfirst("C:/*", &dirEntry);
    int res = (int)dirHandle;
    while(res != -1) {
        cout << dirEntry.name << endl;
        res = _findnext(dirHandle, &dirEntry);
    }
    _findclose(dirHandle);
    cin.get();
   return (0);
}

what this does is printing the name of everything that the given directory (C:) contains. Now I have to make this print out the name of everything in the subdirectories (if there are any) as well. I've got this so far:

int _tmain(int argc, _TCHAR* argv[]) {
    _finddata_t dirEntry;
    intptr_t dirHandle;
    dirHandle = _findfirst(argv[1], &dirEntry);
    vector<string> dirArray;
    int res = (int)dirHandle;
    unsigned int attribT;
    while (res != -1) {
        cout << dirEntry.name << endl;
        res = _findnext(dirHandle, &dirEntry);
        attribT = (dirEntry.attrib >> 4) & 1; //put the fifth bit into a temporary variable
//the fifth bit of attrib says if the current object that the _finddata instance contains is a folder.
        if (attribT) { //if it is indeed a folder, continue (has been tested and confirmed already)
            dirArray.push_back(dirEntry.name);
            cout << "Pass" << endl;
            //res = _findfirst(dirEntry.name, &dirEntry); //needs to get a variable which is the dirEntry.name combined with the directory specified in argv[1].
    }
}
_findclose(dirHandle);
std::cin.get();
return (0);

}

Now I'm not asking for the whole solution (I want to be able to do it on my own) but there is just this one thing I can't get my head around which is the TCHAR* argv. I know argv[1] contains what I put in my project properties under "command arguments", and right now this contains the directory I want to test my application in (C:/users/name/New folder/*), which contains some folders with subfolders and some random files. The argv[1] currently gives the following error:

Error: argument of type "_TCHAR*" is incompatible with parameter of type "const char *"

Now I've googled for the TCHAR and I understand it is either a wchar_t* or a char* depending on using Unicode character set or multi-byte character set (I'm currently using Unicode). I also understand converting is a massive pain. So what I'm asking is: how can I best go around this with the _TCHAR and _findfirst parameter?

I'm planning to concat the dirEntry.name to the argv[1] as well as concatenating a "*" on the end, and using this in another _findfirst. Any comments on my code are appreciated as well since I'm still learning C++.

Arrrow
  • 542
  • 5
  • 21

2 Answers2

2

See here: _findfirst is for multibyte strings while _wfindfirst is for wide characters. If you use TCHAR in your code then use _tfindfirst (macro) which will resolve to _findfirst on non UNICODE, and _wfindfirst on UNICODE builds.

Also instead of _finddata_t use _tfinddata_t which will also resolve to correct structure depending on UNICODE config.

Another thing is that you should use also correct literal, _T("C:/*") will be L"C:/*" on UNICODE build, and "C:/*" otherwise. If you know you are building with UNICODE defined, then use std::vector<std::wstring>.

btw. Visual Studio by default will create project with UNICODE, you may use only wide versions of functions like _wfindfirst as there is no good reason to build non UNICODE projects.

TCHAR and I understand it is either a wchar_t* or a char* depending on using UTF-8 character set or multi-byte character set (I'm currently using UTF-8).

this is wrong, in UNICODE windows apis uses UTF-16. sizeof(wchar_t)==2.

marcinj
  • 48,511
  • 9
  • 79
  • 100
  • So it is either change to _tfindfirst/_tfinddata_t or get rid of the TCHAR completely? – Arrrow Apr 28 '16 at 17:07
  • Visual Studio will generate code using TCHAR.h so to stay consistent its better to use TCHAR.h. Those mapping you may find here: https://msdn.microsoft.com/en-us/library/szdfzttz.aspx. But in your code you may use wide versions of functions - code will compile. I personally use TCHAR.h. – marcinj Apr 28 '16 at 17:13
  • @Arrrow actually your code should "magically" start working once you change in project settings: General->Character Set to 'Use Multi-Byte Character Set'. But I suggest you stay with UNICODE and fix your code. – marcinj Apr 28 '16 at 17:42
1

Use this simple typedef:

typedef std::basic_string<TCHAR> TCharString;

Then use TCharString wherever you were using std::string, such as here:

vector<TCharString> dirArray;

See here for information on std::basic_string.

PaulMcKenzie
  • 34,698
  • 4
  • 24
  • 45