0

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.')?

SheetJS
  • 22,470
  • 12
  • 65
  • 75
user2583127
  • 51
  • 1
  • 5

5 Answers5

2

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);
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
0

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 ?

haccks
  • 104,019
  • 25
  • 176
  • 264
0

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)

MOHAMED
  • 41,599
  • 58
  • 163
  • 268
  • see my question. i dnt want program to ask users how many nos. will he enter. I want to allow users to enter as many nos. they want. But I dont know how many nos. the user will enter, so how can I make scanf() type specifiers to accept any no. of numbers? – user2583127 Oct 08 '13 at 13:23
  • you can make an infinite loop while – MOHAMED Oct 08 '13 at 13:24
  • IF I want this?? ENTER NUMBERS SEPARATED BY WHITESPACES: 56 989 859 582 6949 //These 5 numbers are given by user and the user then pressed enter, And I dont know how many %d to enter in scanf as it depends on user that how many nos. would he enter AVERAGE: ***** //***** should be replaced by the average answer. – – user2583127 Oct 08 '13 at 13:38
  • @user2583127 ok I see now. so the user input is always numbers separeted by spaces and then at the end is an enter (newline). Is this correct? – MOHAMED Oct 08 '13 at 13:40
  • @user2583127 I update my answer I added the way of the user input is always numbers separeted by spaces and then at the end is an enter (newline) – MOHAMED Oct 08 '13 at 13:55
  • @mohamed, I would suggest a better format string. First of all, the space before `%d` is unnecessary. `%d` already consumes whitespaces. Second, after the last digit there could be extra whitespaces (you can't prevent user from doing that). So, it's better to ignore all non-digit-non-enter characters before reading that character): `scanf("%d%*[^-+1234567890\n]%c", &input, &c)` and immediately after `ungetc(c, stdin);` to put back the test character (it could belong to the next digit, since we ignored whitespace). – Shahbaz Oct 08 '13 at 16:18
0

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...

Floris
  • 45,857
  • 6
  • 70
  • 122
  • Note - I saw your comment about "not wanting to do anything to end input" after writing my answer so I updated it a little bit. You get the average after each number entered. But at some point the program needs to know when to stop - either before it is run, or at the end. I think the latter is better. – Floris Oct 08 '13 at 13:24
  • Answer updated. User does not have to type q to quit - it will report average of all numbers entered, but it just never ends... Is that better? – Floris Oct 08 '13 at 13:26
  • IF I want this?? ENTER NUMBERS SEPARATED BY WHITESPACES: 56 989 859 582 6949 //These 5 numbers are given by user and the user then pressed enter, And I dont know how many %d to enter in scanf as it depends on user that how many nos. would he enter AVERAGE: ***** //***** should be replaced by the average answer. – user2583127 Oct 08 '13 at 13:31
  • Ah that is clearer. You don't like the letter Q but you like the "enter" key. It is just a different ASCII character. But I have now updated my answer. – Floris Oct 08 '13 at 13:40
  • I will try it just now & update! By the way we should not use gets() . so is using fgets() a good idea? and can gets be replaced by getline???? – user2583127 Oct 08 '13 at 13:43
  • UPDATE Edited program gives this error: Line 9: stdin undeclared So I tried adding stdio.h header file then it gives this error: Line 11: lvalue expected – user2583127 Oct 08 '13 at 13:49
  • Apologies - I should have tested my code before posting. Updated, working now (I believe). – Floris Oct 08 '13 at 14:17
  • As for your `gets` vs `fgets` question: `fgets` contains the "no more than n characters" parameter, while `gets` will allow buffer overflow. Big difference. `getline` can work too, and is safer since it will resize the block of data in which the result is stored. I will update my answer... – Floris Oct 08 '13 at 15:04
0

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

Community
  • 1
  • 1
Shahbaz
  • 46,337
  • 19
  • 116
  • 182
  • 3
    **!!!Don't ever use `gets`!!!**. It's inherently unsafe and is deprecated. Yes it can be done with `getline`. – Shahbaz Oct 08 '13 at 13:26
  • Note - typing an "end of file" character (or a carriage return) is really not that different from typing any other character (say, the letter `Q`). What is the real requirement here...? – Floris Oct 08 '13 at 13:30
  • @Shahbaz: `getline` is not a C standard function. – Keith Thompson Oct 08 '13 at 15:31
  • @KeithThompson, I know. I didn't want to get into the details of how to read a line since that would be a different (and already answered) question. – Shahbaz Oct 08 '13 at 16:10
  • @Floris, the difference is that typing end of file makes `scanf` fail, which is different from basically all other characters. Even though in this particular case any nondigit (except `-` and `+`) would make this `scanf` fail. – Shahbaz Oct 08 '13 at 16:11
  • @Shahbaz - I was referencing the "what is the real requirement here" question, not the "why does A work and B doesn't". Sorry if I caused confusion. – Floris Oct 08 '13 at 16:30