#1
  1. Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jan 2014
    Posts
    134
    Rep Power
    1

    Problem with tolower function


    So I am building a program that would check whether the words provided as command line arguments are one of the names of the planets (yes, I am considering Pluto as a planet too), and if any of them indeed are, it would check the rank of the planet. Firstly I want all of the words provided as command line arguments to drop their cases, so that any issues of case mismatch doesn't occur while strcmp is operating. Here's the code I came up with:
    Code:
    #include <stdio.h>
    #include <string.h>
    #include <ctype.h>
    
    #define NUM_PLANETS 9
    
    int main(int argc, char *argv[])
    {
        char *planets[] = {"mercury", "venus", "earth", "mars", "jupiter", "saturn", "uranus", "neptune", "pluto"};
        char str[20];
    	int i, j;
    
        for (i = 1; i < argc; i++) {
            for (j = 0; j < NUM_PLANETS; j++)
            strcpy(str, planets[j]);
            tolower(str);  /*this is the line with the problem*/
            if (strcmp(argv[i], str) == 0) {
                printf("%s is planet %d\n", argv[i], j + 1);
                break;
            }
            if (j == NUM_PLANETS)
                printf("%s is not a planet\n", argv[i]);
        }
    
        return 0;
    }
    I have marked the line containing the problem with a comment. Here are the warnings that are being shown: "passing argument 1 of 'tolower' makes integer from pointer without a cast [enabled by default]", "statement with no effect [-Wunused-value]" and "ctype.h [Note] expected 'int' but argument is of type 'char *'" I would be grateful if someone could explain the problems here, precisely why tolower is not having any effect.

    By the way, how do I debug a program that takes command line arguments? After I set a breakpoint and press debug, the console doesn't take any input! How do I do this? Thanks in advance!
  2. #2
  3. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,155
    Rep Power
    2222
    Read the documentation on tolower. It takes a single character (albeit as an int), not an entire string. Therefore, when you try to pass a string to tolower, the compiler will complain that it's expecting an int but you gave it a char * instead. Just like it told you.

    If you want to convert an entire string to lower case, then you need to use a loop to iterate through all the characters in the string.

    how do I debug a program that takes command line arguments?
    Meaning the command line arguments that are stored in argv[] ? There should be an option somewhere in a dialog box for command line arguments. It may be under the Debug menu or it may be part of the project options/properties. It's different from one integrated development environment (IDE; eg, Visual Studio, Dev-C++) to another. You need to have set that option before you start to debug the program.
  4. #3
  5. Java Junkie
    Devshed Specialist (4000 - 4499 posts)

    Join Date
    Jan 2004
    Location
    Mobile, Alabama
    Posts
    4,021
    Rep Power
    1285
    What it's telling you is that the function accepts a single char as parameter, but you are sending an array of characters.
  6. #4
  7. Contributing User
    Devshed Demi-God (4500 - 4999 posts)

    Join Date
    Aug 2011
    Posts
    4,850
    Rep Power
    481
    If using gdb then start the program with r followed by the command line arguments:

    gdb_prompt> r venus nuptune mers pLUto
    [code]Code tags[/code] are essential for python code and Makefiles!
  8. #5
  9. Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jan 2014
    Posts
    134
    Rep Power
    1
    Originally Posted by dwise1_aol
    Read the documentation on tolower. It takes a single character (albeit as an int), not an entire string. Therefore, when you try to pass a string to tolower, the compiler will complain that it's expecting an int but you gave it a char * instead. Just like it told you.

    If you want to convert an entire string to lower case, then you need to use a loop to iterate through all the characters in the string.
    How about this?
    Code:
    k = 0;
    while (str[k] != '\0') {
    	tolower(str[k]);
    	k++;
    }
    The compiler gives a warning that this statement has no effect! :/
  10. #6
  11. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,155
    Rep Power
    2222
    That's right, it doesn't have any effect. Take another example, the arctangent of 1.0:
    atan(1.0);
    That doesn't have any effect either. Can you see why? Now look at this version of the same statement:
    x = atan(1.0);
    Now that statement does have an effect. Why is that? Well, atan returns the arctangent of the value passed to it. If you don't make any use of the return value of atan, then calling the function has no effect. Can you see that?

    When you read the documentation for tolower, what did it tell you about the function? Didn't it tell you that the return value was the argument converted to lower case? So shouldn't you use the return value? Say, by assigning it to str[k]?

    I'm not trying to be insulting, but rather I'm trying to take you through a way of thinking about the problem and about how code works, as well as the importance of reading the documentation for these library functions. I'm trying to promote a way of thinking about problems that will help you solve them.

    Other than that, the loop is fine. Though, as in spoken languages, while there are many ways to say the same thing, native speakers tend to say things in a certain way. Experienced C programmers tend to use the for-statement a lot, even when a while would be more appropriate; eg:
    Code:
        while(str[k] != '\0') // normal
    
        for (; str[k] != '\0'; ) // the more colloquial form, but not too common
    
        while(1)  // an infinite loop (use break; to exit it)
    
        for (;;)  // an infinite loop with for; extremely common
    And besides, this loop just cries out for a for-statement, what with the initialization and incrementing of that index variable:
    Code:
        for (k=0; str[k] != '\0'; k++)
            str[k] = tolower(str[k]);
    To reiterate, the way you wrote it does work (except for the tolower with no effect) and does do the same thing as the for loop does, but most programmers would use the for-statement instead.

    BTW, very good work in paying attention to warnings! If you had ignored that warning, then you'd have no idea that that didn't work. Warnings are so very much more important than error messages.

IMN logo majestic logo threadwatch logo seochat tools logo