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]);
Related
I want to write a program, at first I input a number N, then I want to get the name (can consist of multiple words) and price of N items one by one. Example:
3
item a // the name can consist of multiple words
25.00
item b
12.50
item c
8.12
Next I want to process this data, however i got stuck on the scanning part. my code looks like this:
#include <stdio.h>
int main(){
int n;
char name[50];
int price;
scanf("%d\n", &n);
for(int i = 0; i < n; i++){
scanf("%s\n%d",name,&price);
printf("%s , %d", name, price);
}
printf("end");
}
This works for a single word item, but if the item has a space in it will not continue scanning. I tried using the gets() function, however I still don't have the right result. the code:
for(int i = 0; i < n; i++){
gets(name);
scanf("%d\n",&price);
printf("%s , %d\n", name, price);
}
printf("end");
returns:
3 // Input 3 items
item a // name of first item
1 // price of item 1
item b // name of item 2
item a , 1 // the print of the first item
2 // price of item 2
item c // name of item 3
item b , 2 // print of item 2
3 // price of item 3
word // no clue where this new input came from
end // end of scanning
My question is, how would I go about correctly scanning an input such as this? I also tried changing the scan function into while((c = getchar()) != '\n');, but got the same result...
Mixing gets(), scanf() is bad as scanf() tends to leave the trailing '\n' in stdin.
Using gets() is bad.
scanf("%s", ...) is not useful for reading a line of info with spaces meant to be saved.
how would I go about correctly scanning an input such as this?
A simple alternative is to read each line into a string and then parse the string.
#include <stdio.h>
int main() {
char line[100];
int n;
fgets(line, sizeof line, stdin);
sscanf(line, "%d", &n);
for(int i = 0; i < n; i++){
char name[50];
// int price;
double price;
fgets(line, sizeof line, stdin);
sscanf(line, " %49[^\n]", name);
fgets(line, sizeof line, stdin);
// sscanf(line, "%d", &price);
sscanf(line, "%lf", &price);
printf("%s , %.2f\n", name, price);
}
printf("end");
}
Advanced: Better code would check the return values of fgets(), sscanf(). Maybe replace sscanf(line, "%lf",... with strtod().
I think you could probably figure out what's happening here pretty easily if you added some more output. Let's try shall we?
Also, first of all you're really looking for a double input - not an integer. With an integer, your scan function won't match properly based on what you're looking for. But let's add some more output!
#include <stdio.h>
int main()
{
int n;
char name[50];
double price;
printf("Enter count: ");
scanf("%d", &n);
for (int i = 0; i < n; i++) {
printf("%s\n", "Please type a name followed by a newline followed by a number and then press enter:");
scanf("%s\n%lf", name, &price);
printf("%s , %lf", name, price);
}
return 0;
}
So I think what was happening in your initial attempt was a combination of things. Mostly that you were possibly pressing enter after the output from the first iteration? That will break the scanf call - since it isn't expecting to start with a \n but it is immediately expecting you to enter a name.
Second, I don't know the number you entered in the first iteration, because you didn't supply the output of it while still using scanf - so I have nothing other than speculation. You possibly used an integer on the first go, and subsequently on the remaining iterations you chose to use decimals? Again, this is only a guess.
Sometimes it is easier to just write your own functions with error checking. Below is a suggestion. You may also want to check that the numbers are non-negative.
#include <assert.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
void ReadLine(char result[], int resultLen)
{
int ch, i;
assert(resultLen > 0);
i = 0;
ch = getchar();
while ((ch != '\n') && (ch != EOF)) {
if (i < resultLen - 1) {
result[i] = ch;
i++;
}
ch = getchar();
}
result[i] = '\0';
}
void ReadInteger(int *i)
{
int ch, count;
count = scanf("%d", i);
if (count == 1) {
do {
ch = getchar();
} while (isspace(ch) && (ch != '\n'));
} else {
fprintf(stderr, "invalid input, integer expected\n");
exit(EXIT_FAILURE);
}
}
void ReadReal(double *x)
{
int ch, count;
count = scanf("%lf", x);
if (count == 1) {
do {
ch = getchar();
} while (isspace(ch) && (ch != '\n'));
} else {
fprintf(stderr, "invalid input, real number expected\n");
exit(EXIT_FAILURE);
}
}
int main(void)
{
char name[50];
int n;
double price;
ReadInteger(&n);
for (int i = 0; i < n; i++) {
ReadLine(name, sizeof name);
ReadReal(&price);
printf("%s, %.2f\n", name, price);
}
return 0;
}
As chux said in the comments of this answer: "All scan specifiers, except %c, %[, %n consumes leading white-spaces." So you don't need to account for them.
scanf("%s%d",name,&price);
And looking at your input, you should use float or double for the price.
scanf("%s%lf",name,&price);
Note that this works only if items are made of one word. If they can be of two or more words, you'd better use fgets
EDIT: for items made of more words you should use fgets
fgets(name, 50, stdin);
scanf("%lf",&price);
Replace your for loop with this:
for (int i = 0; i < n; i++) {
scanf(" %[^\n]\n%d", name, &price);
printf("%s , %d\n", name, price);
}
The first space skips leading spaces, and the [^\n] allows you to get more than one word as string input.
I am new in proggraming and i can't solve a problem. So i have to scanf and check if it is an integer (int n), and than read n floats (with checking if they are floats). Problem is that machine tests add multiple floats separeted by space in input and i don't know how to get these numbers.
I wrote something like this:
int n;
if(!scanf("%d", &n)){
printf("Invalid input");
return 1;
}
float *tab = malloc(n*sizeof(float));
printf("Enter variables: ");
for(int i=0; i<n; i++){
if(scanf("%f", (tab+i))!=1){
printf("Incorrect input data");
return 2;
}
}
I don't know if it is good and what to do if you input less or more numbers in input.
Guys, please explain me what is wrong here and how to solve it.
Thanks for your time.
How to scanf multiple inputs separated by space in C?
The "%d" and "%f" will happily handle numeric text separated by spaces, tabs, end-of-lines, etc., yet not distinguish between spaces and end-of-line. With insufficient input in one line, code will read the input of the next line. With excess input, the entire line is not read - rest of line reamins for next input function.
If OP is concerned about lines of inputs, best to read a line of input and then parse.
I don't know if it is good and what to do if you input less or more numbers in input.
Put yourself in charge: if you directed a team of coders, what would you want? Consume and ignore non-numeric input, consume input and report an error, simple end the code, etc.
Aside from the first scan, code looks reasonable as is.
For me, for robust code, I would drop all scanf() and use fgets() in a helper function to parse. Then sscanf() or strto*() to parse and complain if not as expected.
Sample
Of course this helper function is overkill for such a simple task, yet it is a helper function - one that I can use over and over for anytime I want to read a a group of float from one line. I can improve as desired (e.g. more error handle, handle overly long lines, ...)
// Read 1 line of input.
// return EOF on end-of-file or stream error,
// else return number of float read, even if more than N.
int get_floats(const char *prompt, float *dest, int N) {
if (prompt) {
fputs(prompt, stdout);
fflush(stdout);
}
char buf[BUFSIZ];
if (fgets(buf, sizeof buf, stdin) == NULL) {
return EOF;
}
char *endptr = buf;
int floats_read = 0;
// parse the line into floats
while (*endptr) {
const char *s = endptr;
float f = strtof(s, &endptr);
if (s == endptr) {
break; // no conversion
}
if (floats_read < N) {
dest[floats_read] = f;
}
floats_read++;
}
// Consume trailing white-space
while ((unsigned char) *endptr) {
endptr++;
}
if (*endptr) {
return -1; // Non-numeric junk at the end
}
return floats_read;
}
Usage:
int n;
if(get_floats("Enter variables: ", tab, n) != n) {
printf("Invalid input");
return 1;
}
The answer is really simple: put a space in front of your scanf format specifier. That tells scanf to eat all the whitespace before converting.
Like this:
#include <stdio.h>
#include <stdlib.h>
int main() {
int n;
if (1 != scanf(" %d", &n)) {
exit(1);
}
float *tab = calloc(n, sizeof *tab);
if (!tab) {
exit(3);
}
for (int i = 0; i < n; ++i) {
if (1 != scanf(" %f", &tab[i])) {
exit(2);
}
}
const char *sep = "";
for (int i = 0; i < n; i++) {
printf("%s%f", sep, tab[i]);
sep = ", ";
}
printf("\n");
free(tab);
return 0;
}
I want the user to enter just two integers and not more than two or less than two. Also, upon invalid input, I wish to print an error and prompt the user to enter the two integers again. The user should enter two integers delimited by space and not a newline. Thus, for example:
1) Valid input is: 1 2
2) Invalid input: 1
3) Invalid input: 1 2 3
I have tried it with following two approaches:
#include<stdio.h>
int main(){
int first;
int second;
printf("Enter input:\n");
int returnValue = scanf("%d %d", &first, &second);
while(returnValue != 2){
printf("Invalid input. Please enter again: \n");
returnValue = scanf("%d %d", &first, &second);
}
printf("First: %d Second: %d\n", first, second);
return 0;
}
In this first approach involving scanf, I am unable to prevent the user from entering each integer on newline. Neither am I able to limit the input to just 2 numbers. That is, if the user inputs more than 2 integers, then program is accepting first 2 integers and ignoring third. I want to print error in that case.
My other approach involves fgets and sscanf:
#include<stdio.h>
int main(){
int first;
int second;
printf("Enter input:\n");
char line[20];
fgets(line, sizeof(line), stdin);
int returnValue = sscanf(line, "%d %d", &first, &second);
while(returnValue != 2){
printf("Invalid input. Please enter again: \n");
fgets(line, sizeof(line), stdin);
returnValue = sscanf(line, "%d %d", &first, &second);
}
printf("First: %d Second: %d\n", first, second);
return 0;
}
In this approach, I am able to print error if the user hits enter after entering just one integer. But I am unable to limit the input to just 2 numbers. That is, if the user inputs more than 2 integers, then program is accepting first 2 integers and ignoring third. I want to print error in that case.
So my question is, are my requirements achievable by modifying first approach as well as second approach?
Thanks.
One solution would be to use the %n conversion specification after the two %d conversions. The %n conversion specification does not match any characters, but stores the number of characters read to this point in the format string. So, in the call:
sscanf(line, "%d %d %n", &first, &second, &bufPos);
if the second %d is reached, then bufPos will hold the index of the character after the last character read in line. Since there is a space before the %n, zero or more white-space characters will be read and skipped over before the index value is stored in bufPos. Thus, after a valid entry, bufPos will indicate the \0 terminator. If any other character is found in line at this index, there were extraneous characters in the input.
Here is a modified version of your second code example. After fgets() reads a line of input, sscanf() is used to scan the string. If fewer than 2 matches are made, or if line[bufPos] is not '\0', then badInput is set to true. The input loop is a do loop that executes once, and continues to execute so long as badInput is true.
#include <stdio.h>
#include <stdlib.h> // for exit()
#include <stdbool.h> // for bool type
#define BUF_SIZE 100
int main(void)
{
int first;
int second;
char line[BUF_SIZE];
int returnValue;
int bufPos;
bool badInput = false;
do {
if (badInput) {
printf("Invalid input. Please enter again: ");
badInput = false;
} else {
printf("Enter input: ");
}
if (fgets(line, sizeof(line), stdin) == NULL) {
perror("Error in fgets()");
exit(EXIT_FAILURE);
}
returnValue = sscanf(line, "%d %d %n", &first, &second, &bufPos);
if (returnValue < 2 || line[bufPos] != '\0') {
badInput = true;
}
} while (badInput);
printf("First: %d Second: %d\n", first, second);
return 0;
}
Sample interaction:
Enter input: 1
Invalid input. Please enter again: 1 2 3
Invalid input. Please enter again:
Invalid input. Please enter again: 1 2
First: 1 Second: 2
To prevent issues when asking for char * you can use the regular expression.
If you are not forced to get two in one scanfyou could use this function:
int secure_input(int max, int min) {
int choice,buffer;
do {
choice = -1;//initialize in a values not included among min and max
scanf("%d", &choice);
while ((buffer = getchar()) != '\n' ? buffer != EOF : false); // empty the buffer to avoid infinite loop
} while (choice > max ? true : choice < min);
return choice;
}
In your main function you just to call the function like that:
first = secure_input(2;1);
Different from other answers, you could also parse the input using strtok(), then checking how many numbers were found. This approach is complicated, but it does offer a different outlook on the problem.
Inside your while() loop, you can check how many spaced numbers were found from fgets(), then if only 2 were found, then you can break out of the loop. Otherwise, keep searching. Once out of the loop, then you can just sscanf() two integers from the most recent input read. You can also use strtol() to check if integers are valid.
Note: strtok() is reeantrant, and it does modify the string that it parses. So in this case, you might need to create a copy of it somewhere. You can use strdup() or malloc() to do this.
Here is some example code that shows this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define LINESIZE 20
#define BASE 10
int main(void) {
char line[LINESIZE];
const int n = LINESIZE;
char *number, *copy, *endptr;
const char *delim = " ";
int first, second, check, invalidnum;
size_t slen, count;
while (1) {
printf("Enter input: ");
if (fgets(line, n, stdin) == NULL) {
printf("Error reading buffer from fgets()\n");
exit(EXIT_FAILURE);
}
slen = strlen(line);
if (slen > 0 && line[slen-1] == '\n') {
line[slen-1] = '\0';
} else {
printf("Buffer overflow detected\n");
exit(EXIT_FAILURE);
}
copy = strdup(line);
count = 0;
invalidnum = 0;
number = strtok(copy, delim);
while (number != NULL) {
check = strtol(number, &endptr, BASE);
if (endptr == number || check == 0) {
invalidnum = 1;
break;
}
count++;
number = strtok(NULL, delim);
}
free(copy);
copy = NULL;
if (count != 2 || invalidnum) {
printf("Invalid input\n\n");
} else {
break;
}
}
if (sscanf(line, "%d %d", &first, &second) != 2) {
printf("Unexpected error from sscanf()\n");
exit(EXIT_FAILURE);
}
printf("first = %d, second = %d\n", first, second);
return 0;
}
This is just another approach to your problem. In terms of simplicity, #David Bowling has the better idea, and I would suggest using his.
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");
}
}
}
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...