Thread: good habits - TCHAR, unicode, etc.

  1. #1
    Registered User
    Join Date
    Feb 2012
    Posts
    44

    good habits - TCHAR, unicode, etc.

    Since I'm very new to all this, what would be useful for me?

    Currently, as pointed out in another thread, the VS C++ compiler has UNICODE as the default.

    I'm struggling with the whole mindset of thinking on pairs of bytes vs. single bytes.

    The programs I'm writing are mostly for myself but occasionally they might be used by just a few people via other forums.

    Should I go through the learning curve to fumble with TCHAR? Or, should I simply learn for a bit using CHAR for everything (turn UNICODE compile option OFF)?

    Any other tips you have regarding the best way for me to proceed?

  2. #2
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    You don't really need to concern yourself whether you're using wide char or simply char, so there is no point in learning to use "both."
    Use TCHAR instead of char or wchar_t. Use _T("txt") instead of "txt" or L"txt". In the Windows API, use the base function names (ie, OutputDebugString instead of OutputDebugStringA or OutputDebugStringW).
    For the standard library in C and C++, you may have to create macros or typedefs for some "wide char neutral" functions that will call the right ones depending on what you're using.

    Take heed that the standard library's support for wide chars can be rather limited. It sucks, I know. Welcome to the real world.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  3. #3
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    >> Should I go through the learning curve to fumble with TCHAR?
    I would understand what they are and how they work. But don't use them.

    For Win32 programming, just use WCHAR/wchar_t/L""/etc... for strings.

    More rationale here: To _T() or not to _T()? - CodeGuru Forums

    gg

  4. #4
    Registered User
    Join Date
    Feb 2012
    Posts
    44
    Codeplug, are you saying just always WCHAR for every single string (whether related to an API or even if just one's own strings in their program)?

    How about this. For any Win API calls or storage related to API calls, use TCHAR.

    For other strings I might use, would it be confusing to use regular CHAR?

    The other problem is I'm not sure how to convert TCHAR to CHAR (there's some TtoC or functions like that. So, I've been forced to make API-related strings as TCHAR.

    Seriously. I really value everyone's opinion and wish to not box myself in a corner with bad habits.

    FTR, I do understand TCHAR, WCHAR and DBCS, etc. I just think in bytes since I've been programming 30 years....

  5. #5
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    >> ... are you saying just always WCHAR for every single string (whether related to an API or even if just one's own strings in their program)?
    Yeah. Or just don't bother with TCHAR's.

    >> How about this. For any Win API calls or storage related to API calls, use TCHAR.
    Why? What's the benefit?

    >> The other problem is I'm not sure how to convert TCHAR to CHAR
    You would use pre-processor conditionals and handle both the TCHAR=CHAR and TCHAR=WCHAR cases individually. There are ATL/MFC conversion classes too (if using a non-Express version of Visual Studio).

    >> ... I've been forced to make API-related strings as TCHAR.
    Why has this been forced?

    gg

  6. #6
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    It depends on how you want characters and strings to be represented, as far as your code is concerned. It also comes down to how you structure and organise (i.e. architect) your code. Generally, I would assert that code should be structured in a way that ensures system-specific calls are highly localised rather than being entwined throughout your business logic.

    In VC++, a wchar_t and a unicode character representation are equivalent.

    If you need to use narrow chars internally, then do so. And convert to wide (unicode) strings before passing those strings to win32 API or other API functions that assume unicode. It is not difficult to convert a char to a wchar_t and a std::string to a std::wstring (and back).

    If you need to use wide characters internally, then do so. Unicode characters and strings will not need any conversion before being passed to win32 API or other API functions that assume unicode. They will need conversion if being passed to any functions that specifically assume narrow characters.

    It comes down to what criteria you use to decide whether to work with narrow (char) or wide (wchar_t) internally. If the internals of your program need to be internationalisation-aware (for example, you load prompt strings from a file, and manipulate them before passing onto win32 API function) better to work with wchar_t. If not, then using wide characters is optional .... the tradeoff is more about memory usage of wide versus narrow strings, and possibly difficulty of understanding for the programmer. Those trade-offs are relatively minor, unless the code is structured poorly.

    The conversion before passing to a win32 API function should be trivial (apart from calling the right API function, the mechanics are just converting char to/from wchar_t and string to/from wstring which, as I mentioned above, are not difficult). The worst case is that you need to write thin wrappers for some win32 API functions.

    The approach I suggest also requires minimal conversion if porting code to or from other operating systems. The only code that needs adaptation is that specific to the host system (for example, the win32 API functions on windows which, hopefully, will be only called by thin wrappers rather than being used directly by your "business logic" code).

    As such, I would hope never to see _T() or TCHAR used in most of the "business logic" code which, I assert, should be written in a portable manner (using the standard C++ library, etc). If _T or TCHAR are used, it would be in code that is specifically calling some Microsoft-specific functions (win32, ATL, MFC, or whatever). In other words, within the "thin wrappers".

    In this, although I've expressed the details a little differently, I largely agree with CodePlug.
    Last edited by grumpy; 02-05-2012 at 01:49 AM.
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  7. #7
    Registered User
    Join Date
    Feb 2012
    Posts
    44
    Still pretty bewildered.

    If I'm reading data from a regular .txt file, can that data be converted to TCHAR on-the-fly?

    My "force" issue was trying to figure out how to compare TCHAR to CHAR? I guess I'll have to write all the conversion and compare functions myself (no biggie). I googled and I can't find any of the header files referenced in examples of some built-in functions for converting back and forth.

    I'm finding, again, that 95% of the time spent in writing C code is fumbling about with all these non-programming (end-result) issues. Very, very unproductive. I'm just so used to reading Principles of Operations manuals for instruction sets that there's no issues at all like this. An instruction does what it says it does and the rest is up to you.

    I'm also amazed any of this Windows-related code is manageable/maintainable. I'd hate to see what commercial code looks like.

    I'm also using C (for now since I just started).
    Last edited by jlewand; 02-05-2012 at 09:43 AM.

  8. #8
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by jlewand View Post
    If I'm reading data from a regular .txt file, can that data be converted to TCHAR on-the-fly?
    No. See below.

    My "force" issue was trying to figure out how to compare TCHAR to CHAR?
    You don't. The point of TCHAR is to be narrow/wide char neutral. That is, your project will be able to compile with both options.
    TCHAR is simply a macro that changes to char or wchar_t depending on settings. That is all.
    No conversions are done.

    Hence, it is an error to compare TCHAR to either wchar_t or char, because that breaks your narrow/wide neutrality. If you do that, then you have to choose whether to go narrow or wide.
    Avoid this.

    I guess I'll have to write all the conversion and compare functions myself (no biggie). I googled and I can't find any of the header files referenced in examples of some built-in functions for converting back and forth.
    There ware built-in functions for this. The best thing you can do is simply use a proper library, however.
    Googling wchar to char or ascii to unicode (or the reverse) will probably yield a lot of results.

    I'm also amazed any of this Windows-related code is manageable/maintainable. I'd hate to see commercial code.
    Win32 code is unmanageable. Don't use it. Whatever language you use, get a proper library for GUI, and use the standard library for everything else.

    I'm also using C (for now since I just started).
    I am not going to question what language you use, but since you felt the need to mention that, I am going to mention that you should think if you really need C.
    C is the lowest level of programming languages (except for assembly), which really makes writing programs unproductive.
    There is a reason why C still exists, and its primary use is still for hardware and low-level stuff like drivers. If you aren't writing such things, then I strongly recommend you evaluate other languages, such as C++, Java, C#, etc.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  9. #9
    Registered User
    Join Date
    Feb 2012
    Posts
    44
    Elysia, thanks for the comments.

    I meant to say I'd hate to see ANY commercial code for ANY of these languages (C, C#, C++, Java) meaning ANY of those in which Windows is involved in any way. They are so abstract with all these issues as to no longer really be a language. I'm finding it hard to break 30 years of assembler habits.

    To repeat: I could spend hours googling wchar to char conversions (which I did to some degree) but when people show examples, MOST of the time they don't mention what headers are needed. For the ones that DID mention the headers, those are not available in my VS C++ express (latest version).

    Seems 100x easier to roll your own on everything rather than search, find stuff, then have to figure out how to get it to work, rather than just writing the code.

    Once you have a function library fully-built, C is no different than any other language. For example, seasoned assembler programmers have tons of macros that handle all kinds of nuances/details. It's highly productive to write in assembler code ONCE you have those macros all built (which all commercial shops do).
    Last edited by jlewand; 02-05-2012 at 01:04 PM.

  10. #10
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    To repeat: I could spend hours googling wchar to char conversions (which I did to some degree) but when people show examples, MOST of the time they don't mention what headers are needed. For the ones that DID mention the headers, those are not available in my VS C++ express (latest version).
    If you would get an example of those sites, we could point out the missing information.

    Seems 100x easier to roll your own on everything rather than search, find stuff, then have to figure out how to get it to work, rather than just writing the code.
    It's always like that in the beginning, but once you get the hang of it, you begin to love all the high-quality stuff already out there.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  11. #11
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    >> My "force" issue was trying to figure out how to compare TCHAR to CHAR?
    But where does this need to "compare TCHAR to CHAR" come from?

    As you may already know, a TCHAR is just a typedef to char or wchar_t, depending on if UNICODE is defined or not:
    Code:
    #ifdef UNICODE
    typedef wchar_t TCHAR;
    #else
    typedef char TCHAR;
    #endif
    The Microsoft C runtime (MS CRT) also provides function mappings. For example, _tcsclen() maps to either strlen() or wcslen().
    Routine Mappings

    >> If I'm reading data from a regular .txt file, can that data be converted to TCHAR on-the-fly?
    Assuming you have a simple ASCII text file, you could use _fgetts() to read into a TCHAR buffer.

    As Elysia mentions, the goal here is be "narrow/wide char neutral". The link in post #3 describes why/how the need for this facility arose. There is no reason for new code to use TCHAR's. Just call fgets/fgetws, or strlen/wcslen, etc... When using the Win32 API, use wchar_t strings

    >> ... they don't mention what headers are needed.
    The documentation for Visual Studio, MS-CRT, and the Win32 API are all on MSDN. That would be the first place to search.
    MSDN Library

    Another concept to familiarize yourself with is "character encoding". The encoding describes how an array of char's or wchar_t's are interpreted to form glyphs.

    Win32 API's that take narrow strings are expected to be encoded with a Windows codepage. Here's an example codepage: Windows 1252 This is a single-byte character set (SBCS) since it only takes a single byte to encode a single glyph. There are also codepages that take up to 2 bytes per glyph. These are called double-byte character sets (DBCS), like codepage 932 (Shift-JIS). However, documentation often refers to these as "multi-byte character sets", or MBCS. (You may of noticed in the "Routine Mappings" link above, that there are 3 TCHAR function mappings in the MS-CRT: SBCS, MBCS, and UNICODE.)

    The wchar_t encoding in Windows is UTF16, which is a Unicode encoding. Here's a good synopsis on Unicode: What is Unicode?

    Here is a longer, more in-depth reading on character encodings and Unicode: The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!) - Joel on Software

    Here is some information on the encoding of strings from the source code to the execution environment for Microsoft's compiler and GCC: Non-English characters with cout

    That may be information overload, on a tangential subject, but I think it's good to get an early exposure to this stuff, even if the code you write now isn't really concerned with internationalization.

    >> Still pretty bewildered.
    Let's throw around some real code examples, or links to examples you would like explained. Anything you don't quit understand, ask away. This is one of those subjects that isn't easily learned by googling away

    gg

  12. #12
    Registered User
    Join Date
    Feb 2012
    Posts
    44
    I have study the generated assembler to get a handle on this.

    For starters:

    if/while (whatever)

    with NO comparison operator. I would never dream of allowing a programming language construct like that. In assembler, you always compare something TO something (or explicitly test a condition).

    When I see the above in code I'm stealing, I'm always stuck with forcing it to their exact way as I can't modify it without testing every possible scenario of that that if/while might do.

    no code tags as it won't allow me to code block the whole chunk of code....editor bug...


    x = GetLogicalDriveStrings (255, TCHbuff);
    if ( x > 0 ) {
    // get drive type, volume name and volume serial
    *PTCHbuff = *TCHbuff;
    k = 0;
    // max l'volume name found
    do {
    // point to current dl-colon-backslash-0 set
    *TCHbuff = *PTCHbuff;
    f = GetDriveType(TCHbuff);
    if ( f == DRIVE_FIXED ) {
    dlal[dlat][0] = TCHbuff[0];
    dlal[dlat][1] =
    '\0';
    dlay[dlat][0] =
    '\0';
    strcat_s (dlay[dlat],
    "FIXED");
    //
    f = GetVolumeInformation(TCHbuff, TCHvoln, sizeof(TCHvoln), &DWvols,
    NULL, NULL, TCHdir,
    sizeof(TCHdir));
    if ( f == 0 ) {
    printf(
    "ERROR GetVolumeInformation RC %d", f); nl(1);
    exit(1);
    }
    dlavn[dlat][0] =
    '\0';
    _tcscat_s (dlavn[dlat], TCHvoln);
    // track max l'volume name
    y = _tcslen (TCHvoln);
    if ( y > k ) {
    k = y;
    }
    dlai[dlat] = 0;
    dlag[dlat] = 0;
    dlat++;
    // DRIVE_FIXED
    }
    // spin until next 0 byte?
    while (*PTCHbuff++);
    }
    // bool FALSE and PTCHbuff?
    while ( !found && *PTCHbuff);
    }


    The last while is a mystery. It seems the !found is extraneous and unnecessary?

    The 2nd to last while seems to be incrementing a pointer (in this a TCHAR pointer, hence an ADD 2 in the generated assembler) and ALSO checking to see if that pointer is pointing at a \0 byte?
    Last edited by jlewand; 02-05-2012 at 04:45 PM.

  13. #13
    Registered User
    Join Date
    Feb 2012
    Posts
    44
    Another example. I've been getting my winAPI calls to work pretty much the first time (quite lucky). I've got a recursive directory walk that I stole from codeproject.com.
    The code below produces this. I have since figured out that the 2 consecutive bottom while printfs are occurring from recursion.

    You'll also notice I'm checking directory via && 0x10 as the predefined FILE ATTRIBUTES field shows as undefined. What header is it in?


    FrunCB routine address 1392770
    FindFirstFile E:\WindowsImageBackup\*
    dpath E:\WindowsImageBackup\
    NEXT dpath after FNF E:\WindowsImageBackup\
    NEXT file/dir ..
    NEXT dpath bottom while E:\WindowsImageBackup\
    NEXT dpath after FNF E:\WindowsImageBackup\
    NEXT file/dir JIM-GLH_2011-11-06_012348
    NEXT dpath prior E:\WindowsImageBackup\
    NEXT directory
    Frun recurse E:\WindowsImageBackup\JIM-GLH_2011-11-06_012348

    FrunCB routine address 1392790
    FindFirstFile E:\WindowsImageBackup\JIM-GLH_2011-11-06_012348\*
    dpath E:\WindowsImageBackup\JIM-GLH_2011-11-06_012348\
    NEXT dpath after FNF E:\WindowsImageBackup\JIM-GLH_2011-11-06_012348\
    NEXT file/dir ..
    NEXT dpath bottom while E:\WindowsImageBackup\JIM-GLH_2011-11-06_012348\
    NEXT dpath after FNF E:\WindowsImageBackup\JIM-GLH_2011-11-06_012348\
    NEXT file/dir Backup 2011-11-06 012348
    NEXT dpath prior E:\WindowsImageBackup\JIM-GLH_2011-11-06_012348\
    NEXT directory
    Frun recurse E:\WindowsImageBackup\JIM-GLH_2011-11-06_012348\Backup 2011-11-06 012348

    FrunCB routine address 1392790
    FindFirstFile E:\WindowsImageBackup\JIM-GLH_2011-11-06_012348\Backup 2011-11-06 012348\*
    dpath E:\WindowsImageBackup\JIM-GLH_2011-11-06_012348\Backup 2011-11-06 012348\
    NEXT dpath after FNF E:\WindowsImageBackup\JIM-GLH_2011-11-06_012348\Backup 2011-11-06 012348\
    NEXT file/dir ..
    NEXT dpath bottom while E:\WindowsImageBackup\JIM-GLH_2011-11-06_012348\Backup 2011-11-06 012348\
    NEXT dpath after FNF E:\WindowsImageBackup\JIM-GLH_2011-11-06_012348\Backup 2011-11-06 012348\
    NEXT file/dir 8ba1faea-ef34-40e0-a9e1-788ab5618fac_AdditionalFilesc3b9f3c7-5e52-4d5e-8b20-19adc95a34c7.x
    print2 E:\WindowsImageBackup\JIM-GLH_2011-11-06_012348\Backup 2011-11-06 012348\8ba1faea-ef34-40e0-a9e1-
    NEXT dpath after file E:\WindowsImageBackup\JIM-GLH_2011-11-06_012348\Backup 2011-11-06 012348\
    NEXT dpath bottom while E:\WindowsImageBackup\JIM-GLH_2011-11-06_012348\Backup 2011-11-06 012348\
    NEXT dpath after FNF E:\WindowsImageBackup\JIM-GLH_2011-11-06_012348\Backup 2011-11-06 012348\
    NEXT file/dir 8ba1faea-ef34-40e0-a9e1-788ab5618fac_Components.xml
    print2 E:\WindowsImageBackup\JIM-GLH_2011-11-06_012348\Backup 2011-11-06 012348\8ba1faea-ef34-40e0-a9e1-
    NEXT dpath after file E:\WindowsImageBackup\JIM-GLH_2011-11-06_012348\Backup 2011-11-06 012348\
    NEXT dpath bottom while E:\WindowsImageBackup\JIM-GLH_2011-11-06_012348\Backup 2011-11-06 012348\
    NEXT dpath after FNF E:\WindowsImageBackup\JIM-GLH_2011-11-06_012348\Backup 2011-11-06 012348\
    NEXT file/dir 8ba1faea-ef34-40e0-a9e1-788ab5618fac_RegistryExcludes.xml
    print2 E:\WindowsImageBackup\JIM-GLH_2011-11-06_012348\Backup 2011-11-06 012348\8ba1faea-ef34-40e0-a9e1-
    NEXT dpath after file E:\WindowsImageBackup\JIM-GLH_2011-11-06_012348\Backup 2011-11-06 012348\
    NEXT dpath bottom while E:\WindowsImageBackup\JIM-GLH_2011-11-06_012348\Backup 2011-11-06 012348\
    NEXT dpath after FNF E:\WindowsImageBackup\JIM-GLH_2011-11-06_012348\Backup 2011-11-06 012348\
    NEXT file/dir 8ba1faea-ef34-40e0-a9e1-788ab5618fac_Writer4dc3bdd4-ab48-4d07-adb0-3bee2926fd7f.xml
    print2 E:\WindowsImageBackup\JIM-GLH_2011-11-06_012348\Backup 2011-11-06 012348\8ba1faea-ef34-40e0-a9e1-
    NEXT dpath after file E:\WindowsImageBackup\JIM-GLH_2011-11-06_012348\Backup 2011-11-06 012348\
    NEXT dpath bottom while E:\WindowsImageBackup\JIM-GLH_2011-11-06_012348\Backup 2011-11-06 012348\
    NEXT dpath after FNF E:\WindowsImageBackup\JIM-GLH_2011-11-06_012348\Backup 2011-11-06 012348\
    NEXT file/dir 8ba1faea-ef34-40e0-a9e1-788ab5618fac_Writer542da469-d3e1-473c-9f4f-7847f01fc64f.xml
    print2 E:\WindowsImageBackup\JIM-GLH_2011-11-06_012348\Backup 2011-11-06 012348\8ba1faea-ef34-40e0-a9e1-
    NEXT dpath after file E:\WindowsImageBackup\JIM-GLH_2011-11-06_012348\Backup 2011-11-06 012348\
    NEXT dpath bottom while E:\WindowsImageBackup\JIM-GLH_2011-11-06_012348\Backup 2011-11-06 012348\
    NEXT dpath after FNF E:\WindowsImageBackup\JIM-GLH_2011-11-06_012348\Backup 2011-11-06 012348\
    NEXT file/dir 8ba1faea-ef34-40e0-a9e1-788ab5618fac_Writera6ad56c2-b509-4e6c-bb19-49d8f43532f0.xml
    print2 E:\WindowsImageBackup\JIM-GLH_2011-11-06_012348\Backup 2011-11-06 012348\8ba1faea-ef34-40e0-a9e1-
    NEXT dpath after file E:\WindowsImageBackup\JIM-GLH_2011-11-06_012348\Backup 2011-11-06 012348\
    NEXT dpath bottom while E:\WindowsImageBackup\JIM-GLH_2011-11-06_012348\Backup 2011-11-06 012348\
    NEXT dpath after FNF E:\WindowsImageBackup\JIM-GLH_2011-11-06_012348\Backup 2011-11-06 012348\
    NEXT file/dir 8ba1faea-ef34-40e0-a9e1-788ab5618fac_Writerafbab4a2-367d-4d15-a586-71dbb18f8485.xml
    print2 E:\WindowsImageBackup\JIM-GLH_2011-11-06_012348\Backup 2011-11-06 012348\8ba1faea-ef34-40e0-a9e1-
    NEXT dpath after file E:\WindowsImageBackup\JIM-GLH_2011-11-06_012348\Backup 2011-11-06 012348\
    NEXT dpath bottom while E:\WindowsImageBackup\JIM-GLH_2011-11-06_012348\Backup 2011-11-06 012348\
    NEXT dpath after FNF E:\WindowsImageBackup\JIM-GLH_2011-11-06_012348\Backup 2011-11-06 012348\
    NEXT file/dir 8ba1faea-ef34-40e0-a9e1-788ab5618fac_Writerbe000cbe-11fe-4426-9c58-531aa6355fc4.xml
    print2 E:\WindowsImageBackup\JIM-GLH_2011-11-06_012348\Backup 2011-11-06 012348\8ba1faea-ef34-40e0-a9e1-
    NEXT dpath after file E:\WindowsImageBackup\JIM-GLH_2011-11-06_012348\Backup 2011-11-06 012348\
    NEXT dpath bottom while E:\WindowsImageBackup\JIM-GLH_2011-11-06_012348\Backup 2011-11-06 012348\
    NEXT dpath after FNF E:\WindowsImageBackup\JIM-GLH_2011-11-06_012348\Backup 2011-11-06 012348\
    NEXT file/dir 8ba1faea-ef34-40e0-a9e1-788ab5618fac_Writercd3f2362-8bef-46c7-9181-d62844cdc0b2.xml
    print2 E:\WindowsImageBackup\JIM-GLH_2011-11-06_012348\Backup 2011-11-06 012348\8ba1faea-ef34-40e0-a9e1-
    NEXT dpath after file E:\WindowsImageBackup\JIM-GLH_2011-11-06_012348\Backup 2011-11-06 012348\
    NEXT dpath bottom while E:\WindowsImageBackup\JIM-GLH_2011-11-06_012348\Backup 2011-11-06 012348\
    NEXT dpath after FNF E:\WindowsImageBackup\JIM-GLH_2011-11-06_012348\Backup 2011-11-06 012348\
    NEXT file/dir 8ba1faea-ef34-40e0-a9e1-788ab5618fac_Writere8132975-6f93-4464-a53e-1050253ae220.xml
    print2 E:\WindowsImageBackup\JIM-GLH_2011-11-06_012348\Backup 2011-11-06 012348\8ba1faea-ef34-40e0-a9e1-
    NEXT dpath after file E:\WindowsImageBackup\JIM-GLH_2011-11-06_012348\Backup 2011-11-06 012348\
    NEXT dpath bottom while E:\WindowsImageBackup\JIM-GLH_2011-11-06_012348\Backup 2011-11-06 012348\
    NEXT dpath after FNF E:\WindowsImageBackup\JIM-GLH_2011-11-06_012348\Backup 2011-11-06 012348\
    NEXT file/dir 936b54bf-228a-11df-8147-806e6f6e6963.vhd
    print2 E:\WindowsImageBackup\JIM-GLH_2011-11-06_012348\Backup 2011-11-06 012348\936b54bf-228a-11df-8147-
    NEXT dpath after file E:\WindowsImageBackup\JIM-GLH_2011-11-06_012348\Backup 2011-11-06 012348\
    NEXT dpath bottom while E:\WindowsImageBackup\JIM-GLH_2011-11-06_012348\Backup 2011-11-06 012348\
    NEXT dpath after FNF E:\WindowsImageBackup\JIM-GLH_2011-11-06_012348\Backup 2011-11-06 012348\
    NEXT file/dir 936b54c0-228a-11df-8147-806e6f6e6963.vhd
    print2 E:\WindowsImageBackup\JIM-GLH_2011-11-06_012348\Backup 2011-11-06 012348\936b54c0-228a-11df-8147-
    NEXT dpath after file E:\WindowsImageBackup\JIM-GLH_2011-11-06_012348\Backup 2011-11-06 012348\
    NEXT dpath bottom while E:\WindowsImageBackup\JIM-GLH_2011-11-06_012348\Backup 2011-11-06 012348\
    NEXT dpath after FNF E:\WindowsImageBackup\JIM-GLH_2011-11-06_012348\Backup 2011-11-06 012348\
    NEXT file/dir BackupSpecs.xml
    print2 E:\WindowsImageBackup\JIM-GLH_2011-11-06_012348\Backup 2011-11-06 012348\BackupSpecs.xml
    NEXT dpath after file E:\WindowsImageBackup\JIM-GLH_2011-11-06_012348\Backup 2011-11-06 012348\
    ***NEXT dpath bottom while E:\WindowsImageBackup\JIM-GLH_2011-11-06_012348\Backup 2011-11-06 012348\
    while exhausted
    ***NEXT dpath bottom while E:\WindowsImageBackup\JIM-GLH_2011-11-06_012348\Backup 2011-11-06 012348 (trailing backslash has been removed magically)
    NEXT dpath after FNF E:\WindowsImageBackup\JIM-GLH_2011-11-06_012348\Backup 2011-11-06 012348
    NEXT file/dir Catalog
    NEXT dpath prior E:\WindowsImageBackup\JIM-GLH_2011-11-06_012348\Backup 2011-11-06 012348
    NEXT directory
    Frun recurse E:\WindowsImageBackup\JIM-GLH_2011-11-06_012348\Backup 2011-11-06 012348Catalog

    Code:
    int Frun (TCHAR* Fruni, void (*FrunCB)(TCHAR* FrunCBt)) {
    WIN32_FIND_DATA SFrun;
    HANDLE HFrun;
    TCHAR Frundpath[555];
    TCHAR Frunfpath[555];
    nl(2);
    printf("FrunCB routine address %x", FrunCB); nl(1);
    // dpath has \* on the end for use in FindFirstFile calls
    _tcscpy (Frundpath, Fruni);
    _tcscat (Frundpath, L"\\*");
    // fpath has \ on end for discrete use
    _tcscpy (Frunfpath, Fruni);
    _tcscat (Frunfpath, L"\\");
    // find first file/directory and set Handle
    // dpath has \*
    _tprintf(L"FindFirstFile %s", Frundpath); nl(1);
    HFrun = FindFirstFile(Frundpath, &SFrun);
    // remove ending *
    _tcscpy (Frundpath, Frunfpath);
    _tprintf(L"dpath %s", Frundpath); nl(1);
    // skip . ..
    if ( SFrun.cFileName[0] != L'.' ) {
    // directory?
    if ( SFrun.dwFileAttributes & 0x10 ) {
    _tprintf(L"FIRST dpath prior %s", Frundpath); nl(1);
    _tcscat (Frundpath, SFrun.cFileName);
    _tprintf(L"FIRST directory\nFrun recurse %s", Frundpath); nl(1); 
    Frun(Frundpath, print2);
    }
    // file
    else {
    _tcscpy (Frunfpath, Frundpath);
    _tcscat (Frunfpath, SFrun.cFileName);
    FrunCB(Frunfpath);
    _tprintf(L"FIRST dpath after file %s", Frundpath); nl(1);
    }
    }
    // get each file/directory
    while ( FindNextFile (HFrun, &SFrun) ) {
      _tprintf(L"NEXT dpath after FNF %s", Frundpath); nl(1);
      _tprintf(L"NEXT file/dir %s", SFrun.cFileName); nl(1);
    // skip . ..
    if ( SFrun.cFileName[0] != L'.' ) {
    // directory?
    if ( SFrun.dwFileAttributes & 0x10 ) {
          _tprintf(L"NEXT dpath prior %s", Frundpath); nl(1);
          _tcscat (Frundpath, SFrun.cFileName);
          _tprintf(L"NEXT directory\nFrun recurse %s", Frundpath); nl(1);
          Frun(Frundpath, print2);
        }
    // file
    else {
          _tcscpy (Frunfpath, Frundpath);
          _tcscat (Frunfpath, SFrun.cFileName);
          FrunCB(Frunfpath);
          _tprintf(L"NEXT dpath after file %s", Frundpath); nl(1); 
        }
    // . ..
    }
    
    _tprintf(L"NEXT dpath bottom while %s", Frundpath); nl(1);
    // while
    }
    
    printf("while exhausted\n");
    
    FindClose(HFind);
    return(-1);
    }
    
    Last edited by jlewand; 02-05-2012 at 05:32 PM.

  14. #14
    Registered User
    Join Date
    Feb 2012
    Posts
    44
    Codeplug, thanks for the excellent links. Will read away...

  15. #15
    Registered User
    Join Date
    Feb 2012
    Posts
    44
    Can't edit post above. Got it working (figured out). My first recursion and my first passing a pointer to a function as a function argument.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Old habits die hard
    By Yarin in forum General Discussions
    Replies: 11
    Last Post: 01-24-2012, 12:50 AM
  2. Bad coding habits
    By Magos in forum A Brief History of Cprogramming.com
    Replies: 14
    Last Post: 09-12-2005, 05:44 PM
  3. Unicode vurses Non Unicode client server application with winsock2 query?
    By dp_76 in forum Networking/Device Communication
    Replies: 0
    Last Post: 05-16-2005, 07:26 AM
  4. Professional Habits?
    By RoD in forum A Brief History of Cprogramming.com
    Replies: 28
    Last Post: 01-17-2003, 02:27 PM
  5. Unicode & Good Program Design :: C++
    By kuphryn in forum Windows Programming
    Replies: 2
    Last Post: 08-05-2002, 04:09 PM