1

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.

2 Answers2

1

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

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;
}
Zan Lynx
  • 53,022
  • 10
  • 79
  • 131
  • " put a space in front of your scanf format specifier. " --> Putting a space before `"%d"` or `"%f"` serves no functional purpose. Prior white-space is consumed by those specifiers even without a leading `" "`. "Input white-space characters ... are skipped, unless the specification includes a [, c, or n specifier" C17dr – chux - Reinstate Monica May 21 '20 at 20:23