Re: FindFirstFile, how much faster than FindNextFile?
From: Joseph M. Newcomer (newcomer_at_flounder.com)
Date: 02/13/05
- Next message: Joseph M. Newcomer: "Re: FindFirstFile, how much faster than FindNextFile?"
- Previous message: Joseph M. Newcomer: "Re: Serialize puzzle"
- In reply to: John Doe: "Re: FindFirstFile, how much faster than FindNextFile?"
- Next in thread: John Doe: "Re: FindFirstFile, how much faster than FindNextFile?"
- Reply: John Doe: "Re: FindFirstFile, how much faster than FindNextFile?"
- Messages sorted by: [ date ] [ thread ]
Date: Sat, 12 Feb 2005 22:08:33 -0500
See below...
On Fri, 11 Feb 2005 20:29:16 GMT, John Doe <jdoe@usenet.is.the.real.thing.com> wrote:
>Joseph M. Newcomer <newcomer@flounder.com> wrote:
>
>>You have many issues here. There's nothing wrong with your code
>>that a complete rethinking and rewrite won't solve.
>
>I apologize if my code isn't clear. If you point out where the
>problem is, I will happily clarify (of course I will, I'm asking for
>help). That's one reason I keep re-including my code in the reply.
*****
I think I pointed out numerous places where your code is not clear
*****
>
>>First, you are presuming the files are in the root directory. This
>>would at best be a horrible assumption;
>...
>
>I know exactly where the files will be. This is the folder as
>planned.
>
>C:\Program Files\Shortcuts\Scripts
*****
I wouldn't trust anything like this. For example, some installations protect c:\Program
Files so random programs cannot be installed. In a multiboot system the user may want the
scripts to be in a directory appropriate for the current boot, not in C:\. This assumption
is dangerous. I am always deeply suspicious of any program that claims that the path is a
known compile-time absolute, mostly because of the huge number of programs that I've had
to fix because these assumptions proved invalid in practice.
Read the value from the Registry.
*****
>
>All of the files will be in that folder, nowhere else.
>
>>Next, you say you want an arbitrary substring of the filename, but
>>that's not what your patterns are suggesting. If I want to find any
>>file that contains "KeyA" anywhere in it, the correct pattern is
>>not
>> *KeyA.txt
>>but
>> *KeyA*.txt
>...
>
>There is no second asterisk because there is no space between the
>capital letter A and the ".txt"
****
But you clearly said "arbitrary substring" and "using strstr". Both of these are quite
different from what you are now saying. The correct statement of the problem is
All my file names will be of the form "*Key?.txt", where the ? is from the set [A-Z0-9] or
"*Pad?.txt" where ? is from the set [1-9].
That is a clear and precise definition, which could not be inferred from anything you had
said, and certainly not from the code.
but you confuse the description with misleading sentences. Say exactly what you intend.
*****
>
>>... where do you get the strings for comparison? You erroneously
>>answered where you got the filenames for the other half of the
>>comparison;
>
>Oh, okay. The strings for comparison include "Key" or "Pad" and the
>regular keyboard letter and number keys (A-Z and 1-9), and the
>keypad keys 1-9, plus the TXT extension.
*****
OK, that is actually a useful description.
>
>The ends of the filenames will look like this.
>...KeyA.txt
>...KeyB.txt
>...KeyC.txt
>...Key1.txt
>...Key2.txt
>...Key3.txt
>...Pad1.txt
>...Pad2.txt
>...Pad3.txt
>... and so on
>
>I know that because earlier in the program I generate the filenames.
>
>Trying to keep track of the filenames probably won't work since they
>can be edited from within Windows Explorer (the last part remains
>intact). My program relies on that editing to do significant
>programming work.
>
>>I knew that you got them from FindFirstFile. But why do you need a
>>case at all?
>
>Because the cases allow searching directly for the specific last
>part of a filename like "*KeyB.txt" or "*Pad7.txt" where the wParam
>search criteria is one of the 45 user input symbols/codes.
>
>>Just do
>> FindFirstFile( strings[i], ...)
>>
>>and you don't need something as silly as 50 cases to handle a
>>trivial problem. Just an array of 50 strings!
>
>Using only one FindFirstFile()?
*****
You have not actually said what you are trying to find. Given the names, you then must
give a description such as
"I wish to enumerate all files in the directory of the form "*Key?.txt" for ? in the set
[A-Z0-9]" which would suggest that you want more than one file. Your description suggests
that you would specify the pattern and get a unique file, and your code, given it sets a
specific name, enforces the notion that you are looking for one file of the name.
*****
>
>>so the whole discussion about whether a switch statement is
>>"faster" is irrelevant.
>
>If I didn't favor efficiency, it might be irrelevant. I tend to
>dwell on efficiency. It's not a big deal.
>
>I appreciate your effort.
>
>>Since it is clear the table is compile-time constant,
>>
>>static const LPCTSTR strings[] = {
>> _T("*KeyA*.txt"),
>> _T("*KeyB*.txt"),
>>...
>> NULL // end of table
>>};
>
>Except maybe without the second asterisk. There is no space between
>the capital letter and the ".txt"
>
>>Why are you using strcpy?
>
>Your guess is as good as mine.
>
>>... you are begging for some serious bug to arise.
>
>I will be the first to know since I use the program all day long.
****
The time to find a bug is not when you are using it. The time to detect the possibility of
a bug is to code the program so the bug cannot arise. Use of strcpy opens opportunity for
bugs to arise. Use of CString makes sure that such a bug can never happen. What do you
think is the more robust approach? Hope you don't see one, plan to deal with it when the
program crashes, or create a program that can never have a bug of that nature and
consequently cannot crash because of it?
*****
>
>>Lose the switch statement. Rethink the problem and if the answer
>>does not seem obvious, ask it in terms of a program construct that
>>would make sense.
>
>This is my current signature:
>To participate in an open-source Windows macro recorder project,
>please see the unmoderated group (comp.windows.open-look). Coding
>help is needed. Using VC++ 7. The project files or the program files
>will be provided to programmers or expert Windows users, just ask.
*****
Omigod. Not Another Macro Recorder! You're doomed. A lot of people have tried these, and
I've seen very few success stories. The mouse is the killer. Keyboard recorders are
usually doomed too, for a variety of reasons that should be obvious. For example, suppose
I drop down a combo box and arrow down six selections. Will I get the same selection the
next time the program runs? EVERY time the program runs? It is even worse with a mouse.
What does it mean to hit the space bar in a checkbox? For example, suppose I start up the
dialog and do tab, tab, tab, space. Is the check box checked or unchecked? How do I create
a macro that always selects the file "somefile.txt" from a listbox of file names based on
the directory contents? Right. Dream on.
Let me put it this way: After programming Windows for 15 years, I would not tackle a macro
recorder project. Not even Microsoft can get it right...I've tried to use their macro
recorder, and it sucks. Big time. In every Office application, without exception. I even
know why it sucks; it is because the problem is fundamentally intractable. You are trying
to guess from keystrokes what the actual intent of the user was in the actual problem
domain. This is rarely successful. I would not tackle such a project because I know, after
all these years, that it is impossible to get right. This has not stopped any number of
beginners from trying to do one. This newsgroup is littered with the history of
unsuccessful attempts at macro recorders. The first time they hit a real combo box, a list
control, a tree control, it is all over.
But if you still think it is doable, feel free to try. But if history is any judge, you
are wasting your time.
*****
>
>That's where the code will be, for anyone who was afraid to ask.
>
>>In fact, when I re-read your message, the actual solution is even
>>simpler, if the ? is unique.
>>CString suffix = _T("ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"); // for
>>example FileHandle = FindFirstFile( MakePattern(keybase +
>>suffix[i]), &FindData); FileName = keybase + suffix[i] +
>>extension;
>>CString MakePattern(const CString & keybase)
>> {
>> return basedirectory + _T("*") + keybase + _T("*") +
>> extension;
>> }
>>And PLEASE do not suggest that this is "inefficient";
>
>Do you want me to lie?
*****
Depends on what you are lying about. It actually isn't inefficient, if you measure
efficiency in terms of program performance instead of lines of code performance.
*****
>
>>In rereading the code once more, I see that you really DIDN'T mean
>>case 65; you almost certainly meant case 'A', which is what you
>>should have written. In this case, the code is even more trivial:
>>you just concatenate the character you would have used in the
>>switch statement!
>>TCHAR value;
>>FileHandle = FindFirstFile( MakePattern(keybase + value),
>>&FindData); FileName = keybase + value;
>
>I guess, if those possibilities use only one FindFirstFile().
>
>>A good refresher on basic principles of the C language seems a good
>>investment of your time. If you want to represent the value of the
>>character 'A', the value 'A' is a much better choice than the value
>>65. So if you wanted a case based on letter values, the preferred
>>way of writing it would be
>> case 'A':
>> ... something here
>> break;
>> case 'B':
>> ... something for the B case
>> break;
>>
>>Note that if you had actually indicated this by something as
>>obvious as using the value you meant, 'A', instead of some bizarre
>>numeric encoding of the character, the code would have been more
>>obvious. The fact that it took me three careful readings of your
>>code to try to make sense out of it--that you had written code so
>>convoluted and obscure that its meaning was not obvious on first
>>reading--already suggests so many failures of the coding process
>>that you need to scrap this entirely and rewrite it.
>
>You are too kind [kidding].
>
>Since I'm going to also use keypad numbers, I doubt that the graphic
>representation is better than the simple ASCII character
>representation for the case labels.
****
Note that if you are looking at WM_CHAR, the keypad '0' is indistinguishable from the
normal keyboard '0'. If you are looking at WM_KEYDOWN, there are already VK_ constants
defined for a number of these symbols, e.g., VK_NUMPAD0. The symbols VK_A-VK-Z and
VK_0--VK-9 are stated as being equivalent to the ASCII characters 'A'-'Z' and '0'-'9', so
I'm not sure exactly what advantage you see in using absolute numeric constants.
Of course, you may be doing another translation from the VK_NUMPADn values to some other
inernal value; in that case,, use a macro, e.g., KEYPAD(x) so if you want the numeric code
for '0' on the keypad, you would write KEYPAD('0'), which abstracts the details of how the
macro works out of the way, but doesn't leave the user reading some silly numeric constant
and trying to figure out what it means.
CString pattern;
CString FileName;
CString FilePattern;
if(('A' <= key && key <= 'Z') || ('0' <= key && key <= '9')
pattern = CString(_T("Key")) + key;
else
if(VK_NUMPAD0 <= key && key <= VK_NUMPAD9)
pattern = CString(_T("Pad")) + KEYPADCHAR(key);
else
...either deal with error, or you know key is valid and has to be one of the above
FileName = pattern;
FilePattern = basedirectory + _T("*") + pattern + _T(".txt");
where
#define KEYPADCHAR(x) ((TCHAR)(_T('0') + (TCHAR)((x) - VK_NUMPAD0))
makes everything a lot more readable and conveys what is really going on, instead of
leaving people guessing. Note that I've reduced your 200 lines with a switch statement to
about 8 lines with no switch statement. What could be simpler?
*****
>
>>Why write a switch statement with 4 lines of code for each of 50
>>cases (the case plus the three lines of executable code--that's 200
>>lines of code!) when you can write the whole thing in about three
>>lines of code? And have it more robust
>
>Not that it matters, but arguments so far have not convinced
>me that using the switch statement is less robust. Yes, it's a lot
>more code, especially considering your refinements to the other
>possible method. That's why I posted.
*****
What is robust? Robust under mantenance is critical. If you decide to add one line, you
now have to add 50 instances of that one line, one for each of the switch cases. I guess
if it has to be explained to you why the switch statement is absurd, you may be beyond
recovery.
*****
>
>>I've just reduced 200 lines of code to 3 lines of code, which is
>>66:1 compression.
>...
>>I think you need to focus less on what is "efficient" in terms of
>>the API interactions and more on basic principles of constructing
>>code that is easy to write, read, understand and maintain, and is
>>robust and correct under actual user scenarios. Your example meets
>>none of the previous criteria.
>
>I'm the user, all day long.
****
No, you said it is going to be an open source project. Open source has a lot more
requirements than a personal pet project. Open source means that anyone, anywhere, should
be able to see exactly what the code is doing; it must be easy to read, easy to modify,
and a work of art. What I see here is something that is obscure, hard to maintain, and as
a work of art looks like the sort of birdhouse a six-year-old would build. It is laden
with bent nails, the edges barely meet, and it would not pass my elementary criteria for
acceptability in a freshman programming course. If you make it open source, you owe the
readers a work that is the best that can be done. This isn't even close to acceptable by
most standards.
>
>>efficiency. And "right" does not simply mean "computes the result I
>>want".
>
>It could be worse.
>
>
>
>
>
>
>
Joseph M. Newcomer [MVP]
email: newcomer@flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
- Next message: Joseph M. Newcomer: "Re: FindFirstFile, how much faster than FindNextFile?"
- Previous message: Joseph M. Newcomer: "Re: Serialize puzzle"
- In reply to: John Doe: "Re: FindFirstFile, how much faster than FindNextFile?"
- Next in thread: John Doe: "Re: FindFirstFile, how much faster than FindNextFile?"
- Reply: John Doe: "Re: FindFirstFile, how much faster than FindNextFile?"
- Messages sorted by: [ date ] [ thread ]
Relevant Pages
|