Thread: Comparing command line arguements to a string.

  1. #1
    Devil's Advocate SlyMaelstrom's Avatar
    Join Date
    May 2004
    Location
    Out of scope
    Posts
    4,079

    Comparing command line arguements to a string.

    Hi, I'm just starting to get into these command line arguements, and I just have one small problem with my first one. It's a simple program, which I basically got to work, it's just the conditions for error checking in the program aren't all working.

    Code:
    #include <iostream>
    #include <string>
    #include <fstream>
    
    using namespace std;
    
    int main(int argc, char* argv[]) {
        if (argc == 2) {
           string word = argv[1];
           cout << argv[1] << " has " << word.length() << " letters in it.";
           }
        else if (argc == 3 && argv[1] == "file") {
           ifstream input_file(argv[2]);
           if(!input_file) {
    			cout << argv[2] << " does not exist";
    			return 0;
    		}
    		char c;
    		int count = 0;
    		while(input_file.get(c)) {
               if (c != '\n' && c != ' ')
    		   count++;
    		}
    		cout << argv[2] << " has " << count << " letters in it.";
        }
        else {
           cout << "Proper format is 'count <string>' or " << endl
                << "'count file <file>'" << endl << argv[1];
           return 0;
           }
        
        return 0;
    }
    The bolded and underlined " argv[1] == "file" " is where I'm having the problem. It doesn't seem to understand this in the program. What confuses me though is if I create a string variable and set that equal to "file", then compare the arguement to the variable, it works fine. Also, I output argv[1] in the else statement just to make sure it says "file", and it did.

    So, I guess my question is... is it unacceptable to directly compare an arguement to a string constant?
    Sent from my iPadŽ

  2. #2
    Code Goddess Prelude's Avatar
    Join Date
    Sep 2001
    Posts
    9,897
    >The bolded and underlined " argv[1] == "file" " is where I'm
    >having the problem. It doesn't seem to understand this in the program.
    The program understands it perfectly, it just has a different idea of what you're doing than you do. Since both argv[1] and "file" are C-style strings, they're effectively pointers when you do this comparison. Because the two are unlikely to refer to the same memory, the test will probably fail. To compare C-style strings, you use std::strcmp:
    Code:
    #include <cstring>
    
    else if (argc == 3 && strcmp ( argv[1], "file" ) == 0) {
    >is it unacceptable to directly compare an arguement to a string constant?
    Not at all, it's just not usually what you want.
    My best code is written with the delete key.

  3. #3
    Devil's Advocate SlyMaelstrom's Avatar
    Join Date
    May 2004
    Location
    Out of scope
    Posts
    4,079
    Oh, thank you. I probably should have thought of that.

    Thanks, very much.
    Sent from my iPadŽ

  4. #4
    Registered User
    Join Date
    Apr 2003
    Posts
    2,663
    Hi,

    You are comparing pointers not values. Whenever you have a string literal like "file", C++ slaps a '\0' onto the end of it and stores it in memory somewhere and returns the address. argv[1] is stored at another address. When you do this:

    argv[1] == "file"

    you are comparing a pointer to an address. To compare the values at those addresses, you need to use the <cstring> function strcmp().
    Code:
    #include <iostream>
    #include <cstring>
    using namespace std;
    
    int main()
    {
    	char* argv[] = {"something", "file", "other"};
    
    	if( strcmp(argv[1],"file") == 0 )
    	{
    		cout<<"they are equal"<<endl;
    	}
    
    	return 0;
    }
    Last edited by 7stud; 10-28-2005 at 02:59 PM.

  5. #5
    Devil's Advocate SlyMaelstrom's Avatar
    Join Date
    May 2004
    Location
    Out of scope
    Posts
    4,079
    Thank you, too.

    You both deserve a simley award.

    One for Prelude
    ...and one for 7stud
    Sent from my iPadŽ

  6. #6
    Registered User
    Join Date
    Apr 2003
    Posts
    2,663
    Most things I post came via Prelude anyway.

  7. #7
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    Instead of using strcmp you could just use the string class's operator== like you do in other parts of the program by converting one of the two C-style strings to a C++ string:
    Code:
    argv[1] == string("file")
    // or
    string(argv[1]) == "file"

  8. #8
    Devil's Advocate SlyMaelstrom's Avatar
    Join Date
    May 2004
    Location
    Out of scope
    Posts
    4,079
    Yes, I had done that. Which is why I said the program worked fine in the first place, I was just curious as to why I couldn't pass the arguement the way I was trying to in the example. Anyway, thanks to Prelude's advice, I've elimated the use of String.h completely to simplify the program.

    Here is the finished product, it works fine:
    Code:
    #include <iostream>
    #include <fstream>
    
    using namespace std;
    
    int main(int argc, char* argv[]) {
        if (argc == 2) {
           cout << argv[1] << " has " << strlen (argv[1]) << " letters in it.";
           }
        else if (argc == 3 && strcmp ( argv[1], "file" ) == 0) {
           ifstream input_file(argv[2]);
           if(!input_file) {
    			cout << argv[2] << " does not exist";
    			return 0;
    		}
    		char x;
    		int letter = 0;
    		while(input_file.get(x)) {
               if (x != '\n' && x != ' ')
    		   letter++;
    		}
    		cout << argv[2] << " has " << letter << " letters in it.";
        }
        else {
           cout << "Proper format is 'count <string>' or " << endl
                << "'count file <file>'";
           return 0;
           }
        
        return 0;
    }
    You can compile it if you wish to try it, though it's probably below those that have replied to this, thus far.
    Last edited by SlyMaelstrom; 10-28-2005 at 11:22 PM.
    Sent from my iPadŽ

  9. #9
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    >> Anyway, thanks to Prelude's advice, I've elimated the use of String.h completely to simplify the program.

    You actually eliminated <string> which is completely different than <string.h>. But you should also add <cstring> (which is equivalent to <string.h>) because the strcmp method is found in <cstring>. So you haven't removed any headers (you just got lucky that your program worked on your compiler without <cstring> or <string.h>).

    IMO, using the string class is much simpler. Even in this particular program I think the C++ string version is simpler and cleaner. I'm not sure Prelude was actually advising you to stop using C++ strings.
    Last edited by Daved; 10-29-2005 at 08:11 AM.

  10. #10
    Devil's Advocate SlyMaelstrom's Avatar
    Join Date
    May 2004
    Location
    Out of scope
    Posts
    4,079
    Hmmm, I understand your point. I wouldn't say my original working program using <cstring> was bad, but I personally would disagree that it was any neater than using strcmp() and strlen(). Neither preference is complicated if you know the syntax. I'd say for this program, I like my final code better.

    ...that's just me though.
    Sent from my iPadŽ

  11. #11
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    That's fine. This program concentrates on command line arguments, which even in C++ are C-style strings. So using C-style string functions to handle them isn't a bad thing.

    BTW, I know it's confusing, but you might want to brush up on the differences between <string> and <cstring>/<string.h>. You've confused them again (your original program used <string>, not <cstring>), and it makes it a little harder to understand what you're saying.

  12. #12
    Devil's Advocate SlyMaelstrom's Avatar
    Join Date
    May 2004
    Location
    Out of scope
    Posts
    4,079
    Yeah, I really don't know the difference between string.h and string. Other than string.h is a depreciated library as far as my programming level and compiler goes they do the exact same thing. I'll make some time to study up on them.

    By the way, if the include doesn't have a .h, like <string>, is it still considered a library?
    Sent from my iPadŽ

  13. #13
    Registered User
    Join Date
    Apr 2003
    Posts
    2,663
    Ok, here's the deal: C++ does not have legal standard header file names with .h after them.

    If you put .h after your standard header file names, you are breaking the rules of C++, and therefore you should get an error when you try to compile your program. Just because your compiler allows you to do that, does not mean you are programming in C++, and if you try to compile your program on another compiler, it may not work. C++ is a language that has certain rules and syntax. Various manufacturers make compilers to compile C++ code in accordance with those rules, but they don't always get the rules right or they decide to break the rules. That is why you will read discussions about which compiler is the best, i.e. which one follows the rules most accurately.

    You should also be aware that the rules and syntax of C++ change. Programmers propose rule changes and improvements, which are then either adopted or rejected. In the past, manufacturers of compilers adopted an unofficial rule where standard header files ended in .h. At some point in time, the C++ governing body officially adopted a standard that required that C++ standard files not end in .h, and thereafter all the unofficial standard header file names ending in .h were officially changed. The standard header file name <string.h> became <cstring>, the standard header file name <math.h> became <cmath>, <time.h> became <ctime>, etc. Hopefully, you can see the pattern: the .h was dropped and 'c' was added to the front of the name.

    So, <string.h> is equivalent to <cstring>, which contains functions dealing with c-style strings, i.e. character arrays. <string> is a type that was added when C++ was invented, and it contains the functions dealing with "string" types. A C++ string type is a different type than a cstyle string. With cstyle strings, you can't do this:
    Code:
    char str1[] = "hello ";
    char str2[] = "world";
    
    str1 = str1 + str2;
    to get "hello world". Instead you have to call a function to combine the arrays, and not only that, the first array has to have the extra space to hold the characters from the second array.

    Well, that and other things can make cstyle strings a pain in the butt. So, the inventor of C++ decided to invent a type that made operations on strings easier: the "string" type. With a string type, you can do this:
    Code:
    string str1 = "hello ";
    string str2 = "world";
    
    str1 = str1 + str2;
    and get "hello world". Note how you don't have to worry about there being extra space in the first string to hold the characters from the second string. The '+' sign also makes it more intuitive what is happening compared to strcat().
    Last edited by 7stud; 10-30-2005 at 03:12 AM.

  14. #14
    Devil's Advocate SlyMaelstrom's Avatar
    Join Date
    May 2004
    Location
    Out of scope
    Posts
    4,079
    Well thanks for that. As I said, I do understand how both c-style and C++ style strings work.
    ...but the information explaining <cstring> and such was very helpful.

    Thanks
    Sent from my iPadŽ

  15. #15
    Registered User
    Join Date
    Apr 2003
    Posts
    2,663
    Here's a better explanation of the legal names for standard header files in C++:

    http://www.cplusplus.com/doc/ansi/hfiles.html

    New header files introduced in C++ just got the .h lopped off their names, e.g. <iostream.h> became <iostream>, and any header files that existed in C got the .h removed and a 'c' added to the front, e.g. <string.h> became <cstring>.
    Last edited by 7stud; 10-30-2005 at 04:58 AM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Please check my C++
    By csonx_p in forum C++ Programming
    Replies: 263
    Last Post: 07-24-2008, 09:20 AM
  2. String issues
    By The_professor in forum C++ Programming
    Replies: 7
    Last Post: 06-12-2007, 09:11 AM
  3. Calculator + LinkedList
    By maro009 in forum C++ Programming
    Replies: 20
    Last Post: 05-17-2005, 12:56 PM
  4. Comparing string contents
    By Slavakion in forum C++ Programming
    Replies: 3
    Last Post: 01-13-2004, 12:14 PM
  5. Warnings, warnings, warnings?
    By spentdome in forum C Programming
    Replies: 25
    Last Post: 05-27-2002, 06:49 PM