This is the problem:Your program is to use the brute-force approach in order to find the Answer to Life, the Universe, and Everything. More precisely... rewrite small numbers from input to output. Stop processing input after reading in the number 42. All numbers at input are integers of one or two digits.
Input:
1
2
88
42
99
My first code doesn't work:
while( scanf("%d\n", &n) != 42 ){
printf("%d\n",n);
}
second code, with for loop, works but there is a test case where there is no number 42 so it returns TLE, how do I check for end of input?
for(i=1;i>0;i++){
scanf("%d\n",&n);
if(n!=42 ){ /* end of input??? */
printf("%d\n",n);
}
else {
break;
}
}
And why doesn't while loop work like it should?
scanf returns the number of characters scanned, not the result.
So, write while loop as follows:
scanf("%d", &n);
while( n != 42 ){
printf("%d\n",n);
scanf("%d", &n);
}
Always good to avoid magic numbers. Define a constant.
Check the result of scanf() (#Joachim Pileborg)
To check if the input is valid , test if scanf() result is 1 (1 format specifier correctly scanned).
To check for end of input, test if scanf() result is EOF.
while loop failure is well explained by #dbasic. Roughly, scanf() reports the number of fields scanned, not the value scanned.
There is a lot to scanf(). If up to it, read the scanf() section of the C spec. Where do I find the current C or C++ standard documents?
const int Answer_to_Life_the_Universe_and_Everything = 42;
int n;
int cnt;
// Use 2d to limit to 2 digits
while ((cnt = scanf("%2d\n",&n)) == 1) {
if(n != Answer_to_Life_the_Universe_and_Everything) { /* end of input? */
printf("%d\n",n);
}
else {
break;
}
}
if (cnt != EOF) Handle_UnexpectedInput(); // example someone type in "junk"
Related
I am trying to create program which checks if input from user is a number. This works fine for all of the number and charatcers entered, except for numbers in range of 48 to 57. I've been looking through StackOverflow forum and could not find the answer. Could you please advise, what I am doing wrong?
Here is my code:
#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
int main(){
int tab[100];
int input;
int index = 0,count=0;
printf("Podaj liczby:\n");
do{
scanf("%i", &input);
if(!isdigit(input)){
if(input!=0){
tab[index] = (int)input;
index++;
}
}else{
printf("Incorrect input");
return 1;
}
}while(input!=0 && index<100);
if(index<2){
printf("not enough data available");
return 2;
}
for(int i = 0; i <index; i++){
count = 0;
for(int j = i+1;j< index; j++){
if((tab[i] == tab[j]) && tab[i]!=0) {
count++;
tab[j] = 0;
}
}
if(count>0){
printf("%i ",tab[i]);
}
}
return 0;
}
scanf("%i", &input);
scanf with the format %i converts its input to an integer. If the user presses 4 2 Enter, that makes the scanf call equivalent to input = 42.
If the input can't be converted to an integer, scanf returns EOF and doesn't set input. Since you don't check the return value of scanf, your program continues with an indeterminate value in input. (In theory that's undefined behavior, but in practice your program will run with whatever happened to be in the memory location of input.)
if(!isdigit(input)){
This tests whether the number input is the numerical code of a digit character. In practice, the correspondence between characters and their numerical codes on your computer is ASCII, so digits occupy the range from 48 to 57 inclusive. So the body of this if clause only runs if input is not between 48 and 57.
I have no idea why you'd do that. If you meant to check whether the input is valid, check the return value of scanf. If you thought you were checking the first character of the input, then 1. no you aren't, you're checking the result of the conversion, you can't access the raw input from the user; and 2. you'd only be checking one character anyway so your check couldn't possibly be correct.
The if(!isdigit(input)) clause is checking whether input is a digit, and it jumps to the else part if it is. So, if this was ever going to work, you would have to get rid of the '!' operator.
Which leaves us with the next problem: you are using scanf() to read ints. There is no more checking to be done to see whether an int is a number. An int is already a number.
But what you do, is that you treat the int as a char and pass it to isdigit(), which will of course only succeed if the char is between 0 and 9, which corresponds to int numbers between 48 and 57. So, only these numbers succeed, and then you negate the result of isdigit(), so you think that only these numbers fail.
Long story short: quit checking whether your numbers are numbers, they are already numbers.
How do I print invalid when someone enter big or small letters, because supposedly they only enter floats between 0 to 10.
I tried coding like this
It went so wrong.
#include<stdio.h>
int main()
{
int trial=0;
float judge1=0,judge2,judge3,judge4,judge5;
char a;
printf("\n%90s","Welcome to the constentant score calculator program :)");
printf("\n\n\n\n\n\rKindly enter the constentant score by 5 respected
judges:");
do
{
printf("\n\nScore by JUDGE 1 (0-10):\t");
scanf("%f",&judge1);
if ((judge1>-1)&& (judge1<11) )
printf("The constentant got %.2f from the judge",judge1);
else
printf("\aPlease input a valid score between 0 and 10:");
} while ((judge1<0) || (judge1>10)||(judge1=a>96) && (judge1=a<123)||
(judge1=a<91) && (judge1=a>64));
}
okay this is my second code
#include<stdio.h>
int main()
{
float judge1;
printf("\n%90s","Welcome to the constentant score calculator program :)");
printf("\n\n\n\n\n\rKindly enter the constentant score by 5 respected
judges:");
printf("\n\nScore by JUDGE 1 (0-10):\t");
scanf("%f",&judge1);
if ((judge1>-1) && (judge1<11))
printf("The constentant got %.2f from the judge",judge1);
else
printf("\aPlease input a valid score between 0 and 10:");
}
}
When you use the "%f" as the format string for scanf, it will read only characters that are valid for a floating point type and will stop reading if it detects any other characters. So if someone types "abc", nothing is written to judge1 and those characters are left in the input buffer to be read again. You'll then get stuck in an infinite loop reading those same characters.
Also, this expression doesn't make sense:
judge1=a>96
> has higher precedence than ==, so it is equivalent to:
judge1=(a>96)
Assuming a is assigned a value, a>96 compares that value with 96 and evaluates to either 0 or 1. Then you assign this value to judge1, overwriting what was read from the user. Assuming you meant to use == this doesn't make sense either. That being the case, either judge1==0 or judge1==1 is evaluated depending on the result of a>96. So the above expression will only be true if judge1 is 1 and a is greater than 96 or judge1 is 0 and a is less than or equal to 96.
Another problem is that a is never assigned a value. You seem to be under the impression that when you call scanf("%f",&judge1); that the first character read is written to a. There is no link that causes that to happen, so a is left uninitialized.
What you want to do instead is read in a line of text using fgets, then using strtof to read a float. The strtof function accepts the address of a pointer as the second parameter to let you know where in the string the parsing stopped. So if this pointer does not point to the null terminator at the end of the string (or to a newline character, since fgets reads and stores the newline), then you know you read a non-float character.
float judge1;
char line[100];
char *p;
int invalid_input;
do {
invalid_input = 0;
fgets(line, sizeof(line), stdin);
errno = 0;
judge1 = strtof(line, &p);
if (errno || ((*p != 0) && (*p != '\n')) || (judge1 < 0) || (judge1 > 10)) {
printf("Please input a valid score between 0 and 10:");
invalid_input = 1;
} else {
printf("The constentant got %.2f from the judge\n ",judge1);
}
} while (invalid_input);
First, check the return value of scanf. If it fails to match the item it will return 0. Then you can check whether the number entered is within bounds:
int r, judge1;
...
r = scanf("%d", &judge1);
if(r != 1)
{
printf("invalid input\n");
while((r = fgetc(stdin)) != EOF && r != '\n');
}
else if((judge1 < 0) || (judge1 > 10))
printf("input out of range\n");
else
printf("valid input\n");
The problem is you have the bad charachter stuck in the stream. The solution is here:
scanf fails why?.
The suggested thing to do from John Bode is to use a getchar to get it out. Also apply the check mnistic suggested and it should work.
it doesn't offer anything and it only messes with the greater picture.
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.