I am writing a program that starts printing at 0.
It prints up to 15 and asks the user a y/n question.
if y that program prints next 15.
if n program stops.
The program I wrote does not work.
Help solving this.
int main()
{
int i=0,k=1;
char ans;
while(k=1)
{
i++;
printf("\n%d",i);
if(i%15==0)
{
printf("\nDo you want to continue?(y/n): ");
scanf("%c",ans);
ans = toupper(ans);
if(ans=='Y') {
continue;
}
else if(ans=='N') {
k=0;
}
}
}
}
----------------------------------EDIT-------------------------------------
changed the code as #Programmer400. Also 15-->3. Now my computer prints
1
2
3
Do you want to continue?(y/n): y
4
5
6
Do you want to continue?(y/n):
7
8
9
Do you want to continue?(y/n): y
First it prints till 3 and asks. After Y, it prints till 6 and asks and then without any input prints till 9 and asks. Note the missing y in the 2nd question.
I have provided a working C program below that performs the tasks you specified in your question.
I have taken an effort to stay true to the functions that you used in your original code sample and I have also taken care to only make additions (not remove code).
In the comments, I have explained lines of code that I have added that were not in your original code sample.
#include <stdio.h>
int main(void)
{
int i = 0, k = 1;
char user_input;
char ans;
while(k == 1)
{
i++;
printf("%d\n", i);
if (i % 15 == 0)
{
printf("Do you want to continue? (y/n/Y/N): ");
scanf(" %c",&user_input); // Keep the whitespace in front of the %c format specifier -- it's important!
getchar(); // Consume the newline character left in the buffer by scanf()
// Check if user input is already capitalized
if (user_input >= 65 && user_input <= 90)
// If it is, keep it capitalized
ans = user_input;
else
// If it isn't, capitalize it
ans = toupper(user_input);
if (ans=='Y')
{
// Allow the loop to continue
continue;
}
else if (ans == 'N')
{
// Inform the user that execution is ending
printf("Exiting loop... ending program.\n");
// Consider removing 'k' entirely, just use a 'break' statement
k = 0;
}
else
{
// Inform the user that the input was not recognized (if not y/n/Y/N...)
printf("User input not recognized... please provide input again.\n");
// Decrement 'i' so that the user is forced to provide input again...
i--;
// Allow the loop to continue
continue;
}
}
}
}
Helpful notes:
scanf leaves a newline character in the buffer when you are reading user input with character formatters. Namely...
%c, %n, and %[] are the 3 specified expectations that do not consume leading whitespace
-- From a comment on this StackOverflow answer.
Keep in mind that if you would like to exit your while loop, you could simply insert a break statement. This way, you don't have to change the value of k (which is rather ambiguous) to end the loop and the code is more readable because an explicit break statement is harder to misinterpret. In this simple case, the use of k is easily understood (so don't worry about it too much, for now).
If you ever intend to read string input from a user (i.e., an array of characters), then I would recommend that you use fgets() instead of scanf(). A discussion of the merits of fgets() in comparison to scanf() is provided in this StackOverflow answer. Further, it is important to recognize that even though you can use gets() to perform a similar operation it is highly dangerous and never advised. Check out the explanations provided by the top two answers to this StackOverflow question.
I tried changing your code so that it doesn't generate warnings, now it seems to "work" (but maybe it can be even more correct).
#include <stdio.h>
#include <stdbool.h>
#include <ctype.h>
int main()
{
int i=0,k=1;;
char c;
char ans[] = "";
while(k==1)
{
i++;
printf("\n%d",i);
if(i%15==0)
{
printf("\nDo you want to continue?(y/n): ");
scanf(" %c",ans);
ans[0] = (char) toupper(ans[0]);
if(ans[0]=='Y') {
continue;
}
else if(ans[0]=='N') {
k=0;
}
}
}
}
Related
Task:
Create a number guessing game where the user has a limited number of guesses to figure out what the randomly generated number is
Check whether the user has inputted a digit or character using "Isdigit" informing them to input a number between 1 and 20 if they use the wrong input or guess out of the expected range.
Using a while loop limits the user guesses
After the user runs out of guesses close the program
Problem I'm facing: I'm new to programming and so I don't have too much experience yet. It's my first time trying to understand the is digit function and I feel like there is a more efficient way of solving this problem.
Since I'm using 2 data types when trying to compare int's and chars I can't make a direct comparison but I figured out the difference between char 1 and int 1 is 48 apart so I made that as a temporary solution. But it only works for single-digit numbers
I've read that I might be able to go through the string character by character to make sure each of them are a digit before the input is accepted and combine the string at the end but I'm not sure how to do that
The user can't input more than 1 character or the program ends
I'd also like to fix any other bugs people may find and write the code in a more effective and understandable way
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
int main()
{
int iRandomNum = 5; //setting up a number as a placeholder until Code works
char guess; //char being used as I beleive it needs to be char for isdigit to function
int guessCount = 0; //
int guessLimit = 3;
int outOfGuess = 0;
srand(1-10);
//iRandomNum = (rand()%20)+1;
while (guess != iRandomNum && guessCount != 3 && outOfGuess == 0){ //Intended to break out of loop once any variable is satisfied
if(guessCount< guessLimit){
printf("\n%d", iRandomNum);
printf("\nYou have %d guesses left", guessLimit- guessCount); //extra user info
printf("\nGuess the number between 1 - 10: ");
scanf(" %s", &guess);
if (isdigit(guess)==0)
{
printf("\nEnter a digit!");
guessCount++; //supposed to limit user to 3 chances
}else
{ //need help solving this
printf("\nYou entered %d\n", guess - 48); //Using for testing
guess = guess - 48;
if (guess == iRandomNum) //I dont think functions as char and int are different data types
{
printf("\nYou've Won");
break;
}else{
printf("\nWrong guess");
guessCount++;
}
}
}else //Once user runs out of guesses while loop should break an then display following data
{
printf("Second else");
guessCount++;
//outOfGuess = 1;
}
}
if (outOfGuess == 1){
printf("\nOut of guesses!");
}
else{
printf("\nCongratulations!");
}
return 0;
}
An issue not already mentioned in comments: guess is used in the while condition before it has been assigned a value - that's an error.
Regarding the main problem:
In order to allow the user to input more than 1 character (i. e. up to two for a two-digit number), you can use a sufficiently sized character array. Of course you then have to account for a second character when checking using "Isdigit". So e. g. replace
scanf(" %s", &guess);
if (isdigit(guess)==0)
with
char s[2+1]; // +1 for string-terminating null character
if (scanf(" %2s", s) < 1 || !isdigit(s[0]) || s[1] && !isdigit(s[1]))
In order to convert the string in the array to an integer, you can simply use atoi:
guess = atoi(s);
I'm trying to do a program with a simple game for a user to guess the number. My code is below:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define MAX 30
#define TRYING 5
void guessnumber(int, int, int *);
int main(void) {
int mytry = 1;
guessnumber(MAX, TRYING, &mytry);
if (mytry <= TRYING)
printf("Congratulations! You got it right in %d tries\n", mytry);
else
printf("Unfortunately you could not guess the number in the number of tries predefined\n");
printf("End\n");
return EXIT_SUCCESS;
}
void guessnumber(int _n, int _m, int *_mytry) {
srandom(time(NULL));
int generated = 0, mynum = 0, test = 0;
generated = rand() % (_n + 1);
printf("Welcome to \"Guess the number\" \n");
printf("A number between 0 and %d was generated\n", _n);
printf("Guess the number:\n");
while (*_mytry <= TRYING) {
test = scanf(" %d", &mynum);
if (test != 1 || mynum < 0 || mynum > MAX)
printf("ERROR: please enter a valid number \n");
else
if (mynum > generated)
printf("Wrong! The number your trying to guess is smaller\n");
else
if (mynum < generated)
printf("Wrong ! The number your trying to guess is bigger\n");
else
break;
*_mytry = *_mytry + 1;
}
}
Okay, now the program is working pretty ok except for one thing: the scanf test.
It works if I try to enter a number out of my range (negative or above my upper limit) but it fails if I for example try to enter a letter. What it does is that it prints the message of error _m times and then it prints "Unfortunately you could not guess the number in the number of tries predefined" and "End".
What am I doing wrong and how can I fix this?
In case, a character is entered, you're trying to detect it correctly
if(test!=1 ......
but you took no action to correct it.
To elaborate, once a character is inputted, it causes a matching failure. So the input is not consumed and the loop falls back to the genesis position, only the loop counter is increased. Now, the previous input being unconsumed, is fed again to the scanf() causing failure once again.
This way, the loop continues, until the loop condition is false. Also, for every hit to scanf(), as unconsumed data is already present in the input buffer, no new prompt is given.
Solution: You need to clean the input buffer of existing contents when you face a failure. You can do something like
while ((c = getchar()) != '\n' && c != EOF);
to clean the buffer off existing contents.
When you enter a letter, scanf() leaves the letter in the input stream since it does not match the %d conversion specifier. The simplest thing to do is use getchar() to remove the unwanted character:
if (test != 1) {
getchar();
}
A better solution would be to use fgets() to get a line of input, and sscanf() to parse the input:
char buffer[100];
while (*_mytry<=TRYING)
{
if (fgets(buffer, sizeof buffer, stdin) == NULL) {
fprintf(stderr, "Error in fgets()");
exit(EXIT_FAILURE);
}
test=sscanf(buffer, "%d", &mynum);
if(test!=1 || mynum<0 || mynum>MAX)
printf ("ERROR: please enter a valid number \n");
else if(mynum>generated)
printf("Wrong! The number your trying to guess is smaller\n");
else if(mynum<generated)
printf("Wrong ! The number your trying to guess is bigger\n");
else
break;
*_mytry=*_mytry+1;
}
In the above code, note that the leading space has been removed from the format string. A leading space in a format string causes scanf() to skip leading whitespaces, including newlines. This is useful when the first conversion specifier is %c, for example, because any previous input may have left a newline behind. But, the %d conversion specifier (and most other conversion specifiers) already skips leading whitespace, so it is not needed here.
Additionally, your code has srandom() instead of srand(); and the call to srand() should be made only once, and probably should be at the beginning of main(). And, identifiers with leading underscores are reserved in C, so you should change the names _m, _n, and _mytry.
First of all, thank you for the assist!
I'm new to the C language (and programming in general) and I'm trying to write a program wherein the user inputs data points. The data points are then saved in an array where they can then be manipulated.
Where I am stuck: I want the user to be able to input (almost) any number of points, then use a 'keyword' of sorts to signal the end of data entry. In this case, the user would type 'done'.
Here's what I have so far:
#include <stdio.h>
#include <string.h>
int main(void) {
printf("\n Welcome! \n\n Please enter each data point. Enter 'done' when finished.\n\n");
double data[1048];
int i, count;
for (i = 1; ;i++) {
printf("Data[%i]: ", i);
scanf("%lf", &data[i]);
if (data[i] == 'done') {
break;
} else {
count++;
}
}
}
I've tried 'return 1;' and 'break;'. Each time, the program works well until the 'keyword' is entered, at which point I get:
Data[8]: Data[9]: ... Data[1120]: Data[1Segmentation fault 11
The only time it works is if I have it break when the user inputs a particular number (like -1 or 0). But that doesn't quite work for the user since they might have to enter those numbers as data points.
Sorry for the long post, but I appreciate the help!
You have received a number of good answers to your question, and there are several more ways to take input of doubles and stop on "done". Since you are learning C, always, ALWAYS (in case it wasn't clear), check the return of scanf to validate the number of conversions you expected actually took place.[1] (this also provides your way to end input on "done" (or any non-double entered causing scanf to return less than 1)
As noted in the comment, arrays are zero based in C. When you are taking input, you will want to use count as your array-index, rather than i (in this case if you exit the read on each failure -- it doesn't matter, but you could just as easily prompt again for additional input and increment count only on a successful return from scanf) Back to your question. If you set up your read loop to continually loop until there is a scanf failure, you can make use of a temporary variable to initially capture the input value, and only assign the value to your array and increment your index on success. e.g. (with a constant MAXD = 1048)
for (;;) { /* loop until scanf input fails (with 'done') */
double tmp; /* block scope declarations are fine */
printf (" data[%4d]: ", count);
if (count < MAXD && scanf(" %lf", &tmp) == 1)
data[count++] = tmp;
else
break;
}
(you can even move a copy of the prompt above the loop, and move the one above after the if (....) {...} to eliminate the prompt when the array limit (MAXD) is reached -- that's left as an exercise)
In the example above you have 2 conditions you enforce before storing a value. (1) you limit the number of values your user can store to MAXD, and (2) you only store a value if a valid conversion to double takes place in scanf. You leave the loop if either of the conditions fails (which if you enter "done" as a double-value, it will).
Putting the pieces together and dropping a few additional tips in the comments, you could test with something like the following:
#include <stdio.h>
enum { MAXD = 1048 }; /* declare constants instead of using magic numbers */
int main (void) {
double data[MAXD] = {0}; /* in ISO C declarations come before code */
int i, count = 0; /* initializing variable saves debug time */
printf ("\n Welcome! \n\n Please enter each data point. "
"Enter 'done' when finished.\n\n");
for (;;) { /* loop until scanf input fails (with 'done') */
double tmp; /* block scope declarations are fine */
printf (" data[%4d]: ", count);
if (count < MAXD && scanf(" %lf", &tmp) == 1)
data[count++] = tmp;
else
break;
}
printf ("\n %d values entered:\n\n", count);
for (i = 0; i < count; i++)
printf (" data[%4d] : %.2lf\n", i, data[i]);
return 0; /* main() is type 'int' and returns a value */
}
Example Use/Output
$ ./bin/scanfdoubles
Welcome!
Please enter each data point. Enter 'done' when finished.
data[ 0]: 1.1
data[ 1]: 1.2
data[ 2]: 1.3
data[ 3]: 1.4
data[ 4]: 1.5
data[ 5]: 1.6
data[ 6]: done
6 values entered:
data[ 0] : 1.10
data[ 1] : 1.20
data[ 2] : 1.30
data[ 3] : 1.40
data[ 4] : 1.50
data[ 5] : 1.60
Look things over and let me know if you have any questions.
footnotes:
1. while you can use scanf to take user-input in C, you are better off using a line-oriented function (like fgets) and then parsing the complete line (with, e.g. sscanf). The allows you to both (1) validate the read (e.g. the return of fgets) and then (2) separately validate the value entered by the user. This decoupling of your read, and your parsing has many advantages.
No element of data[] will ever be 'done' (they're floats). If you want to scanf() directly, you'll need to choose a double value that ends the sequence (commonly zero or -1 or something). If that won't work, you can either use something like:
Use fgets() to pull a string, then strncmp() to check for the terminating value and sscanf() to pull out the double, or:
Have the user use Ctrl-D to terminate and check the scan value for EOF.
Oh, and strictly speaking you have an upper limit of entries. You should check i to make sure that you don't exceed that. Never assume your input won't exceed boundaries. sizeof() on a statically-allocated variable or some #defined macro to track that.
Your data is of type double. It can't scan a literal "done".
Instead use EOF for checking end of input.
while(scanf("%lf",&data[i]) != EOF) {
...
}
Another way:
while(scanf("%lf",&data[i]) == 1) {
...
}
Another thing, initialize count to zero, i.e. count = 0;
Bottom line: don't use scanf.
Use something like
char inputline[100];
i = 0;
while(fgets(inputline, sizeof(inputline), stdin) != NULL) {
if(strncmp(inputline, "done", 4) == 0) break;
data[i++] = atof(inputline);
}
scanf is hard enough to use even when all your inputs are the numbers you expect. If the input might be either a number or the word "done", scanf will never work. But reading a line of text, as here, is generally easier and more flexible.
P.S. You also have to worry about the possibility that the user enters more than 1048 numbers.
For your task the loop of gathering input should control not only keyword, but also number if inputs. I suggest to do this as follows:
#include <stdio.h>
#include <string.h>
#define NUM_OF_DATA 1048
int main(void)
{
printf("\n Welcome! \n\n Please enter each data point. Enter 'done' when finished.\n\n");
double data[NUM_OF_DATA];
int i; // counter of entered numbers
char str[5] = { 0 }; // string to read 'done' or other word from input
for (i = 0; i < NUM_OF_DATA; i++) // the first index of data in array is 0 (the last NUM_OF_DATA-1)
{
printf("Data[%i]: ", i);
if (1 == scanf("%lf", &data[i])) // if number was successfully read
continue; // go to next iteration
// if some problem was with reading a loat number
// read the string
scanf("%4s", str); // read not more than 4 characters from input
if ( strcmp(str, "done") == 0)
{
break; // stop input if 'done' was entered
}
// clean input buffer before next input
while (getchar() != '\n');
// correct counter in case of wrong input
i--;
}
// output the number of correct inputs
printf("%d numbers were entered.\n", i);
// do something with data
// taking in account, that i is not index of the last element,
// but the number of elements (indexes are 0 ... i-1)
// ...
return 0;
}
This for loop stops in two cases:
1) when data array is full,
2) when 'done' without quotes entered.
Additional feature is skipping of incorrect input (try how it works).
I have a some code, and the function I am having trouble with is this:
unsigned int getInputData() {
printf("Please input a positive integer number terminated with a carriage return.\n");
do{
scanf("%c", &input);
if(isdigit(input)) {
temp = charToInt(input);
rValue = mergeInt(rValue, temp);
}
if(rValue >= imax) {
rValue = 0;
printf("ERROR: That is too large of an integer. Please try again. \n");
}
else if(isalpha(input)){
rValue = 0;
printf("This is not a integer. Please try again. \n");
}
else{
printf("OK. This is a good number. \n");
}
} while(1);
}
I'm scanning in each char individually, merging it into an int. Which is exactly what I want to do BUT I only want it to print "OK. This is a good number." once when the user types it in. Example: If someone was to type in: 12345 I want it to return: "OK. This is a good number." once for those 5 char rather than once each. Hoping this makes sense, been at it for awhile so anything will help.
There's huge logic problems behind your code:
You loop infinitely without checking for end of input:
You say you want to tell whether this is a good number when the user inputs several digits, but you do only read one character at a time, and you do not define how a number ends.
Though you do specify to end with a carriage return, you did not design your algorithm that way, you never check for the \n character.
You define a return value for the getInputData() function but you do never return from that function.
You test whether input is a digit to update the value, but for errors you do show an error only if it's an alphabetic character.
Basically, to keep with the way you wrote your algorithm, here's another take:
unsigned int getInputData() {
char input;
long value=0;
do {
scanf("%c", &input);
if (isdigit(input))
value = value*10+input+'0';
else if (input == '\n')
return 1;
else
return 0;
} while(1);
}
int main() {
printf("Please input a positive integer number terminated with a carriage return.\n");
if (getInputData() == 1)
printf("OK. This is a good number.\n");
else
printf("This is not a integer. Please try again. \n");
return 0;
}
but I do exit from the infinite loop to be able to check the result.
N.B.: for the purpose of the example, I did not check for overflows.
N.B.1: I kept using scanf() to stay close to your code, but if you only want to read one character at a time, it is better to use getchar() which is way simpler and faster.
N.B.2: you can also simplify your code by using more features of scanf():
unsigned int getInputData() {
unsigned input;
long value=0;
int n;
do {
n = scanf("%u", &input);
if (n == 0)
return 0;
else
return 1;
} while(1);
}
You may even try to use scanf("%a[0-9]") which is a GNU extension. See man scanf for more details.
It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
So this is some code I have written, I am barley beginning on c so bear with me, my code makes sense to me but its not working properly, when am trying to say no to stop playing and display average it repeats the playing function.
Basically my program guesses the users number from 1-100 whatever number the user came up with. Here's some output that is wrong, just to give you an idea. The play game function is working fine but not the main.
Playing guess my number game
is your number 50 ?=
Great!
Play again? (y for yes n for no): is your number 50 ?=
Great!
Play again? (y for yes n for no): is your number 50 ?n
and so on i cant find where i went wrong any advice?
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <stdbool.h>
int playgame(void);
main() {
int numberofplays = 0;
float average = 0;
int numberguesses = 0;
printf("Playing guess my number game\n");
printf("-------------------------------\n");
bool play = true;
int xtry = 0;
int totaltries = 0;
char answer;
do {
xtry = playgame();
numberofplays++;
totaltries = totaltries + xtry;
printf("Play again? (y for yes n for no): ");
answer = getchar();
if(answer =='n')
play = false;
} while(play==true);
average = (float)(totaltries/numberofplays);
printf("average is %f tries per game\n",average);
return 0;
}
int playgame(void) {
int guessnumber = 50;
int xnumber = 25;
int count=0;
char x;
bool stillguessing = true;
while(stillguessing == true) {
printf("is your number %d ?", guessnumber);
x = getchar();
if(x=='=') {
count++;
printf("Great!\n");
stillguessing=false;
return count;
}
else if(x == '<') {
guessnumber = guessnumber - xnumber;
xnumber = xnumber/2;
if(xnumber<1) xnumber = 1;
count++;
}
else if (x == '>') {
guessnumber = guessnumber +xnumber;
xnumber = xnumber/2;
if(xnumber<1) xnumber = 1;
count++;
}
}
}
The function getchar pulls a character from the stream stdin.
The stream stdin contains everything that you have entered into the Standard Input device; in your case, this is the keyboard.
Now, when you respond to the computer's guess, you press two keys. You press = and then Enter.
Your code in playgame handles the =, but it leaves the Enter on stdin... thus, your next call to getchar pulls that.
What you need to do is to flush the stdin stream. You can't use fflush(stdin) for this, as fflush is for output streams.
Instead, you can use something like
void flushSTDIN() {
while ((ch = getchar()) != '\n' && ch != EOF);
}
to clear out any old newlines in the buffer, before you ask your question.
You should do this before all calls to getchar in your program.
So:
flushSTDIN();
printf("is your number %d ?", guessnumber);
x = getchar();
Your problem is that getchar() is consuming a single character from the input. However, the input stream always contains at least two characters when you enter a response: the character you enter (such as '=') and the newline (or enter) character that follows it.
This does not matter so much in the playgame() function (although all of the prompts are printed twice), but when you get to
answer = getchar();
this call to getchar() gets the newline that was left over from the previous character you typed.
How you fix this is a question of how you want to handle user input - whether you want to validate it, whether you want to be able to enter longer strings, etc.
In your case, the simplest solution is to replace your calls to getchar() with a loop that will discard whitespace.
I suggest doing the following:
Add the following line at (or near) the start of your program:
#include <ctype.h>
This provides the isspace() function that cleanly and portably checks if a character is whitespace.
Replace the line:
answer = getchar();
with:
while (isspace(answer = getchar()))
;
And similarly, replace
x = getchar();
with:
while (isspace(x = getchar()))
;
The single semicolon is a null statement - something (in this case nothing) has to go in the body of the loop.
Assigning to x/answer within a condition would often be frowned upon, but in this particular case it is the most idiomatic way of writing this.
Note that incorrect macro implementations of isspace() could cause issues by evaluating the call to getchar() multiple times