1

I converted a code that I know how to construct in python in C Language, but everytime I run the program in CodeBlocks, the program crashes! And I have NO idea why this is happening, can someone help me?

The program is suppose to guess a person's number (between 0 - 100), using binary search. For example, if my number is 66, the program asks if my number is 50, since 66 is higher than 50, the number 50 becomes the lower boundary while 100 remains to be the higher boundary, and so on...

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

int main()
{
    int x;
    printf("Please think of a number between 0 and 100\n\n");
    x = binarysearch();
    printf("%d", x);


}
int binarysearch()
{
int hi,lo,guess;
hi = 100;
lo = 0;
char user_inp;
while (1){
    guess = round(((hi + lo)/2));
    printf("Is your secret number %d?\n\n", guess);
    printf("Enter 'h' to indicate the guess is too high. \nEnter 'l' to indicate the guess is too low.\nEnter 'c' to indicate I guessed correctly. \n");
    scanf("%c", &user_inp);
    if (strcmp(user_inp, "c") == 0){
        break;
    }
    else if  (strcmp(user_inp, "h")==0){
        hi = guess;
    }
    else if (strcmp(user_inp, "l")==0){
        lo = guess;
    }
    else{
        printf("Sorry, I did not understand your input.");
        continue;
    }
}
printf("Game over. Your secret number was");
return guess;

}
  • 1
    add a space before the conversion specifier: `scanf(" %c", &user_inp)` – pmg Jan 14 '20 at 15:27
  • 2
    don't use strings to compare: `if (user_inp == 'h') ...` – pmg Jan 14 '20 at 15:28
  • 2
    turn on all your compiler warnings, and **mind them**. – pmg Jan 14 '20 at 15:30
  • 1
    @pmg's comment is important but rather terse. To elaborate: `strcmp()` compares two strings, but you're passing a character and a string. If you'd passed a pointer to the character, you'd have got away with it. But instead, strcmp will be interpreting the character value (some small number) as a pointer to a string. And that's likely causing the crash. – Edd Inglis Jan 14 '20 at 15:36
  • @pmg's _second_ comment is also very valuable: if you enable compiler warnings (`-Wall` for GCC or `\W4` for MSVC), your compiler would likely have spotted your mistake and told you upfront, rather than leaving you in this confusing hole at runtime. – Edd Inglis Jan 14 '20 at 15:37
  • 1
    Heh, I didn't even need to enable warnings, GCC just immediately barfed: `so.cpp: In function 'int binarysearch()': so.cpp:17:29: error: invalid conversion from 'char' to 'const char*' [-fpermissive] if (strcmp(user_inp, "c") == 0){` – Edd Inglis Jan 14 '20 at 15:40
  • I think we're ready for a real Answer. I'm happy to write one, but it seems rude to take the credit for what was really @pmg's advice. – Edd Inglis Jan 14 '20 at 15:43
  • thanks @EddInglis. Feel free to "hijack" my comments, I'm on my mobile and prefer to leave proper answers when I have access to a real computer. – pmg Jan 14 '20 at 16:11
  • In passing, make sure you always check the result of `scanf()` before using the written-to variables - if there's an error, we end up reading uninitialised `user_inp` and probably loop indefinitely. Not good. – Toby Speight Jan 17 '20 at 11:40

2 Answers2

1
  1. Your binary search is incorrect, you need to swap the check of 'h' and 'l'.
  2. Because you compare chars and not strings, use == and not strcmp().
  3. You don't need to include <math.h> because guess is an int, so it'll automatically round floats.
  4. You can use getchar() to clear the buffer after the scanf()
  5. You need to declare your function before main (possibly by defining the function before main).
#include <stdio.h>
#include <stdlib.h>
// WITHOUT <MATH.H>

int binarysearch(void);

int main(void)
{
    int x;
    printf("Please think of a number between 0 and 100\n\n");
    x = binarysearch();
    printf("%d", x);
    return 0;    // RETRUN 0    
}

int binarysearch(void)
{
    int hi,lo,guess;
    hi = 100;
    lo = 0;
    char user_inp;
    int flag = 1;    // USE FLAG, NOT BREAK AND CONTINUE
    while (flag){
        guess = ((hi + lo)/2);   // WITHOUT ROUND
        printf("Is your secret number %d?\n\n", guess);
        printf("Enter 'h' to indicate the guess is too high. \nEnter 'l' to indicate the guess is too low.\nEnter 'c' to indicate I guessed correctly. \n");
        scanf("%c", &user_inp);
        getchar(); // CLEAR THE BUFFER
        if (user_inp == 'c'){   // MAKE FLAG 0
            flag = 0;
        }
        //  USE '==', NOT STRCMP
        else if  (user_inp == 'l'){  // YOU NEED TO SWAP 'L' & 'H'
            hi = guess;
        }
        else if (user_inp == 'h'){
            lo = guess;
        }
        else{
            printf("Sorry, I did not understand your input.");
        }
    }
    printf("Game over. Your secret number was ");
    return guess;
}
Toby Speight
  • 27,591
  • 48
  • 66
  • 103
asaklein
  • 74
  • 4
  • If you use `1.` instead of `1)` for numbering, you will get nice list formatting. Then you can put some text (any text) in front of the code snippet then to make it format nicely (so that the code snippet is not part of the enumeration). – KamilCuk Jan 17 '20 at 11:30
  • 1
    Good but would it not be better to actually get the input with `getchar()` instead of `scanf`? A portable way to do this would be something like `while((c = getchar()) != '\n' && c != EOF);` Best to add the terminating semi-colon on a new line for readability, see http://c-faq.com/stdio/stdinflush2.html and https://stackoverflow.com/a/7898516/5362795 – Nagev Jan 17 '20 at 11:53
1

As per the comments, the problem was very likely the incorrect use of strcmp:

char *string = "fish";
char not_a_string = 'f';
if (0 == strcmp( not_a_string, string  ))
  ...

The character 'f' has ASCII value 0x66. strcmp would blindly use this as a pointer (expecting it to point to a valid string) which would cause a crash as you access memory that's not yours (a segmentation fault).

You would have got away with strcmp( &not_a_string, string ) in this case, but that's good fortune, not correct code.

To compare the user's character input with another character, you can just use a straightforward equality (since they're both really integers):

if ( user_inp == 'c' ) ...

So that's your code fixed, but how did you ever get to run it in the first place? For me GCC immediately complained:

In function 'int binarysearch()': so.cpp:17:29: error: invalid conversion from 'char' to 'const char*' [-fpermissive] 
if (strcmp(user_inp, "c") == 0){

and didn't produce an output. It's telling you the same thing I just did (albeit fractionally more cryptically).

Lessons to learn: listen to your compiler's complaints (and make your compiler as complainy as possible)


@pmg also noted:

add a space before the conversion specifier: scanf(" %c", &user_inp)

Without it, every time you hit Enter:

Sorry, I did not understand your input.Is your secret number 25?

ie you get a spurious complaint. But with the space it works as desired.

(I hate scanf, so have no idea why this works ;) )

Edd Inglis
  • 1,067
  • 10
  • 22
  • Hi! As per the suggestions in the comments, I fixed the character comparison test to:if ( user_inp == 'c' ) ... but if i input the characters 'l' 'h' or 'c' it gives me the same answer o "Sorry, I did not understand your input.Is your secret number 50?" – Roger SNITH Jan 14 '20 at 16:10
  • 2
    I hate `scanf()` too, though it has its moments ... anyway, the space before the `"%c"` asks `scanf()` to skip optional whitespace (the enter from the previous line). – pmg Jan 14 '20 at 16:13
  • @pmg WOoooW I think the mistake was that I used Double quotations for the character comparison instead of single quotations...AND IT HAS MADE ALL THE DIFFERENCE! haahahah DAMN I really really hate the C language right now, ugh! – Roger SNITH Jan 14 '20 at 16:23
  • @EddInglis is there another alternative to scanf? – Roger SNITH Jan 14 '20 at 16:28
  • 1
    We're getting a little off-topic now, but... Yes, there are alternatives to `scanf`, but they mostly involve getting single characters at a time and doing it 'by hand'. For what you're doing, it's a perfectly fair choice for the convenience it offers. But that convenience comes at a cost: maybe 50% of C questions on SO seem to concern some hideous bug or confusion introduced by incorrect use of scanf, which surely has to tell you something. – Edd Inglis Jan 14 '20 at 16:34
  • Random linky: http://sekrit.de/webdocs/c/beginners-guide-away-from-scanf.html – Edd Inglis Jan 14 '20 at 16:39
  • @RogerSNITH: If you're all good, please accept an answer. If you have further problems, please let us know. – Edd Inglis Jan 16 '20 at 09:17