Home > Mobile >  Scanf an unknown amount of integers without using array and printf right away
Scanf an unknown amount of integers without using array and printf right away

Time:10-04

(I'm a newbie) I need to use a loop to scanf an unknown amount of integers without using array until Ctrl-D and printing them as loop goes. For example, an input can be:

140 128 8 1603 
4905 -3 -2 0 0 
9166 255 -1322 
8900 10000 -1 6543 

in which case output should be:

140, 128, 8, 1603, 4905, -3, -2, 0, 0, 9166, 255, -1322, 8900, 10000, -1, 6543

Now, when I try to write something like

while (scanf("%d", &number)) {
    /* code */
    printf("%d, ", number);
    /* code */
}

scanf will scan values until it sees a \n, then it prints every value it scanned and repeats until Ctrl-D, which leads to my input mix up with my output like that:

140 128 8 1603 
140, 128, 8, 1603, 4905 -3 -2 0 0 
4905, -3, -2, 0, 0, 9166 255 -1322
9166, 255, -1322, 8900 10000 -1 654

Could i get some advices on coding techniques of avoiding that and also what in this case could be an optimal check to not printf the last comma?

CodePudding user response:

Your code is almost correct: should should just test while (scanf("%d", &number) == 1) instead of != 0 as scanf() will return EOF at end of file.

You might want to only print the , if there is another number. As coded, the output will have a trailing comma. You can do this by printing ", " before each number except the first one.

Your interpretation of the program's behavior is slightly incorrect: the reason scanf() seems to convert and retain all values up to the newline is stdin is line buffered on your system so input is not available to scanf() until a full line of text has been read. Furthermore there is another layer of buffering at the terminal level, so changing the buffering scheme of stdin with setvbuf() will not suffice if you are reading from a terminal.

CodePudding user response:

A possible approach to not printing the last comma (in this case we print the comma first, unless it is the first element that we scan):

#include <stdio.h> // scanf(), printf()
#include <stdbool.h> // bool, true, false

int main(void) {
  int number;

  bool first_scan = true;
  while (scanf("%d", &number) == 1) {
    if (first_scan != true) {
      printf(", ");
    }
    printf("%d", number);
    first_scan = false;
  }
  printf("\n");

  return 0;
}

If you write a file test.txt containing:

1 2 3
4 5 6

And you run your program like this:

./program < test.txt

You get this output:

1, 2, 3, 4, 5, 6

NOTE: scanf() isn't well suited for this purpose, because it will not detect integer overflows (and it will also give you a lot headaches), so it is generally good practice to avoid it. An alternative approach in this case would be using fgets() and strtoll(), but it is out of the scope of this answer.

EDIT: my previous note was quite ambiguous (thanks, Steve Summit): when I say "scanf() isn't well suited for this", I mean "isn't suited for reading integers in a real-world application", but for beginning programs like yours, it's fine. However, when you become more comfortable with C (and you start writing more complex applications), you should take a look at fgets() and strtoll() (not yet, if you're not ready), so you can write more correct programs.

  • Related