C-programming loop wont stop with scanf!=0 - c

What is wrong with this ? Also, I have to use scanf(). It is supposed to read any integers and sum them, the loop is to stop when 0 is entered..
main (void){
int a;
int r=0;
while(scanf(" %d",&a)){
r=r+a;
}
printf("the sum is %d\n",r);
return 0;
}

Quoting from man
These functions return the number of input items assigned. This
can be
fewer than provided for, or even zero, in the event of a matching fail-
ure. Zero indicates that, although there was input available, no conver-
sions were assigned; typically this is due to an invalid input character,
such as an alphabetic character for a `%d' conversion.
The value EOF is
returned if an input failure occurs before any conversion such as an end-
of-file occurs. If an error or end-of-file occurs after conversion has
begun, the number of conversions which were successfully completed is
returned.
So, that pretty much explains what is returned by scanf().
You can solve the problem by adding ( 1 == scanf("%d", &a) && a != 0 ) as the condition in your while loop like
int main (void)
{
int a;
int r=0;
while( 1 == scanf("%d", &a) && a != 0 )
{
r=r+a;
}
printf("the sum is %d\n",r);
return 0;
}
Also note that you have to specify the type of main as int main().
I would also like to add that the loop will end when you enter a character like 'c' ( or a string ) and it will show the sum of all the numbers you entered before entering the character.

scanf() doesn't return what it has written to the variable. It returns the total number of items successfully filled.
EDIT:
You would be much better off using fgets() to read from stdin and then using sscanf() to get the integer, which you can check against 0.
#define BUFF_SIZE 1024
int main (void)
{
int a;
int r = 0;
char buffer[BUFF_SIZE] = {0};
while(1) {
fgets(buffer, sizeof buffer, stdin);
sscanf(buffer, "%d", &a);
if(!a)
break;
r = r + a;
}
printf("the sum is %d\n", r);
return 0;
}

Related

Function that prompts user for integer value and checks for valid input

I currently am stuck on a small part of an assignment I need to do.
One requirement of the assignment is
"Call a function that prompts the user for each of the values of the coefficients a, b, and c for the quadratic equation and returns the value entered, with error checking for a valid input (scanf returned a value)."
and I can't figure out how to do this. I can easily prompt the user for input and I can check if it is valid input, but I don't know how to turn this into a function. My current code is:
{
if (isalpha(a))
{
printf("INPUT ERROR!\n");
printf("Enter a value for a: ");
scanf("%d", &a);
}
} //this is how I would normally check the input
int main(void) //start of main() function definition
{
int a, b, c, n, D; //declares integer variables a, b, c, n, and D
float root1, root2; //declares float variables root1 and root2
do //do while loop starts here
{
printf("Enter a value for a: "); //prompts user to input integer for variable 'a'
scanf("%d", &a); //reads an integer from the keyboard and stores in the variable 'a'
printf("%d\n", a); //returns value of integer that was input for variable 'a'
printf("Enter a value for b: "); //prompts user to input integer for variable 'b'
scanf("%d", &b); //reads an integer from the keyboard and stores in the variable 'b'
printf("%d\n", b); //returns value of integer that was input for variable 'b'
printf("Enter a value for c: "); //prompts user to input integer for variable 'c'
scanf("%d", &c); //reads an integer from the keyboard and stores in the variable 'c'
printf("%d\n", c); //returns value of integer that was input for variable 'c'
...}
Sorry for any formatting mistakes, but that is basically the part of the program I am stuck with.
My question is, how can I combine the first function with everything in the do/while loop to make one big function that I can call three times?
I don't know how I'd be able to switch out all the instances of a for b and c using a function, as I've never really had to use a function like this before.
Function that prompts user for integer value and checks for valid input
If users only entered valid integer text on a line-by-line basis, then code is easy:
// Overly idealized case
fputs(prompt, stdout);
char buf[50];
fgets(buf, sizeof buf, stdin);
int i = atoi(buf);
But users are good, bad and ugly and **it happens. If code wants to read a line, parse it for an in-range int, and detect a host of problems, below is code that vets many of the typical issues of bogus and hostile input.
I especially interested in detecting overly long input as hostile and so invalid as a prudent design against hackers. As below, little reason to allow valid input for a 32-bit int with more than 20 characters. This rational deserve a deeper explanation.
End-of-file
Input stream error
Overflow
No leading numeric test
Trailing non-numeric text
Excessive long line
First a line of input is read with fgets() and then various int validation tests applied. If fgets() did not read the whole line, the rest is then read.
#include <limits.h>
#include <ctype.h>
// Max number of `char` to print an `int` is about log10(int_bit_width)
// https://stackoverflow.com/a/44028031/2410359
#define LOG10_2_N 28
#define LOG10_2_D 93
#define INT_DEC_TEXT (1 /*sign*/ + (CHAR_BIT*sizeof(int)-1)*LOG10_2_N/LOG10_2_D + 1)
// Read a line and parse an integer
// Return:
// 1: Success
// 0: Failure
// EOF: End-of-file or stream input error
int my_get_int(int *i) {
// Make room for twice the expected need. This allows for some
// leading/trailing spaces, leading zeros, etc.
// int \n \0
char buf[(INT_DEC_TEXT + 1 + 1) * 2];
if (fgets(buf, sizeof buf, stdin) == NULL) {
*i = 0;
return EOF; // Input is either at end-of-file or a rare input error.
}
int success = 1;
char *endptr;
errno = 0;
long value = strtol(buf, &endptr, 10);
// When `int` is narrower than `long`, add these tests
#if LONG_MIN < INT_MIN || LONG_MAX > INT_MAX
if (value < INT_MIN) {
value = INT_MIN;
errno = ERANGE;
} else if (value > INT_MAX) {
value = INT_MAX;
errno = ERANGE;
}
#endif
*i = (int) value;
if (errno == ERANGE) {
success = 0; // Overflow
}
if (buf == endptr) {
success = 0; // No conversion
}
// Tolerate trailing white-space
// Proper use of `is...()` obliges a `char` get converted to `unsigned char`.
while (isspace((unsigned char ) *endptr)) {
endptr++;
}
// Check for trailing non-white-space
if (*endptr) {
success = 0; // Extra junk
while (*endptr) { // quietly get rest of buffer
endptr++;
}
}
// Was the entire line read?
// Was the null character at the buffer end and the prior wasn't \n?
const size_t last_index = sizeof buf / sizeof buf[0] - 1;
if (endptr == &buf[last_index] && buf[last_index - 1] != '\n') {
// Input is hostile as it is excessively long.
success = 0; // Line too long
// Consume text up to end-of-line
int ch;
while ((ch = fgetc(stdin)) != '\n' && ch != EOF) {
;
}
}
return success;
}
Sample usage
puts("Enter a value for a: ", stdout);
fflush(stdout); // Insure output is seen before input.
int a;
if (my_get_int(&a) == 1) {
printf("a:%d\n", a);
}
My question is, how can I combine the first function with everything in the do/while loop to make one big function that I can call three times?
Well, the function need not be big. The things to factor out are the prompt string and the variable to read - the latter can be left in the calling main() and assigned from a return value. Regarding how you would normally check the input, I recommend leaving this checking to scanf() and just test its return value.
#include <stdio.h>
#include <stdlib.h>
int input(char *prompt)
{ // prompts user to input integer
// reads an integer from standard input and returns it
int a, s; // leave it to scanf to check the input:
while (printf("%s", prompt), fflush(stdout), s = scanf("%d", &a), !s)
{
printf("INPUT ERROR!\n");
do s = getchar(); while (s != '\n' && s != EOF); // consume bad input
}
if (s == EOF) puts(""), exit(0); // no more input
return a;
}
In main() you can then just do
a = input("Enter a value for a: ");
b = input("Enter a value for b: ");
c = input("Enter a value for c: ");
(without a loop).
scanf() already processes the input for you according to the format specifier (%d) so you just need to understand how scanf works and use it to check and build your function :)
When you write scanf("%d", &a); the program expects you write an integer because of the %d specifier, and if an integer is read, the program writes it into variable a.
But the function scanf also has a return value, ie, you can do check = scanf("%d", &a); and check will have a value of 0 or 1 in this case. This is because the return value records how many values have been successfuly read. If you entered dsfugnodg there's no number so it would return 0. If you entered 659 32 it would read the 1st value successfully and return 1.
Your function would look something like:
#include <stdio.h>
int getAndPrint(char label)
{
int n = 0, val = 0;
do {
printf("Enter a value for %c: ", label);
n = scanf("%d", &val);
if (n == 0) {
printf("Error, invalid value entered.\n");
/* Consume whatever character leads the wrong input
* to prevent an infinite loop. See:
* https://stackoverflow.com/questions/1669821/scanf-skips-every-other-while-loop-in-c */
getchar();
}
} while (n == 0);
printf("%c = %d\n", label, val);
return val;
}
int main()
{
int a, b, c;
a = getAndPrint('a');
b = getAndPrint('b');
c = getAndPrint('c');
printf("a=%d, b=%d, c=%d\n", a, b, c);
}
See also:
Scanf skips every other while loop in C
I think the following code is you wanted:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h> // for isalpha
void InputAndCheck(int * pValue, const char * pName)
{
do
{
printf("Enter a value for %s: ", pName);
scanf("%d", pValue);
if (isalpha(*pValue))
{
printf("INPUT ERROR!\n");
continue;
}
else
{
break;
}
} while (1);
// clear the input buffer
fflush(stdin);
return;
}
int main()
{
int a, b, c;
InputAndCheck(&a, "a");
InputAndCheck(&b, "b");
InputAndCheck(&c, "c");
printf("a=%d;b=%d;c=%d;\r\n",a,b,c);
return 0;
}
What you are looking for is an introduction to functions.
Here is one : https://www.tutorialspoint.com/cprogramming/c_functions.htm
This is a very important building block in programming and you should definitely learn to master that concept.
functions will allow you to execute some code in different contexts over and over, just changing the context (the parameters).
It is declared like this
int add(int first, int second){
//here we can use first and second
printf("first: %d\n", first);
printf("second: %d\n", second);
//and eventually return a value
return first+second;
}
Now when using we are reusing our previous code to excute a task which result will vary depending of the arguments we pass.
printf("1+2 = %d\n", add(1, 2));
-->3
printf("2+2 = %d\n", add(2, 2));
-->4
Example solution for your task:
//this will handle validation
int validateInput(int input){
if(isalpha(input)){
printf("INPUT ERROR!\n");
return 0;
}
return 1;
}
//this will prompt the user and return input only if the input is valid
int askForCoefficient(unsigned char coefficientName){
int valid = 0;
int value = 0;
while(!valid){
printf("Enter a value for %c: ", coefficientName);
value = scanf("%d", &value);
valid = validateInput(value);
}
printf("%d\n", value);
return value;
}

Scanf more values C

i need help with short Code in C. I must read floats on input line seperated with space and input is ended with float 0 or EOF.
How to do this if i dont know how many numbers or in input, or how it works and ask to EOF if i am reading just numbers and not chars?
Thanks for any response.
example of input in one line:
12 11 10 45 50 12 EOF
12 10 11 45 0
int main(void)
{
float num;
float sum = 0;
do{
scanf("%f", num);
sum += num;
} while(EOF || num == 0);
return 0;
}
From the man page of scanf -
scanf returns the number of items successfully matched and assigned
which can be fewer than provided for, or even zero in the event of an
early matching failure. The value EOF is returned if the end of input
is reached before either the first successful conversion or a matching
failure occurs.
This means that scanf will return EOF only when it encounters EOF as the first input when it is called because EOF must be preceded with a newline '\n' else it won't work (depending on the OS). You must also account for the matching failure scanf may encounter.
#include <stdio.h>
int main(void) {
float num;
float sum = 0;
int val;
while((val = scanf("%f", &num)) != EOF && val == 1) {
sum += num;
}
if(val == 0) {
printf("matching failure. input is not a float.\n");
}
else {
printf("end of input.\n");
}
return 0;
}
From scanf reference:
On success, the function returns the number of items of the argument
list successfully filled. This count can match the expected number of
items or be less (even zero) due to a matching failure, a reading
error, or the reach of the end-of-file.
If a reading error happens or the end-of-file is reached while
reading, the proper indicator is set (feof or ferror). And, if either
happens before any data could be successfully read, EOF is returned.
If an encoding error happens interpreting wide characters, the
function sets errno to EILSEQ.
So, you may rewrite your do-while loop to something like
int retval;
while((retval = scanf("%f", &num)) != EOF && retval > 0 && num != 0) {
sum += num;
}
if(retval == 0) {
printf("input read error.\n");
}
to match your constraints.
Also note you need to prefix your variable with & when passing it to scanf(), since the function expects a pointer to deal with (you need to pass variable address).
EDIT:
see this topic concerning EOF problems in Windows
You can re write your code like this
int main(void)
{
float num;
float sum = 0;
do
{
scanf("%f", &num);
sum += num;
} while((!feof(stdin)) && (num != 0));
printf("%f", sum);
return 0;
}
Here feof indicates end of input stream.
The following may be a slightly more robust way to do this:
#include <stdio.h>
#include <string.h>
int main(void) {
int sum=0;
int num;
char *p;
char buf[1000];
fgets(buf, 1000, stdin);
p = strtok(buf," ");
while(p!=NULL) {
if(sscanf(p, "%d", &num) == 1) sum+=num;
p = strtok(NULL, " ");
}
printf("the sum is %d\n", sum);
}
Test:
> testme
1 2 3 4 0
the sum is 10
> testme
1 2 3 4 ^D
the sum is 10
Note - you have to enter ctrl-D twice to get the desired effect when you are at the end of a line.
you can get your doubt clear by reading "C programming a modern approach by K N King"
This book provides proper clarification on this topic
Test the result of scanf() for 0, 1 or EOF.
Test the value scanned for 0.0.
int main(void) {
float num;
float sum = 0;
int cnt;
while ((cnt = scanf("%f", &num)) == 1) {
if (num == 0.0) break;
sum += num;
}
// cnt should be EOF, 0 or 1
if (cnt == 0) {
printf("Input is not a number\n");
}
else {
printf("Sum %f\n", sum);
}
return 0;
}
Although, in general, scanf() returns values EOF, 0, 1, ... "number of format specifiers", a value of 0 occurs rarely. Example input is "+".

Infinite loop when assigning a float to an integer

Please i'm having an issue with my program. Whenever i try to input a float it's getting into an infinity loop. I know that the input is stored as an integer. How can prevent the user from entering a float (how to filter the input).
Why is the program getting into an infinite loop when the input is a float.
This is an example:
#include <stdio.h>
main()
{
int i = 0;
while(i<10){
system("cls>null");
printf("%d^2 = %d\n", i, i*i);
printf("Index: ");
scanf("%d", &i);
}
}
When you call scanf to read a number, but the input contains something incompatible with the input format specifier, scanf does not consume such incorrect input, leaving it in the buffer. Your program does not clear the buffer on input mismatch, entering an infinite loop: scanf tries to read an int again, sees that it's not there, and exits without modifying i. Your loop sees that i is less than 10, and calls the scanf again.
To fix this, check that scanf returned one input. Use the input when it is correct, or call scanf again with the %*[^\n]\n specifier, which means "read to the end of the string, and discard the input":
if (scanf("%d", &i) != 1) {
scanf("%*[^\n]\n");
}
Note the asterisk - it means that the consumed input needs to be discarded, rather than being written into a variable.
Better use fgets() to read a complete line from stdin, and strtol()
to parse it into an number, for example:
char buffer[256];
char *endp;
int i;
while (fgets(buffer, sizeof(buffer), stdin) != NULL) {
// buffer now contains one line (including the terminating newline)
i = (int)strtol(buffer, &endp, 10);
// endp points to the first character after the parsed number:
if (endp > buffer && (*endp == 0 || isspace(*endp))) {
printf("%d^2 = %d\n", i, i*i);
} else {
printf("invalid input\n");
}
}
#include <math.h>
#include <stdio.h>
int main (void)
{
int i = 0;
float j = 0;
while(i<10)
{
system("cls");
printf("%d^2 = %d\n", i, i*i);
printf("Index: ");
if (scanf("%f", &j) <= 0 && j-fabs(j) != 0)
{
printf ("The input is not an interger");
}
}
}

How to allow user to exit while loop from terminal?

For example, if I want to write a code to average an unspecified number of numbers that the user enters, how can I make it so that the user can determine the number of numbers? ie. if the user wants to average just three numbers, he types them in one at a time, and then types in something to signal that this is it.
I wrote something like
while(i!=EOF){
printf("type in a number: \n");
scanf("%f",&i);
array[x]=i;
x++;
}
"and then some code to average the numbers in the array".
The idea was that if the user wants to signal that he finished entering numbers, he types in EOF and then the while loop will stop, however this isn't working. When I type in EOF at the terminal, it just writes "type in a number:" indefinitely.
scanf returns information in two different ways: in the variable i, and as its return value. The content of the variable i is the number that scanf reads, if it is able to return a number. The return value from scanf indicates whether it was able to read a number.
Your test i != EOF is fundamentally a type error: you're comparing the error indicator value EOF to a variable designed to hold a floating-point number. The compiler doesn't complain because that is accidentally valid C code: EOF is encoded as an integer value, and that value is converted to a floating-point value to perform the comparison. In fact, you'll notice that if you enter -1 at the prompt, the loop will terminate. -1 is the value of the EOF constant (on most implementations).
You should store the return value of scanf, and store it into a separate variable. If the return value is EOF, terminate the loop. If the return value is 1, you have successfully read a floating-point value.
If the return value is 0, the user typed something that couldn't be parsed. You need to handle this case appropriately: if you do nothing, the user's input is not discarded and your program will loop forever. Two choices that make sense are to discard one character, or the whole line (I'll do the latter).
double i;
double array[42];
int x = 0;
int r = 0;
while (r != EOF) {
printf("type in a number: \n");
r = scanf("%f", &i);
if (r == 1) {
/* Read a number successfully */
array[x] = i;
x++;
} else if (r == 0) {
printf("Invalid number, try again.\n");
scanf("%*[^\n]"); /* Discard all characters until the next newline */
}
}
You should also check that x doesn't overflow the bounds of the array. I am leaving this as an exercise.
I want to do it by typing in something that's not a number
Then get the input as a string, and exit if it cannot be converted to a number.
char buf[0x80];
do {
fgets(buf, sizeof(buf), stdin);
if (isdigit(buf[0])) {
array[x++] = strtod(buf);
}
} while(isdigit(buf[0]);
In case of no input scanf() does not set i to EOF but rather can return EOF. So you should analyze scanf() return code. By the way you can receive 0 as result which actually means there is no EOF but number cannot be read.
Here is example for you:
#include <stdio.h>
#define MAX_SIZE 5
int main()
{
int array[MAX_SIZE];
int x = 0;
int r = 0;
while (x < MAX_SIZE)
{
int i = 0;
printf("type in a number: \n");
r = scanf("%d",&i);
if (r == 0)
{
printf("ERROR!\n");
break;
}
if (r == EOF)
{
printf("EOF!\n");
break;
}
array[x]=i;
x++;
}
}
You cannot write 'EOF'.. since you are reading into a number...
EOF equals -1.. so if he enterd that, the loop would stop
You can test for the return value of the scanf function. It returns EOF on matching failure or encountering an EOF character.
printf("type in a number:" \n);
while(scanf("%f",&i)!=EOF){
array[x]=i;
x++;
printf("type in a number:" \n);
}

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

Resources