Guess a person's secret number between 0 - 100 using binary search - c

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;
}

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 ;) )

Your binary search is incorrect, you need to swap the check of 'h' and 'l'.
Because you compare chars and not strings, use == and not strcmp().
You don't need to include <math.h> because guess is an int, so it'll automatically round floats.
You can use getchar() to clear the buffer after the scanf()
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;
}

Related

Output not showing in C

I'm writing a code that must identify the letter 't' or 'T' in a word, before or after the middle of it.
If the first half of the word does contain a 't' or a 'T', the program should output a 1. If the first half does not contain the letter 't' or 'T', but the second half does, then the program should output a 2. Otherwise, if there is no 't' or 'T' in the word at all, the program's output should be -1. The word entered will not have more than 50 letters.
#include <stdio.h>
#include <string.h>
int main() {
char word[50];
int i = 0, length, t = 0, T = 0;
scanf("%s", word);
length = strlen(word);
t = word[i] == 't';
T = word[i] == 'T';
while(!t || !T) {
if((t || T) && i <= length / 2) {
printf("%d", '1');
} else if((t || T) && i > length / 2) {
printf("%d", '2');
//}else{
// printf("%d", '-1');
}
i++;
}
return 0;
}
If I enter any word and press enter, nothing is printed. Another thing is that when I remove the comment slashes from the two lines at the bottom, the program goes through an infinite loop.
Could someone please help?
This sounds like a school assignment, so I'll focus on advising/critiquing your code rather than giving a solution.
The first recommendation I have is to use a for loop instead of a while loop. A Rule of thumb in C is to only use a while loop when you actually don't have any idea how many things you need your program to look at.
You already have the length of the string, so set up your for loop to loop exactly once for each character.
Next you need to change how you are using printf. The %d format specifier is for printing integers, but you are passing it '1'. This is not an integer, it is the ascii representation of the symbol 1 (which is actually has the value 49, see the ascii table for more info)
You can either pass printf the value 1, or use the %c specifier, which expects ascii characters.
Better yet, just say printf("1");
That doesn't get you all the way there, but I think it lays the ground work so you can find the solution!
Condition !t || !T has no sense to be used as loop condition ...ask yourself how the loop will end ? you need just to check i is less than length
Second, the assignments t = word[i] == 't'; T = word[i] == 'T'; outside the loop have no sense ...you will be just pointing to the zero index of the string ...you should check all characters
third , the printf lines need to use %d
fourth , you appear not getting the purpose of the program printing inside loop will lead to printing many numbers and you just want to know if there is t or T you need to print single line.you may use variable int result=0; to hold the value you want and print it in the end ...of course you will need using break statement in the if((t || T) && i <= length / 2) and if((t || T) && i > length / 2) because no need for more searching
fifth, you should re-read , re-think , re-code the assignment before going bored and asking about it
sixth, there is a working version by modifying your code but you should try writing a good solution before looking at a solution as it better to solve your problems by yourself
#include <stdio.h>
#include <string.h>
int main() {
char word[50];
int i = 0, length, t = 0, T = 0;
scanf("%s", word);
length = strlen(word);
int result=0;
while( i<length) {
t = word[i] == 't';
T = word[i] == 'T';
if((t || T) && i <= length / 2) {
result=1;
break;
} else if((t || T) && i > length / 2) {
result=2;
break;
}else{
result=-1;
}
i++;
}
printf("%d",result);
return 0;
}
# include <stdio.h>
int main()
{
char name[20];
int age;
int siblings;
int childrens;
printf ("Hello my name is A.I, what is your name? \n");
scanf("%s", &name);
printf("how old are you : \n");
scanf("%d",&age);
printf("how many siblings you have: \n");
scanf("%d", &siblings);
printf("how many children you have: \n");
scanf("%d", &childrens);
printf("so your name is : %s \n", name);
printf("and your age is : %d \n", age);
printf("you have siblings : %d\n", siblings);
printf("so you have childrens : %d\n", childrens);
return 0;
}

C Program, getting error about uninitialized variable, the program never ends

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <ctype.h>
#define MAXGUESSES 5
void Instructions();
int PlayGuess(char solution);
char GetLetter();
int CompareLetters(char guess, char solution);
int main()
{
int i = 0;
int numgames = 0;
char solution;
char guess;
int compareletter(char guess, char solution);
FILE *inp;
inp = fopen("letterList.txt", "r");
fscanf(inp, "%c", &solution);
Instructions();
//get number of games the user wants to play
printf("Please enter the number of games you want to play\n");
scanf("%d", &numgames);
for (i = 1; i <= numgames; i++)
//print current game (value of i)
{
//get letter to guess from file
fscanf(inp, "%c", &solution);
PlayGuess(solution);
printf("\nThe letter is %c\n", solution);
}
fclose(inp);
}
void Instructions()
{
printf("Welcome to Letter Guess\n");
printf("To begin you will enter the number of games you want to
play(1 – 4 games)\n");
printf("You have 5 chances to guess each letter\n");
printf("Let's begin\n");
}
int PlayGuess(char solution) //player defined guesses.
{
int numGuesses = 0;
int winOrLose = 0;
while (numGuesses < MAXGUESSES)
{
GetLetter();
numGuesses = numGuesses + 1;
if (numGuesses>MAXGUESSES)
{
printf("You have run out of guesses\n");
}
}
return 0;
}
//get the guess from the user (call GetLetter function)
//call compareLetters function
char GetLetter()
{
char guess = 0;
char solution;
printf("Enter a guess:", guess);
scanf(" %c", &guess);
CompareLetters(guess, solution);
return guess;
}
//compare the guess and the solution
//return a 1 if they are the same
// message based on before or after alphabetically
//return a 0 if the guess and answer are not the same
int CompareLetters(char guess, char solution)
{
if (guess == solution) //if answer is correct
{ printf("Thats it!\n");
return 1;
}
else
if (guess<solution)
{
printf("The letter you are trying to guess comes after %c\n", guess);
printf("\nTry again\n");
GetLetter();
return 0;
}
else
if (guess>solution)
{ printf("The letter you are trying to guess comes before %c", guess);
printf("\nTry again\n");
GetLetter();
return 0;
}
}
Sorry if the code is a bit messy.
Problem #1: The variable "solution" is uninitialized but i do not know how to fix it. I have this problem a lot, if possible i could use an explanation.
Problem #2: When i launch the program and enter the amount of games I want to play it ignores it and gives me endless guesses, the program never stops.
Thanks.
Just put char solution = '\0';. It's enough to get rid of warning.
Try printing the value of numgames you've just read in scanf() function. It seems you're getting some invalid value for some reason...
Upd: I see your problem: you're calling GetLetter() from PlayGuess(); and you're calling CompareLetters() from GetLetter(); and then you call GetLetter() from CompareLetters() so you create endless recursion. Remove calls GetLetter() from CompareLetters().
Continuing from my comments, the key takeaways from your code are (1) you cannot learn C by guessing at syntax, compiling, over and over again, (2) validate ALL input to your program by checking the return of all input functions and validating the value you receive, (3) enable compiler warnings and then read, understand and correct each warning before attempting to compile again, and (4) do not accept code until it compiles cleanly, without warning.
Since your code includes #define _CRT_SECURE_NO_WARNINGS, it is apparent you are on windows using cl.exe (either from cmd.exe or from VS-Code). For learning basic programming, close VS-Code, open the Command Line provided by your VS (or SDK) install, and don't worry about using the IDE again, until you have mastered compiling from the command line and understand your compiler options. See cl.exe C/C++ Compiler Options, or type cl /? at the command prompt.
From the command line, your basic compile string should be similar to:
cl.exe /nologo /W3 /Ox /Tc mysource.c
(/W3 enable most warnings, /Ox enable all optimizations)
I find it helpful to not clutter my c-source directory with .obj and .exe files so I create two additional directories /obj and /bin for the object and executable files. You then use the /Fo and /Fe options to tell the compiler to put the object files and exe files in the proper directories, e.g.
cl /nologo /W3 /Ox /Foobj/mysource /Febin/mysource /Tc mysource.c
That will put mysource.obj in the obj directory and mysource.exe in the bin directory.
You must have the logic for your code clear in your head before you sit behind the keyboard and start pecking away. (See: (1) above). The easiest way to keep it straight by drawing a simple logic diagram for your code and identify what values you will handle in main() and then what will be handled in each function(). You don't need anything fancy, an 8.5x11 sheet of paper and pencil will do. After you have a clear road map for what each part of your code will do, then sit down and start pecking away.
Putting that logic to test, you can rework your code so it makes a lot more sense than it currently does, e.g.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <ctype.h>
#define MAXGUESSES 5
void Instructions();
int PlayGuess (char solution);
char GetLetter();
int CompareLetters (char guess, char solution);
int main (void)
{
int i = 0,
numgames = 0;
char solution;
FILE *inp = fopen ("letterList.txt", "r");
if (inp == NULL) {
fprintf (stderr, "error: file open failed 'letterList.txt'.\n");
return 1;
}
Instructions(); /* give instructions */
/* get number of games the user wants to play */
printf("Please enter the number of games you want to play: ");
if (scanf ("%d", &numgames) != 1) {
fprintf (stderr, "error: invalid input - numgames.\n");
return 1;
}
putchar ('\n');
for (i = 0; i < numgames; i++)
{
/* get letter to guess from file */
if (fscanf (inp, " %c", &solution) == EOF || solution < ' '
|| '~' < solution) {
fprintf (stderr, "error: invalid character - solution.\n");
return 1;
}
printf (" ==> Game %d <==\n\n", i + 1);
PlayGuess (solution);
printf("The letter was '%c'!\n\n", solution);
}
fclose (inp);
return 0; /* main() is type int and returns a value */
}
void Instructions()
{
printf ("Welcome to Letter Guess\n"
"To begin you will enter the number of games you want "
"to play (1 – 4 games)\n"
"You have 5 chances to guess each letter\n"
"Let's begin\n\n");
}
int PlayGuess (char solution)
{
int numGuesses = 0;
char guess;
while (numGuesses < MAXGUESSES)
{
guess = GetLetter();
if (CompareLetters (guess, solution))
return 1;
numGuesses = numGuesses + 1;
}
printf ("You have run out of guesses\n");
return 0;
}
/* get a letter and validate it is good */
char GetLetter()
{
char guess = 0,
tmp;
printf ("Enter a guess: ");
if (scanf (" %c", &tmp) != EOF && ' ' <= tmp && tmp <= '~')
guess = tmp;
return guess;
}
/* compare the guess and the solution
* return a 1 if they are the same
* message based on before or after alphabetically
* return a 0 if the guess and answer are not the same
*/
int CompareLetters(char guess, char solution)
{
if (guess == solution) /* answer is correct */
{
printf ("Thats it!\n\n");
return 1;
}
if (guess < solution)
printf ("The letter you are trying to guess comes after '%c'\n",
guess);
else
printf ("The letter you are trying to guess comes before '%c'\n",
guess);
printf ("Try again\n\n");
return 0;
}
Example Compile String for cl.exe (VS)
>cl /nologo /W3 /Ox /Foobj/guessletter /Febin/guessletter /Tc guessletter.c
Example Use/Output
> bin\guessletter.exe
Welcome to Letter Guess
To begin you will enter the number of games you want to play (1 – 4 games)
You have 5 chances to guess each letter
Let's begin
Please enter the number of games you want to play: 2
==> Game 1 <==
Enter a guess: k
The letter you are trying to guess comes before 'k'
Try again
Enter a guess: c
The letter you are trying to guess comes after 'c'
Try again
Enter a guess: d
Thats it!
The letter was 'd'!
==> Game 2 <==
Enter a guess: e
The letter you are trying to guess comes after 'e'
Try again
Enter a guess: g
The letter you are trying to guess comes before 'g'
Try again
Enter a guess: f
Thats it!
The letter was 'f'!
Look things over and think about how to approach programming in C. It is an exact language. It is up to you to account for all characters in all input buffers as well as your memory use. If you don't know what parameters a library function takes, or what type and value it will return, or how to use it, look it up. The man pages are available at, e.g. msdn fscanf, fwscanf or scanf(3): input format conversion)
Let me know if you have further questions.
Accepting Input In Any Case, Converting to Lowercase
To accept input in any case and convert the value to lowercase so that guess is always lowercase in your code, you need to change only one-line:
/* get a letter and validate it is good
* (convert letter to lowercase)
*/
char GetLetter()
{
char guess = 0,
tmp;
printf ("Enter a guess: ");
if (scanf (" %c", &tmp) != EOF && ' ' <= tmp && tmp <= '~')
guess = tolower (tmp);
return guess;
}
note: For ASCII characters, the 6th-bit is the 'case bit', if it is 1, the character is lowercase, 0 uppercase. tolower can simply be written as:
unsigned c_tolower (unsigned c)
{
if ('A' <= c && c <= 'Z')
c ^= (1 << 5);
return c;
}
You have to initialize guess and solution to something before you use them in a function.
And what does this line
int compareletter(char guess, char solution);
indicate, there is no function with same name nor it is a call to any function.
In case for dummy initialization you can use
solution = '\0';

How to detect space and letters in a Char in C?

Do you know how I can detect space and letters in a CHAR variable?
I need to detect letters or space in a input of numbers:
This what I want to do:
Enter Document Number of 8 numbers:
// i press space and pressed enter
ERROR: please enter the age again: 4fpdpfsg
There's where my code doesn't detect the letters after the 4, and what I want is recognize that there's letters in the input, and then shows only the 4.
int isLetter(char input[]){
int i = 0;
while(input[i]!='\0'){
if((input[i]!=' ') && (input[i]<'a'||input[i]>'z') && (input[i]<'A'||input[i]>'Z'))
return 0;
i++;
}
return 1;
}
The standard C library has various character type testing functions. They are declared in the #include <ctype.h> header.
Unfortunately, the obvious way of using these functions is often wrong. They take an argument of type int which is actually expected to be an unsigned character value (a byte, effectively) in the range 0 to UCHAR_MAX. If you pass in a char value which happens to be negative, undefined behavior ensues, which might work by coincidence, crash or worse yet form a vulnerability similar to heartbleed (possibly worse).
Therefore the cast to (unsigned char) is quite likely necessary in the following:
#include <ctype.h>
/* ... */
char ch;
/* ... */
if (isalpha((unsigned char) ch) || ch == ' ') {
/* ch is an alphabetic character, or a space */
}
Simple character constants (not numeric escaped ones) derived from the C translation time character set have positive values in the execution environment; code which can safely assume that it only manipulates such characters can do without the cast. (For instance, if all the data being manipulated by the program came from string or character literals in the program itself, and all those literals use nothing but the basic C translation time character set.)
That is to say, isalpha('a') is safe; a is in the C translation time character set, and so the value of the character constant 'a' is positive. But say you're working with source code in ISO-8859-1 and have char ch = 'à';. If char is signed, this ch will have a negative value, which is fine according to ISO C because an accented à isn't in the basic C translation character set. The expression isalpha(ch); then passes a negative value to the isalpha function, which is wrong.
Try:
if (!((input[i] == ' ') || (input[i] >= 'a' && input[i] <= 'z') || (input[i] >= 'A' && input[i] <= 'Z')))
or, better:
#include <ctype.h>
if (!((input[i] == ' ') || isalpha(input[i])))
You could use sscanf(input,"%d%n",&number,&nrOfDigits) which reads in an integral value into number and additionally stores the position of the first character which has not been part of the number in nrOfDigits. With this information, you can then decide what to do, e.g. nrOfDigits < 8 would indicate that either the input was shorter than 8 characters, or that it does contain less than 4 consecutive digits. See sample code of the usage below.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int isLetter(char input[]){
int nrOfDigits=0;
int number;
int scannedElems = sscanf(input,"%d%n",&number,&nrOfDigits);
if (scannedElems == 0) {// number could not be read--
printf ("No number read.\n");
return 0;
}
else {
char c = input[nrOfDigits];
int isAlpha = isalpha(c);
printf("input %s leads to number %d with %d digit(s); first characer after the digits is '%c', (isalpha=%d)\n", input, number, nrOfDigits, c, isAlpha);
return number;
}
}
int main(){
isLetter("4fpdpfsg"); // input 4fpdpfsg leads to number 4 with 1 digit(s); first characer after the digits is 'f', (isalpha=1)
isLetter("afpdpfsg"); // No number read.
isLetter("12345678"); // input 12345678 leads to number 12345678 with 8 digit(s); first characer after the digits is '�', (isalpha=0)
return 0;
}
BTW: you could implement a similar logic with strtoul as well.
hey guys i finally get the way to detect the input is conformed only for 8 numbers theres the code
char* InputDni(char dni[])
{
int sizeletter;
int i;
fflush(stdin);
gets(dni);
// 8 is the size of DNI in argentina
while((isLetter(dni)) || (strlen(dni)!=8))
{
printf("ERROR: enter again the DNI: ");
fflush(stdin);
gets(dni);
}
sizeletter=strlen(dni);
for(i=0 ;i<sizeletter; i++)
{
while(isalpha(dni[i]))
{
printf("ERROR: enter again the DNI: ");
fflush(stdin);
gets(dni);
i++
}
}
return dni;
}
//isLetter
int isLetter(char input[])
{
int i = 0;
int sizeletter;
int flag=1;
sizeletter=strlen(input);
for(i=0;i<sizeletter;i++)
{
if((input[i]!=' ') && (input[i]<'a'||input[i]>'z') && (input[i]<'A'||input[i]>'Z'))
{
flag=0;
}
}
return flag;
}
picture of the code running in cmd:

How to invalidate an input in c

I'm writing a program in C that is suppose to ask the user for a number.
The number has to be greater than zero and cannot have letters before or after the number. (ie: 400 is valid but abc or 400abc or abc400 is not). I can make my program invalidate everything besides 400abc. How would I make it invalidate an input if it starts valid then turns invalid? (I'm about 2 months into an intro to c class so my knowledge is very limited.)
#include<stdio.h>
int check(void);
void clear_input(void);
main()
{
int num;
printf("Please enter a number: ");
num = check();
printf("In Main %d\n", num);
}
int check(void){
int c;
scanf("%d", &c);
while (c < 0){
clear_input();
printf("Invalid, please enter an integer: ");
scanf("%d", &c);
}
return c;
}
void clear_input(void){
char junk;
do{
scanf("%c", &junk);
}while (junk != '\n');
}
You can also check whether ascii value of each char scanned from user input should lie in range 48-57, It will only then be integer value.
strtol can be used to do it, but it takes some extra work.
After running this code:
char *endptr;
int n = strtol(num_text, &endptr, 10);
n will contain the number. But you still have to check that:
1. *endptr=='\0' - this means strtol didn't stop in the middle. In 400abc, endptr will point to abc. You may want to allow trailing whitespace (in this case, check that endptr points to an all-whitespace string.
2. num_text isn't empty. In this case, strtol will return 0, but an empty string isn't a valid number.
Read the input as a line, using fgets.
Check if all characters are numeric.
If not, it's invalid. If yes, use sscanf to get the line into an int.
Check if the int is in the range; you're done.
Scanf with %d will treat the "400abc" as 400, all the trailing characters would be ignored, so there is nothing to worry about.
If you definitely want to treat "400abc" as an invalid input, then maybe you shouldn't use %d in scanf, use %s instead?
One way is to read the whole line as a string and check by yourself if it contains any non-digits.
The other way is reading the integer and then looking into the input using fgetc() to see if the next character after the detected input is valid. Or you could even use the same scanf() for this:
char delim;
if(scanf("%d%c", &c, &delim) == 2 && !isspace(delim))
// the input is invalid
You can read the number in a character array and validate it by checking if all the characters lie in the ascii range 48 to 57 ( '0' to '9' ) .If so your no. is valid otherwise you can safely regard it as invalid input.Here the the demonstration :
#include<stdio.h>
#include<string.h>
int conv( char * word )
{
int ans=0;
int res=0;
for(int i=0;i<strlen(word);i++)
if(word[i]>='0' && word[i]<='9')
ans=(ans*10) + (word[i] - '0');
else
res=-999;
if(res==-999)
return res;
else
return ans;
}
int main()
{
char a[10];
gets(a);
int b=conv(a);
if(b==-999)
printf("Invalid Entry.\n");
else
printf("Success.No is %d.\n",b);
return 0;
}
You can adjust for negatives as well by checking the first character in the word array to be '-' and adjusting the sign accordingly.
This is C99, so compile with -std=c99
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <stdbool.h>
bool getNum(int *n) {
char c, s[10];
if (!scanf("%9s", s))
return false;
for (int i=0; c=s[i]; i++)
if (!isdigit(c))
return false;
*n = atoi(s);
return true;
}
int main() {
int n;
if (getNum(&n))
printf("you entered %d\n", n);
else
printf("you did not enter a number\n");
}
The following is your check function rewritten to fix your problem, so try this:
int check(void){
int n;
char c;
while (EOF==scanf("%d%c", &n,&c) || n < 0 || !isspace(c)){
clear_input();
printf("Invalid, please enter an integer: ");
}
return n;
}

Memory error in C program, The name disappears?

Im trying to make a simple game, http://pastebin.com/BxEBB7Z6, in c. The goal is to beat the computer by getting as close to 21 as possible by getting random numbers.
For each round the players name and sum is presented, but for some reasons it only works that first time? Something like this:
Player John has sum 0.
Player has sum 9.
Player has sum 11.
And so on.
Why does the the player's name get showed once, but not any other prints after that? I dont do a reassign somewhere :-)
I use the function void PrintPlayerSum(struct Player *p) to print it out, it works the first time, but only that.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
struct Player
{
char name[256];
int sum;
};
void PrintPlayerSum(struct Player *p)
{
printf("Player %s has sum %d\n", p->name, p->sum);
}
void wait ( int seconds )
{
clock_t endwait;
endwait = clock () + seconds * CLOCKS_PER_SEC ;
while (clock() < endwait) {}
}
int main()
{
struct Player *player = malloc(sizeof(*player));
strcpy( player->name, "John");
player->sum = 0;
while(1)
{
PrintPlayerSum(player);
printf("Do you want another number? (y/n, q for quit) ");
char ch;
scanf("%s", &ch);
if( ch == 'q' )
break;
if( ch == 'y' )
{
srand(time(NULL));
int rnd = rand() % 13 + 1;
player->sum += rnd;
printf("Player got %d\n", rnd);
}
if( ch == 'n' || player->sum > 21)
{
if( player->sum > 21 )
{
printf("\n*** You lost the game, please try again... ***");
}
else
{
printf("\nCPU's turn\n");
int cpusum = 0;
while( 1 )
{
if( cpusum > 21 )
{
printf("\n*** CPU lost the game with the score %d, you win! ***", cpusum);
break;
}
if( cpusum > player->sum )
{
printf("\n*** CPU won the game with the score %d, please try again ***", cpusum);
break;
}
wait(1);
srand(time(NULL));
int rnd = rand() % 13 + 1;
cpusum += rnd;
printf("CPU got %d, sum is %d\n", rnd, cpusum);
}
}
break;
}
printf("\n\n");
}
/* Cleanup ******************/
free(player);
/****************************/
printf("\n\n\n");
system("PAUSE");
return 0;
}
I suspect the problem is your use of scanf. You say you want to read a zero-terminated string, but you stuff it into a single char. The way the variables are laid out on the stack causes the terminating zero-byte to end up as the first char in player->name.
Try typing "buffer overflow" instead of "y", and you should get "player uffer overflow go ...".
If you want to stick with scanf, you want to make sure you pass it a proper string and set a limit on the size of the target buffer. For reading one char, try fgetc.
Edit:
The above is of course not quite right... It is a buffer overflow, but it is the pointer of the player struct that is being overwritten. By lucky coincidence you get to a valid address that points to a zero-byte. By typing more, you will most likely get a crash instead.
Your scanf call is likely the problem:
scanf("%s", &ch);
You seem to want a single character, but you're reading a string. It'll put the first character in ch, but keep going from there and overwrite whatever's next on the stack.
You should probably just use fgetc(stdin) or another function that reads a single character, if a single character is what you want.
shouldn't it be
struct Player *player = malloc(sizeof(struct Player));
Weird thing like that are usually caused by writing to unallocated memory. (Usually writing beyond the end of an array.)
I didn't look at your code, but search for things like that. Then run your program under valgrind.
At a first glance i can see you have done:
scanf("%s", &ch);
Which will use the address of ch to input a string, and therefore result in a buffer overflow. You need to do
ch = getchar ();
scanf ("%c", &ch);
etc.

Resources