How to loop scanf_s() until success? - c

#include <stdio.h>
int main(){
float x,y;
printf("Enter 2 numbers: \n");
scanf_s("%f %f", &x, &y);
if (getchar() == '\n')
{
printf("Division: %f\n", x / y);
printf("Product: %f\n", x * y);
printf("Sum: %f\n", x + y);
printf("Difference: %f\n", x - y);
}
else
{
printf("no Float-Value!");
}
getchar();
return 0;
}
we need to get a loop in so if we enter the wrong format the program should ask again to enter two numbers

The best way of checking the validity of the input is to check the return value of scanf_s which tells you the number of variables that were successfully set. In your case, if it's 2 then all is well; otherwise you need to repeat.
In other words
do {
int c;
while ((c = getchar()) != '\n' && c != EOF); // clear the input stream
printf("Enter 2 numbers: \n");
} while (scanf_s("%f %f", &x, &y) != 2);
is an appropriate control structure, rather than if (getchar() == '\n'), which you should drop.

What I don't like about using scanf family of functions is that it will go berserk and crash your program when you input something wrong. For example, if you have scanf("%f", &a), try inputing stack overflow. It goes nuts!
So, as I said in the comments, I think you should build your own validating function, and get user input as just a string using fgets.
Here is a simple code that will get you started in it. This is very ugly code and you should refactor it.
#include <stdio.h> /* printf, fgets */
#include <ctype.h> /* isdigit, isspace */
#include <string.h> /* strlen */
int is_valid_float(char *s, int len)
{
int i;
for(i = 0; i < len; i++) {
/* floats may have a decimal point */
if(s[i] == '.') continue;
/* spaces should be ignored, since they separete the nubmers */
if(isspace(s[i])) continue;
/* is there's anything besides a number, we abort */
if(!isdigit(s[i])) return 0;
}
/* if we got here, then the input contains two valid floats.
*
* Does it? Test it!
*/
return 1;
}
int main(void)
{
float a, b;
char buf[100];
int len;
do {
fprintf(stderr, "Enter A and B: ");
fgets(buf, sizeof buf, stdin);
/* fgets will store a newline at the end of the string, we
* just overwrite it with a null terminator
*
* Thanks to #chux for the strcspn() suggestion.
*/
buf[strcspn(buf, "\n")] = 0;
} while(!is_valid_float(buf, len));
/* now, after we know the string is valid and won't cause scanf to go
* berserk, we can use it in our validated string.
*
* Here is where you should really take a moment and look at the
* validation function and improve it. Not valid strings will cause
* your program to go nuts.
*/
sscanf(buf, "%f %f", &a, &b);
/* Did it scan the numbers correctly? */
printf("A: %f\n", a);
printf("B: %f\n", b);
return 0;
}

Related

How to make "overloaded" scanf in C?

Friends how can I make Scanf to take 1 or 2 or 3 numbers depending on input data I give?
sample data 1: "1 2 5"
sample data 2: "1 4"
sample data 3: "4"
if(scanf("%lf",&a)==1 )
{
printf("1 input num\n");
}
else if(scanf(" %lf %lf",&a, &b)==2 )
{
printf("2 input num\n");
}
else if(scanf("%lf %lf %lf",&a, &b, &c)==3 )
{
printf("3 input num\n");
}else
{
printf("Error message.\n");
return 1;
}
You might consider this an answer:
int InputNums=0;
InputNums = scanf("%lf %lf %lf",&a, &b, &c);
if(InputNums!=0)
printf("%d input num\n");
else
printf("Error message.\n");
It works by NOT eating one number and then trying whether instead more numbers could have been read, like your shown code does.
Instead try to read three numbers and then let scanf() tell you how many worked.
But actually I am with the commenters. If you do not have guaranteed syntax in your input (which scanf() is for) then use something else.
This is nicely describing which alternative in which situation AND how to get scanf to work in the same situation:
http://sekrit.de/webdocs/c/beginners-guide-away-from-scanf.html
Scanf already does this for you, and indeed you used the same scanf function with a variable number of arguments. You can look here: How do vararg work in C?
However you don't need to overload scanf, but rather pass to it a string telling what you need to scan. You can do this dynamically by changing the string at runtime.
The code to try is the following:
#include <stdio.h>
int main()
{
char one[] = "%d";
char two[] = "%d%d";
int o1;
int t1,t2;
scanf(one,&o1);
scanf(two,&t1,&t2);
printf("%d %d %d",o1,t1,t2);
return 0;
}
If you must use scanf() ....
"%lf" is a problem as it consumes leading white-space including '\n', so we lost where a line of input might have ended.
Instead first look for leading white-space and see if an '\n' occurs.
#define N 3
double a[N];
count = 0;
while (count < N) {
// Consume leading white-spaces except \n
unsigned char ch = 0;
while (scanf("%c", &ch) == 1 && isspace(ch) && ch != '\n') {
;
}
if (ch == '\n') {
break;
}
// put it back into stdin
ungetc(ch, stdin);
if (scanf("%lf", &a[count]) != 1)) {
break; // EOF or non-numeric text
}
count++;
}
printf("%d values read\n", count);
for (int i=0; i<count; i++) {
printf("%g\n", a[i]);
}
Alterantive to consume various multiple leading whitespaces that only uses scanf() with no ungetc():
// Consume the usual white spaces except \n
scanf("%*[ \t\r\f\v]");
char eol[2];
if (scanf("%1[\n]", eol) == 1) {
break;
}
If the line contains more than N numbers or non-numeric text, some more code needed to report and handle that.
The best solution to problems with scanf and fscanf is usually to use something other than scanf or fscanf. These are remarkably powerful functions, really, but also very difficult to use successfully to handle non-uniform data, including not only variable data but data that may be erronious. They also have numerous quirks and gotchas that, though well documented, regularly trip people up.
Although sscanf() shares many of the characteristics of the other two, it turns out often to be easier to work with in practice. In particular, combining fgets() to read one line at a time with sscanf() to scan the contents of the resulting line is often a convenient workaround for line-based inputs.
For example, if the question is about reading one, two, or three inputs appearing on the same line, then one might approach it this way:
char line[1024]; // 1024 may be overkill, but see below
if (fgets(line, sizeof line, stdin) != NULL) { // else I/O error or end-of-file
double a, b, c;
int n = sscanf(line, "%lf%lf%lf", &a, &b, &c);
if (n < 0) {
puts("Empty or invalid line");
} else {
printf("%d input num\n", n);
}
}
Beware, however, that the above may behave surprisingly if any input line is longer than 1023 characters. It is possible to deal with that, but more complicated code is required.
here is an example of using fgets, strtok and atof to achieve same:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main() {
char input[256];
double inputsf[256];
while(1) {
printf(">>> "); fflush(stdout);
char *s = fgets(input, 255, stdin);
if (!s)
break;
int count = 0;
char *t;
while (t = strtok(s, " \n")) {
s = NULL;
inputsf[count++] = atof(t);
}
printf("Found %d inputs\n", count);
for (int i = 0; i < count; i++)
printf(" %lf\n", inputsf[i]);
if (count == 0)
break;
}
return 0;
}
Bases on the #chux-ReinstateMonica comment, here is a piece of code which uses strtod. It skips leading spaces, but has an issue with the tailing spaces at the end of the string. So, some extra checking is needed there, which could be used for error checking as well. The following loop can replace the strtok loop from above.
while(*s) {
char *e;
double val = strtod(s, &e);
if (e == s)
break; // not possible to parse, break the loop
inputsf[count++] = val;
s = e;
}
You can solve your problem using those line of code
#include <stdio.h>
int main(){
int a[100];
int n;
printf("How many data you want to input: ");
scanf("%d", &n);
printf("Sample %d data Input: ", n);
for (int i=0; i <n; i++) {
scanf("%d", &a[i]);
}
printf("Sample data %d: ", n);
for (int i=0; i <n; i++) {
printf("%d ", a[i]);
}
if(n == 1){
printf("\n 1 input num\n");
}else if(n==2){
printf("2 input num\n");
}else if(n==3){
printf("3 input num\n");
}else{
printf("Error");
}
return 0;
}
if you want to take multiple input in single line use this line
int arr[100];
scanf ("%lf %lf %lf", &arr[0], &arr[1], &arr[2]);

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

for-loop stuck in endless loop [duplicate]

I have never programmed in C and today I have to write small code. Program is very easy - I want to add two integers.
But when I'm trying to check if given input is a number and first scanf returns 0, the second one returns 0 too without waiting for input.
Code:
int main()
{
int a = 0;
int b = 0;
printf("Number a:\n");
if (scanf("%d", &a) != 1)
{
printf("Not a number. a=0!\n");
a = 0;
}
printf("Number b:\n");
if (scanf("%d", &b) != 1)
{
printf("Not a number. b=0!\n");
b = 0;
}
printf("%d\n", a+b);
return 0;
}
The input that failed to convert to a number for the first fscanf() is still pending in standard input's buffer and causes the second fscanf() to fail as well. Try discarding offending input and re-prompting the user:
#include <stdio.h>
int main(void) {
int a = 0;
int b = 0;
int c;
printf("Number a:\n");
while (scanf("%d", &a) != 1) {
printf("Not a number, try again:\n");
while ((c = getchar()) != EOF && c != '\n')
continue;
if (c == EOF)
exit(1);
}
printf("Number b:\n");
while (scanf("%d", &b) != 1) {
printf("Not a number, try again:\n");
while ((c = getchar()) != EOF && c != '\n')
continue;
if (c == EOF)
exit(1);
}
printf("%d\n", a + b);
return 0;
}
Factorizing the code with a utility function makes it much clearer:
#include <stdio.h>
int get_number(const char *prompt, int *valp) {
printf("%s:\n", prompt);
while (scanf("%d", valp) != 1) {
printf("Not a number, try again:\n");
while ((c = getchar()) != EOF && c != '\n')
continue;
if (c == EOF)
return 0;
}
return 1;
}
int main(void) {
int a, b;
if (!get_number("Number a", &a) || !get_number("Number b", &b)) {
return 1;
}
printf("%d\n", a + b);
return 0;
}
That is because, once the first scanf() failed, it is probably because of matching failure, and the input which caused the matching failure, remains inside the input buffer, waiting to be consumed by next call.
Thus, the next call to scanf() also try to consume the same invalid input residing in the input buffer immediately, without waiting for the explicit external user input as the input buffer is not empty.
Solution: After the first input fails for scanf(), you have to clean up the input buffer, for a trivial example, something like while (getchar() != '\n'); should do the job.
This happens if there is any input from the previous entry, can take that, and skip input from the user. In the next scanf also It takes the new line which is left from the last scanf statement and automatically consumes it. That's what happening in your code.
You can clear previous input in stdin stream by using fflush(stdin); before starting your program.
This can also be solved by leaving a space before % i.e scanf(" %d",&n);,Here leaving whitespace ensures that the previous new line is ignored.
Or we can use getc(stdin) before calling any scanf statement, Sometimes it helps very much.
int main()
{
int a = 0;
int b = 0;
printf("Number a:");
//getc(stdin);
if (scanf(" %d", &a) != 1)
{
printf("Not a number. a=0!\n");
a = 0;
}
printf("Number b:\n");
//getc(stdin);
if (scanf(" %d", &b) != 1)
{
printf("Not a number. b=0!\n");
b = 0;
}
printf("%d\n", a+b);
return 0;
}
It's because of input and output aren't synchronized in C. The program can output some lines after user's input while the input hasn't been read. Try to run this code:
char token;
scanf("%c", &token);
printf("%c\n", token);
printf("line 1\n");
scanf("%c", &token);
printf("%c\n", token);
printf("line 2\n");
scanf("%c", &token);
printf("%c\n", token);
printf("line 3\n");
And input abc in one line.
You can imagine this like there are two separated consoles, one for input and another for output.
For example you want to input asd for a and 3 for b. In this case, the first scanf won't find any number and will return 0. But it also won't read anything from the input. Because of this, the second scanf will see asd too.
To clear the input if a isn't a number, you should input all remaining chars in the line until '\n' (look at the #Sourav's solution)
You could do the same thing using strings without problems with scanf. Just take the user input as string and convert it to integer. Then convert the string back to integer to check whether they are the same. If they are the same, treat a and b as integers, if not, do what you do (You will need to include string.h). Here is the working code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int a;
int b;
char str1[100];
char str2[100];
printf("Number a:\n");
scanf("%s", &str1); //take input as a string
a = atoi(str1); //convert string to integer
snprintf(str2, 100, "%d", a); //convert integer back to string
//if the integer converted to string is not the same as the string converted to integer
if (strcmp(str1, str2)!= 0)
{
printf("Not a number. a=0!\n");
a = 0;
}
printf("Number b:\n");
scanf("%s", &str1);
b = atoi(str1);
snprintf(str2, 100, "%d", b);
if (strcmp(str1, str2)!= 0)
{
printf("Not a number. b=0!\n");
b = 0;
}
printf("%d\n", a+b);
return(0);
}

Converting string value to int equivalent in C

Can someone tell me what's wrong with this:
int main()
{
char a[100];
int i = 0;
printf("Enter a number: ");
scanf("%c", &a[i]);
printf("The number you've entered is: %d", a[i] - '0');
}
Brief summary: I am trying to convert a number stored in a char array to its int equivalent. I know in C#, you use the intparse command, but because there isn't such one in C, I do not know what to do. When I input a two digit number, it is only outputting the first digit, of the input char.
strtol sample
#include <stdio.h>
#include <stdlib.h>
int main(){
char str[16], *endp;
int value;
printf("Enter a number: ");
fgets(str, sizeof(str), stdin);
value = strtol(str, &endp, 0);
if(*endp == '\n' || *endp == '\0'){
printf("The number you've entered is: %d\n", value);
} else {
printf("invalid number format!");
}
return 0;
}
If you mean to print ASCII value of char the no need to do a[i] - '0'.
Try this
printf("The number you've entered is: %d", a[i]);
If you are talking about string then first change your scanf statement to
scanf("%s", a);
or better to use fgets library function instead of scanf;
fgets(a, sizeof(a), stdin);
and then use strtol function.
OP method of scanf("%c", &a[i]); only handles a 1 character input.
To read the entire line, suggest using fgets() to read.
The convert to a long using strtol().
Watch for potential errors.
#include <stdio.h>
#include <stdlib.h>
int main(){
// use long to match strtol()
long i;
// size buffer to handle any legitimate input
char a[sizeof i * 3 + 3];
char *endptr;
printf("Enter a number: ");
if (fgets(a, sizeof a, stdin) == NULL) {
// If you would like to handle uncommon events ...
puts("EOForIOError");
return 1;
}
errno = 0;
i = strtol(str, &endptr, 10);
if(*endptr != '\n' /* text after number */ ||
endp == a /* no text */ ||
errno /* overflow */) {
printf("Invalid number %s", a);
}
else {
printf("The number you've entered is: %ld\n", i);
}
return 0;
}
Try
char myarray[5] = {'-', '4', '9', '3', '\0'};
int i;
sscanf(myarray, "%d", &i); // i will be -493
Edit (borrowed from [1]):
There is a wonderful question here on the site that explains and compares 3 different ways to do it - atoi, sscanf and strtol. Also, there is a nice more-detailed insight into sscanf (actually, the whole family of *scanf functions).
#include<stdio.h>
#include<stdlib.h>
int main()
{
char a[100];
int final=0,integer;
int i;
printf("Enter a number: ");
gets(a);
for(i=0;a[i]>='0'&&a[i]<='9';++i)
{
integer=a[i] - '0';
final=final*10+integer;
}
enter code here
printf("The integer is %d ", final);
}

How to use arbitrary number of scanf() format specifiers?

I want to use infinite type specifiers (%d) in scanf() function.
For example-
printf("Enter numbers: \t");
scanf("--%d SPECIFIERS--");
So its not definite how many nos. the user will enter. I don't want my program to ask the user the 'numbers of characters'.. but I want to allow any the numbers of characters. But its not possible to enter infinite %d in scanf().
So can anyone please tell what is the C program of finding average of numbers given by the user (if you dont know how much nos. the user will give and you don't want the program to ask 'how many numbers.')?
This is tricky. 2 approaches
1 - fgets() Read 1 line, then parse
char buffer[1000];
int count = 0;
double sum = 0;
int num;
fgets(buffer, sizeof buffer, stdin);
const char *p = buffer;
int n;
while (sscanf(p, "%d%n", &num, &n) == 1) {
p += n;
; // do something with `num`
sum += num;
count++;
}
printf("Average %f\n", sum/count);
2 - Lets say you infinite input ends with the end-of-line. Now the problem is that %d will consume all leading whitespace, including \n. Thus we need to consume and test all whitespace beforehand
int count = 0;
double sum = 0;
int num;
for (;;) {
int ws = 0;
while (isspace(ws = fgetc(stdin)) && (ws != '\n'));
if (ws == '\n') break;
ungetc(ws, stdin);
if (scanf("%d", &num) != 1) break;
; // do something with num
sum += num;
count++;
}
printf("Average %f\n", sum/count);
If you really interested in infinite number of inputs the just try this
while(1)
{
printf("Enter numbers: \t");
scanf("%d", number);
}
It will take input until you forcibly close your program!
But does it make any sense of doing this ?
You should have some way of knowing where the input ends. There are many ways for it and each has a possibly different solution. The two most common ones would be:
Input finishes at end-of-line
The solution is to read one line and then parse the line to get your numbers until the line ends.
This has the benefit that the program could ask for other input afterwards for other parts of the program. The disadvantage is that the user has to input all the numbers in the same line.
Input finishes at end-of-file
Simply loop, reading one number until end of file:
while (scanf("%d", &num) == 1)
/* do something with num */
Note: the user can enter end-of-file in a Linux console with Ctrl+D
If the user input is always numbers separeted by spaces and then at the end is an enter (newline). Then you can use the following code
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int input;
char c;
while (scanf(" %d%c", &input, &c) == 2 ) {
printf("number is %d\n", input);
if ( c == '\n') break;
}
}
If the use want to communicate the number of input as argument
int main(int argc, char *argv[])
{
int number_of_input = atoi(argv[1]);
int input, i;
for (i=0; i<number_of_input; i++) {
scanf(" %d", &input);
}
}
and when you call you program. you call it in this way:
$ myprogram 5
and 5 here is the number of the integer that you can input
myprogram will be saved in argv[0]
5 will be saved in argv[1]
myprogram and 5 are saved as sting in the argv[] array. atoi(argv[1]) will convert the "5" as string to 5 as integer
you can make the user enter an infinite integer input in this way too:
int main(int argc, char *argv[])
{
int input, i;
while (1) {
scanf(" %d", &input);
}
}
And you can give the user a way to stop this infinite loop:
int main(int argc, char *argv[])
{
int input;
while (scanf(" %d", &input) != EOF) {
//....
}
}
here you can stop the infinite loop with
EOF = CTRL + D (for Linux)
EOF = CTRL + Z (for Windows)
At first reading, the solution to a problem like this is to loop until the user inputs a "done" character. This could be a letter Q for example. By reading in the input as a string you can process both numbers and letters. The code below processes one input at a time (followed by ) - with the possibility to either Quit (terminate program), or Clear (restart calculation, keep program running):
printf("Enter numbers to average. Type Q to quit, or C to clear calculation.\n");
char buf[256];
double sum=0, temp;
int ii = 0;
while(1)
{
printf("Input: \t");
fgets(buf, 255, stdin);
if (tolower(buf[0])=='q') break;
// allow user to "clear" input and start again:
if (tolower(buf[0])=='c') {
sum = 0;
ii = 0;
printf("Calculation cleared; ready for new input\n");
continue;
}
ii++;
sscanf(buf, "%lf", &temp);
sum += temp;
printf("At this point the average is %lf\n", sum / (double)ii);
}
printf("Done. The final average of the %d numbers is %lf\n", ii, sum / ii);
EDIT Following some back-and-forth in the comments to this and other answers, here is a solution that addresses your problem. Code has been tested - it compiles, runs, gives expected results:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void){
double sum=0;
int ii=0;
char buf[256], *temp;
char *token;
printf("Enter the numbers to average on a single line, separated by space, then press <ENTER>\n");
fgets(buf, 255, stdin);
temp = buf;
while((token=strtok(temp, " ")) != NULL) {
temp = NULL; // after the first call to strtok, want to call it with first argument = NULL
sum += atof(token);
ii++;
printf("Next token read is number %d: '%s'\n", ii, token); // so you see what is going on
// remove in final code!!
}
printf("AVERAGE: ***** %lf *****\n", sum / (double)ii);
return 0;
}
One more edit If you want to use getline instead (which you asked about in the comments - and it's even safer than fgets since it will increase the buffer size as needed), you would change to change the code a little bit. I am just giving some of the pertinent lines - you can figure out the rest, I'm sure:
double sum=0;
char *buf, *temp; // declaring buf as a pointer, not an array
int nBytes = 256; // need size in a variable so we can pass pointer to getline()
buf = malloc(nBytes); // "suggested" size of buffer
printf("Enter numbers to average on a single line, separated with spaces\n")
if (getline(&buf, &nBytes, stdin) > 0) {
temp = buf;
// rest of code as before
}
else {
// error reading from input: warn user
}
I am sure you can figure it out from here...

Resources