I found an answer to the first part of my question (how to read multiple values with scanf) but it doesn't seem to work for me (I think it's because of putting the values into an array and maybe also because I'm checking if the values given are 6 ints for sure):
I am writing a program that stores co-ordinates of 4 triangles in an array. Each line has 6 values and stores co-ordinates of one triangle. I want to read 6 co-ordinates at one time and do this operation for 4 triangles separately.
int tab[4][6];
for (int i = 0; i < 4; i++){
while (scanf("%d %d %d %d %d %d", &tab[i][0], &tab[i][1], &tab[i][2], &tab[i][3], &tab[i][4], &tab[i][5]) != 6){
printf("Error, try again: ");
while (getchar() != '\n'){}
}
}
So for example if first triangle's co-ordinates are (2,1), (5,6), (2,7), then I want to type in: "2 1 5 6 2 7" and as a result I want it to fill the first line of the array with the said numbers in the order I typed them in.
Obviously it doesn't work, the program stops working (not finishes the work, it stops) after the first line is given.
I get this error after debugging (after giving first line):
"Unhandled exception at 0x0FDCC28C (msvcr120d.dll) in xxx.exe: 0xC0000005: Access violation writing location 0xCCCCCCCC."
How to fix it?
You need to subtract the pointer i when detecting input error like this for example ->
#include <stdio.h>
int main(int argc, const char * argv[]) {
int tab[4][6];
for (int i = 0; i < 4; i++){
printf("Enter 6 values \n");
int retVal=scanf("%d %d %d %d %d %d", &tab[i][0], &tab[i][1], &tab[i][2], &tab[i][3], &tab[i][4], &tab[i][5]);
if (retVal == 6) {
printf("You did enter -> %d %d %d %d %d %d\n",tab[i][0],tab[i][1],tab[i][2],tab[i][3],tab[i][4],tab[i][5]);
} else {
printf("Error entering values.. (Enter numbers). \n");
while (getchar() != '\n'){}
i--;
}
}
return 0;
}
Unclear why OP's code failed without posting input used and prior code.
How to fix it?
Use fgets() to read a line of user input. Avoid mixing scanf() with fgets() in prior code. Then parse the buffer. Use " %n" at the end to look for success and extra text.
int tab[4][6];
char buf[6*12 * 2]; // Use a buffer twice expected max needs
for (int i = 0; i < 4; i++) {
while (1) {
if (fgets(buf, size buf, stdin) == NULL) {
return "Failed to read enough data"; // Handle end-of-file in some fashion
}
int n = 0;
sscanf(buf, "%d%d%d%d%d%d %n",
&tab[i][0], &tab[i][1], &tab[i][2], &tab[i][3], &tab[i][4], &tab[i][5], &n);
if (n > 0 && buf[n] == 0) {
break; // Success!
}
printf("Error - bad input, try again: ");
}
}
Related
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]);
I'm not sure why I'm receiving this error. I was wondering could it be due to my terminal not being able to read the txt files that run with this program. Let me know if that could be a possible reason for that message.
Im mainly just looking for syntax errors. The files I have just contain a big bunch of numbers and I'm supposed to work from the third value onwards {the first two have another use)
#include <stdlib.h>
#define N 1000000
int main(void)
{
int n; /* The number of lengths */
int x; /* The target length */
int lengths[N]; /* The array of available lengths */
int i, j;
int whichfile=1;
FILE *fp;
scanf("%d", &whichfile);
switch (whichfile) {
case 1:
fp = fopen("testcase_small_sorted.txt", "r");
break;
case 2:
fp = fopen("testcase_large_sorted.txt", "r");
break;
case 3:
fp = fopen("testcase_small_nomatch_sorted.txt","r");
break;
case 4:
fp = fopen("hidden_small_sorted.txt","r");
break;
case 5:
fp = fopen("hidden_large_sorted.txt","r");
break;
}
fscanf(fp, "%d", &x);
fscanf(fp, "%d", &n);
for (i=0;i<n;i++)
fscanf(fp, "%d", &lengths[i]);
fclose(fp);
/* Now all the input data has been read in
search for the required pair of lengths... */
x = lengths[0];
n = lengths[1];
for(i = 2; i < n; i++)
{
for(j = 2; i < n; j++)
{
if(lengths[i] + lengths[j] == x)
{
printf("Found: %d + %d == %d\n", lengths[i], lengths[j], x);
}
}
}
return 0;
} ```
I'm mainly just looking for syntax errors.
Syntax errors are only the beginning. C will not check anything for you. You have to check if files opened, if input scans worked, if values are inside array bounds. If you don't, that's how you get segfaults.
For files, the usual pattern is to try to open the file, check its return value, and then handle the error. fopen returns NULL on error and sets errno. errno is a global which holds what sort of error happened like "file not found", but it's a number. strerror is handy to turn it into an error message. Finally fprintf is like printf but can print to things other than stdout. In this case stderr. Both stdout and stderr normally appear on the screen, but they can be separated.
FILE *fp = fopen(path, mode);
if( fp == NULL ) {
// This will print something like "Could not open testcase_small_sorted.txt: No such file or directory"
fprintf(stderr, "Could not open file %s: %s", path, strerror(errno));
exit(1);
}
But now we need to copy this five times because the code repeats fopen. Instead of each case opening the file, what if it just picked a filename? And since each filename has a number, what if they were just in an array?
const char *files[] = {
NULL, // 0 is not used
"testcase_small_sorted.txt",
"testcase_large_sorted.txt",
"testcase_small_nomatch_sorted.txt",
"hidden_small_sorted.txt",
"hidden_large_sorted.txt"
};
const char *path = files[whichfile];
What if they input something that's not a number? Or what if the number is out of range? These need to be checked for as well. scanf will return the number of items matched. We expect 1. If we get anything else it didn't work.
// Check that we read an integer.
if( scanf("%d", &whichfile) != 1 ) {
fprintf(stderr, "Please enter 1-5.\n");
exit(1);
}
// Check that it's in range.
if( (whichfile < 1) || (5 < whichfile) ) {
fprintf(stderr, "Please enter 1-5.\n");
exit(1);
}
Note that scanf has a lot of problems and should be swiftly discarded once you learn things like fgets and sscanf.
int lengths[1000000] is 4 to 8 megabytes (1 million integers at 4 or likely 8 bytes per integer) and might get you an eponymous stack overflow. Your algorithm is O(n^2) which means if there really were 1,000,000 items it would take 1,000,000,000,000 iterations to find all the pairings and your class will probably be done before the program is.
(A little hint to improve the algorithm: if the numbers are sorted, and you're looking for two of them to sum X, do you need to check every number?)
I think you're meant trust n from the file for how many to read. Normally you don't have this, it's a crutch to let you read input without using dynamic memory (you'll be taught that later). Even if you had it, you wouldn't trust it anyway in production code; if it lies you'll walk out of your array bounds. But for this exercise that's fine.
// Read the first two lines, the sum and the number of remaining lines.
// Note that `fscanf` can also fail and needs to be error checked.
// I'll leave that as an exercise.
fscanf(fp, "%d", &x);
fscanf(fp, "%d", &n);
// Use `n` to allocate just enough space on the stack.
int lengths[n];
// Read the rest.
// Use braces, even for one line.
// They avoid a very silly and hard to debug mistake.
for (i=0;i<n;i++) {
fscanf(fp, "%d", &lengths[i]);
}
fclose(fp);
There's no need to put x and n into lengths. They aren't meant to be summed and you skip over them anyway by starting your loops at 2.
With that fixed the loops can start at 0. There is a mistake in the inner loop, it should check j < n not i < n.
for(i = 0; i < n; i++)
{
for(j = 0; j < n; j++) // <<--- j < n, not i < n.
{
if(lengths[i] + lengths[j] == x)
{
printf("Found: %d + %d == %d\n", lengths[i], lengths[j], x);
}
}
}
The goal of this program is to scan a string populated with numbers and white spaces between them and insert each number into an array. Then each number from the array is sent to checkPowerOfTwo function which determines if the number sent is a power of two and prints the calculation.
When I run this program on windows everything is workingfine. Running on Linux causes a segmentation fault.
I'm compiling my code on a Linux server with : gcc -std=c99 -Wall -pedantic-errors -Werror -DNDEBUG main.c -o mtm_tot. It compiles successfully with no errors or warnings. The problem arises when I try to run a tester : ./mtm_tot< test1.in > tmpout. After pressing enter on this line Segmentation fault rises.
test1.in contains : 8
5 9 -1 4 20 256 -32 17 32
The code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int checkPowerOfTwo(int x);
int main()
{
int exp,size,sum=0,*numbers;
char term,*str=NULL,*token;
printf("Enter size of input:\n");
if(scanf("%d%c", &size, &term) != 2 || term != '\n'){
printf("Invalid Size\n");
return 0;
} if(size<=0){
printf("Invalid size\n");
return 0;
} else{
numbers=(int*)malloc(size * sizeof(int));
str=(char*)malloc(sizeof(int)*(size+1) + (size-1)*sizeof(char));
if(numbers==NULL||str==NULL){
printf("Out of memory\n");
return 0;
} //else{
//printf("Memory allocated\n");
//}
printf("Enter numbers:");
fgets (str, sizeof(int)*(size+1) + (size-1), stdin);
//printf("%s",str);
token=strtok(str," ");
while(token!=NULL){
for(int i=0;i<size;i++){
//printf("token is %s\n",token);
//numbers[i]=token;
sscanf(token,"%d",&numbers[i]);
//printf("Inserting %s to the array\n ",numbers[i]);
token=strtok(NULL," ");
}
}
}
for(int j =0;j<size;j++)
{
//sscanf(numbers[j],"%d",&x);
//printf("the number im sending is : %d ",x);
exp=checkPowerOfTwo(numbers[j]);
if (exp>=0){
printf("The number %d is a power of 2: %d=2^%d\n",numbers[j],numbers[j],exp);
sum+=exp;
}
}
printf("Total exponent sum is %d",sum);
free(numbers);
free(str);
}
int checkPowerOfTwo(int x)
{
int exponent=0;
//sscanf(n,"%d",&x);
//printf("checking number %d\n",x);
if (x==0){
return -1;
} if (x==1){
return 0;
}
while( x != 1)
{
if(x % 2 != 0){
return -1;
}
x /= 2;
exponent++;
}
return exponent;
}
With the input file test1.in as shown in the question you specify a size of 8 and provide 9 numbers.
Your code
while(token!=NULL){
for(int i=0;i<size;i++){
//printf("token is %s\n",token);
//numbers[i]=token;
sscanf(token,"%d",&numbers[i]);
//printf("Inserting %s to the array\n ",numbers[i]);
token=strtok(NULL," ");
}
}
will enter the outer while loop and process 8 numbers in the first run of the inner for loop.
As you have entered 9 numbers, token will not be NULL and the outer loop will repeat and run the inner loop again. This will partially overwrite the numbers in the array. After processing the 9th number in the first cycle, token will become NULL and in the 2nd cycle sscanf will try to use the NULL pointer which may lead to a segmentation fault.
You should combine the counter and the check for NULL in the loop condition.
I also recommend to check the return value of sscanf because a value != 1 will indicate invalid input.
for(int i=0; (i<size) && (token!=NULL); i++) {
if(sscanf(token,"%d",&numbers[i]) != 1) {
/* invalid input */
break;
}
token=strtok(NULL," ");
}
Of course the code following the loop must handle the case that the loop ends with i < size if not enough values were present.
Edit: additional clarification below
Note: The error checking for scanf is incomplete. It will return 0 if it couldn't convert an integer number, but it will also return 1 if it converted an integer number and anything is following it, e.g. for 123abc it will convert 123 and return 1. To check what may follow the number you could add a %c conversion and if the return values is 2 check the converted character. ('\n' or '\r' may be OK here.)
I would prefer to use strtol in a loop to parse the numbers in str.
BTW: The size calculation for the allocation of str is wrong. sizeof int is the size of the internal binary representation of an int value which is 4 (4 bytes = 32 bits) on many systems. It has nothing to do with how many characters are needed for a string representation of a number. A valid number -2147483648 needs 11 characters.
(You could use a buffer str that is too small for the whole line but big enough for more than a valid number if you move the remaining data to the beginning and append new data after pasing a number until you have read the terminating newline.)
Your program logic is wrong:
for (int i = 0; i < size; i++) {
sscanf(token, "%d", &numbers[i]);
token = strtok(NULL, " ");
// token may become NULL here
// and sscanf will segfault right after
}
There may be other problems though.
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.
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...