0

So i have program that get numbers from user in single line for example:

2 1 2 3 4

The first number: 2 mean that the output should be matrix with 2 rows and 2 columns:

1 2
3 4

So this is how i am populate my aray:

int dim;
scanf("%d", &dim);
int *m = (int *)malloc(dim* dim* sizeof(int))

for (r = 0; r < dim; ++r)
{
    for (c = 0; c < dim; ++c)
    {
        scanf("%d", &m[dim * r + c]);
    }
}

Now i want to add some value check, in case the user input start with 2 the next input should contain 4 number () in a single line so in case the input is 2 1 2 3 i want to print error message but my problem is that after this input the scanf just ignored from the new line and wait.

Dana Yeger
  • 617
  • 3
  • 9
  • 26

1 Answers1

2

If you know that your standard input is organized in lines, you could read each line entirely (probably with getline(3) like here or else with fgets) then parse that line appropriately in memory (keeping some internal pointer inside it, and using strtol(3) with its end pointer, or sscanf(3) with %n). BTW what exactly defines a line is operating system specific (Windows vs Linux vs MacOSX have different definitions and line terminators).

If you are not sure that the input is organized in lines, you'll use standard parsing techniques (e.g some recursive descent parser), probably with a single token of look ahead.

In all cases, you'll better specify on paper your file format. A simple EBNF notation is a good specification for most parsers.

Your current code is wrong, because you don't test against failure of scanf. You need to test its returned scanned item count. BTW, it is also wrong to use malloc without testing its failure, and you probably should use calloc not malloc because you should prefer zeroed memory.

Notice that scanf with %d (or better yet, " %d") is skipping spaces, including newline characters ending input lines. In other words, your scanf don't care about lines, as you say you want to.

Compile your code with all warnings and debug info (so gcc -Wall -Wextra -g with GCC) and use the debugger gdb to run it step by step and understand what is happening. Spend more time in reading documentation (notably of standard C functions, and of your software tools: compiler, debugger, ... that you would use on the command line).


BTW, terminals are complex (virtual) devices. On my Linux system, they could be line buffered by the kernel's line discipline. You might read the tty demystified and consider using readline(3) or ncurses (if you are sure to read from the terminal). Using fgets, getline and other stdio(3) functions is enough only if you are just reading from stdin and don't care about pseudo-terminals vs redirections or command pipelines. See also isatty(3).

(the last above paragraph is specific for Linux, and probably not for newbies. IMHO terminals are very complex, once you dive into details.)

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
  • No, the input should be in a single line. – Dana Yeger Nov 22 '17 at 09:29
  • Unless you know that all the input will be passed in one line there is no way to know that the rest of the input comes from the stdin. Simply because user can change her mind just after you call scanf. – mcsim Nov 22 '17 at 09:29
  • i want to count the number and for example if the line start with 2 thats mean that i need more 4 numbers and if i have 3 and new line i want to pring error message – Dana Yeger Nov 22 '17 at 09:33
  • **You** definitely **should spend hours *reading* documentation** (notably of `malloc`, `calloc`, `scanf`, `getline`, `fgets`). We won't do your homework. – Basile Starynkevitch Nov 22 '17 at 09:36
  • 1
    @DanaYeger - the `"%d"` *format specifier* will skip *leading whitespace*. (a `'\n'` is *whitespace*) So what he is saying is it does not matter if all your input is on one line, or if it is on 5 separate lines -- `scanf ("%d",...` will read an integer and then skip all spaces and newlines and read the next value. – David C. Rankin Nov 22 '17 at 09:47
  • @DavidC.Rankin: nitpicking, I think (but I am not entirely sure) that `scanf("%d",` will first skip spaces -including newlines- and then read one integer (not in the opposite order). – Basile Starynkevitch Nov 22 '17 at 09:48
  • 1
    Hehe, that's one I had to prove to myself -- but it does. Example `while (scanf ("%d", &i) == 1) printf ("%d\n", i);` and feed it `printf " 1\n \n2 3\n4" | ./prog`. It will in fact skip `spaces` and `newlines` in any order (even multiple `newlines`) without the leading space (e.g. `" %d"`) in the format string. `:)` – David C. Rankin Nov 22 '17 at 09:55
  • So from all the comments what is the best way to read single line with numbers and from here continue ? – Dana Yeger Nov 22 '17 at 11:30
  • i just very confuse now – Dana Yeger Nov 22 '17 at 11:33
  • I don't know. If you care only about stdin, use `getline` or `fgets` and then parse that line. If you really want an editable line from a terminal on Linux -not just from stdin-, consider `readline`, which BTW is really simple to use. I have no idea if you want your program to support redirections and pipelines. As I explained in my last paragraph, terminals are *really* complex. But your *question* is confusing and your code is wrong (every outside function e.g. `scanf` or `malloc` can fail, and you should test that!) – Basile Starynkevitch Nov 22 '17 at 11:35