#1
  1. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jan 2013
    Posts
    2
    Rep Power
    0

    Input '10' but treated as '1'?


    Hi guys, i really need help with this one. I'm noob in c programming and have difficulties of trying to debug my codes.
    Everytime i try inputing '10', the computer interprets it as '1' and run that instead. I believe it is my if else condition that needs to be amended. But not sure what. My program is below. Please help.

    #include <stdio.h>
    #include <math.h>
    #include <stdlib.h>
    #define PI 3.14
    main()
    {
    char selection;
    printf("\n\tArea of...\n");
    printf("\t1. Sqaure\n");
    printf("\t10. Exit!\n");
    printf("\nPlease make a sellection: ");
    scanf("%c", &selection);
    getchar();

    if ( selection == '1')
    {
    Square();
    }
    else if (selection == '10')
    {
    printf ("\nBye bye!!\n\n");
    system ("pause");
    return 0;
    }
    }

    Square()
    {
    float Square_Length, Square_Area;
    printf("\nPlease key in the length of the square in cm: ");
    scanf("%f", &Square_Length);
    Square_Area=pow(Square_Length,2);
    printf("The area of the square is: %.4f cm2\n", Square_Area);
    getchar();
    printf("\nPress enter to return to main menu...");
    getchar();
    main();
    }
  2. #2
  3. Contributed User
    Devshed Specialist (4000 - 4499 posts)

    Join Date
    Jun 2005
    Posts
    4,387
    Rep Power
    1871
    Because '10' is TWO characters.

    Try using another single letter, say 'q' (that's always popular).
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper
  4. #3
  5. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,162
    Rep Power
    2222
    First, use code tags to preserve your code's formatting. Failure to do so will render it unreadable. Eg (having retrieved your original formatting via the Reply button):
    Code:
    #include <stdio.h>
    #include <math.h>
    #include <stdlib.h>
    #define PI 3.14
    main()
    {
    	char selection;
    	printf("\n\tArea of...\n");
    	printf("\t1. Sqaure\n");
    	printf("\t10. Exit!\n");
    	printf("\nPlease make a sellection: ");
    	scanf("%c", &selection);
    	getchar();
    
    	if ( selection == '1')
    	{
    		Square();
    	}
    	else if (selection == '10')
    	{
    		printf ("\nBye bye!!\n\n");
    		system ("pause");
    		return 0;
    	}
    }
    
    Square()
    {
    	float Square_Length, Square_Area;
    	printf("\nPlease key in the length of the square in cm: ");
    	scanf("%f", &Square_Length);
    	Square_Area=pow(Square_Length,2);
    	printf("The area of the square is: %.4f cm2\n", Square_Area);
    	getchar();
    	printf("\nPress enter to return to main menu...");
    	getchar();
    	main();
    }
    Second, your functions need to be explicitly declared with a return type. If you leave one out, it defaults to int, but then you neglect to actually return anything. What did your warning messages tell you? You are allowing your compiler to display warnings, aren't you? And you aren't ignoring those warnings, are you? Never ignore warnings! Warnings are far more important than error messages.

    Third, never call main! Only the start-up code, which you don't see but is nonetheless there, calls main. You never call main!. To return from a function, return from it! Either you explicitly use the return statement (absolutely required if you are returning a value) or you reach the end of the function. But you never call main!

    Fourth, you need to have declared Square before you call it. You would have gotten a warning about that too; never ignore warnings! Place a function prototype for Square just above main.

    Fifth, single quotes indicate a single character (eg, '1'), whereas double quotes indicate a character string (eg, "1" or "10"). This, '10', is absolutely meaningless and should have generated at least a warning, which you must not ignore!

    What your code does is read in a single character and then test it. When the input is the string "10\n" (a newline will always be part of the input string, because you have to hit the Enter key) and you read in a single character into selection, then selection will contain '1'. The next time you read in a character, selection will contain '0'. And the next time you read in a character, selection will contain '\n'.

    So then, sixth,
    scanf("%c", &selection);
    will read in the next character in the input buffer, including white space such as the newline character. In order to have scanf ignore white space, you need to tell it to ignore white space, thus:
    scanf(" %c", &selection);
    Please note the space before the %. That tells scanf to expect white space before the input character and to ignore that white space.

    Now clean up your code. Also, main needs to be declared as returning int and the final line in main needs to be a return statement that returns an int. Return zero (0) to indicate success and non-zero to indicate failure.
  6. #4
  7. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jan 2013
    Location
    Poland
    Posts
    4
    Rep Power
    0
    Maybe try casting selection variable to int in this part of your code:

    Code:
            if ( (int)selection == '1')
    	{
    		Square();
    	}
    	else if ((int)selection == '10')
    	{
    		printf ("\nBye bye!!\n\n");
    		system ("pause");
    		return 0;
    	}
    I know it's not a proper casting but should work.
  8. #5
  9. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,162
    Rep Power
    2222
    No, casting would not solve the problem. Here is what I get when I try to compile the program. Please note all the warnings:
    C:>gcc -Wall square.c
    square.c:6: warning: return-type defaults to `int'
    square.c: In function `main':
    square.c:17: warning: implicit declaration of function `Square'
    square.c:19: warning: multi-character character constant
    square.c:19: warning: comparison is always false due to limited range of data type
    square.c:25: warning: control reaches end of non-void function
    square.c: At top level:
    square.c:28: warning: return-type defaults to `int'
    square.c: In function `Square':
    square.c:38: warning: control reaches end of non-void function

    C:>
    Note especially the warnings about line 19, which is
    else if (selection == '10')
    First it warns about a multi-character character constant. Then it informs us that that if condition will always evaluate to false. Casting will make no difference whatsoever there.

    Instead, the scanf needs to convert the input commands to integer values, since all the commands are integer values.

    But that code is messed up at least six ways to Sunday and that's not even examining it closely. It needs a lot more work.
  10. #6
  11. Contributing User

    Join Date
    Aug 2003
    Location
    UK
    Posts
    5,110
    Rep Power
    1803
    Take input as an integer, not a character, and test against integer values not character constants.

    Prefer switch/case to if-else if-else when a single integer variable is tested for value.

    Code:
    int selection ;
    
    scanf( "%d", &selection ) ;
    
    switch( selection )
    {
        case 1 :
        ....
        break ;
    
        case 10 :
        ....
        break ;
    }
    Last edited by clifford; February 7th, 2013 at 01:37 PM.
  12. #7
  13. Contributing User
    Devshed Demi-God (4500 - 4999 posts)

    Join Date
    Aug 2011
    Posts
    4,856
    Rep Power
    481
    [edit]Cast affects the way c interprets a region of memory. It does not alter data.
    This small text is incorrect. Quite a blunder since I had just demonstrated otherwise in post.[/edit]
    Last edited by b49P23TIvg; February 1st, 2013 at 08:14 PM.
    [code]Code tags[/code] are essential for python code and Makefiles!
  14. #8
  15. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,162
    Rep Power
    2222
    Originally Posted by b49P23TIvg
    Cast affects the way c interprets a region of memory. It does not alter data.
    Not actually. That's what Borland's (anyone else remember Borland?) Object Pascal did, but not what C does -- conceptually at least; I'm not sure what it does when you force casting of incompatible types. I remember that that was a point of confusion for me when I migrated from Borland's Pascal (greatly extended from the standard) to C and C++.

    When you cast in C, you do not reinterpret the contents of that memory location, but rather you perform an explicit conversion from one data type to another compatible data type. So when you cast a char to a short or to a long, you had started with a single byte but then you convert that into a two- or four-byte integer, extending the sign bit. That is not mere reinterpretation of the bit pattern that already exists, but rather its conversion to a different bit pattern. This is made far more apparent when you cast an integer type to a floating-point type or vice-versa; the bit patterns generated by those conversions are entirely different than those of the original values. Though, since they are incompatible, I'm not sure what would happen if you were to cast a char pointer to an int, though I'm pretty sure that the compiler would throw a warning at you.

    More specifically to the point, here's what Hucilo's "solution" of
    if ( (int)selection == '1')
    would actually do. selection is a char, which is one byte long and would contain the value of 0x31, the ASCII code for '1'. The cast would convert that to a four-byte int, which is 0x00000031. Then to compare that int to a char, the char must be converted to an int as well; C does this automatically, so '1', which was 0x31, now becomes 0x00000031, which is indeed equal to 0x00000031, so the condition evaluates to true. Please note, Hucilo, that the outcome is the same as with the original,
    if ( selection == '1')
    , though without wasting time and computer resources with unnecessary data type conversions, both explicit and implicit. The real problem was with the '10', which is an imaginary beastie that cannot possibly exist and hence references to such abominations are ignored, though warned about, and attempts to use them in comparisons always result in FALSE.

    Rather what casting in Object Pascal did was to reinterpret the bit pattern that was in memory; if you wanted to convert from one data type to another (eg, from INTEGER to REAL), then there were functions that did that for you, but not casting. I became rather fond of the low-level things I could do with casting and was disappointed to discover that C's casting worked completely differently. So instead what I needed to do in C was something like in my program for displaying a float as a hex representation of its internal bit pattern:
    Code:
    #include <stdlib.h>
    #include <stdio.h>
    
    int main(int argc, char *argv[])
    {
        int i;
        float f;
        
        if (argc != 2)
        {
            fprintf(stderr,"Usage: f2hex <floating-point value>");
            exit(1);
        }
        
        f = (float)atof(argv[1]);
        printf("%g = ",f);
        
        for (i=3; i>= 0; i--)
            printf(" %02X",((unsigned char*)(&f))[i]);
        printf("\n"); 
        
        return 0;       
    }
    So I take the address of the variable, recast that pointer to point to a different data type, and then dereference that pointer to a different data type. That is more apparent in the reverse process where the hex bytes are loaded into an array of bytes, buffer:
    Code:
        float f;
        unsigned char buffer[4];
        // ... intervening code loading hex bytes into buffer
        f = *((float*)buffer);
    It was later pointed out to me that I could have used unions instead, but then I never was a union man myself.

    Comments on this post

    • b49P23TIvg agrees : Ooops! I edited my post accordingly.
  16. #9
  17. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jan 2013
    Posts
    2
    Rep Power
    0
    Wow. Thanks guys for the help. Esp dwise1. Yea, I'm still stuck trying to solve the warnings. :confused:
  18. #10
  19. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,162
    Rep Power
    2222
    If you're asking us to help you with that, I hope you realize that we need to see the warnings and the code.

IMN logo majestic logo threadwatch logo seochat tools logo