how the below mentioned scanf part will execute ...
scanf("%[^\n]\n",s)
weakly attempts to read a line of input.
Code then uses strtok()
to find tokens which are then parsed with atoi()
.
Code contains weaknesses.
Incorrect reading a a line of user input
"%[^\n]"
fails if the first character is '\n'
. Else it reads an unlimited number of non-'\n'
characters into s
, then appending a null character. "\n"
then reads in, and discards, 0 to an unlimited number of white-spaces including '\n'
, ' '
, etc.
while(scanf("%[^\n]\n",s)==1){
will stop the loop if the first line is only "\n"
, but will silently consume "\n"
otherwise. Lacking a width, it it worse than gets()
.
Perhaps scanf("%9999[^\n]%c", s, &char_sentinel) >= 1
, yet far better to use fgets()
here.
// Basic alternative
while (fgets(s, sizeof s, stdin)) {
10000 - that's a long line
For 100 int
in a line, I'd expect a worse case of 11 char
(e.g. "-2147483647") and a spacer so 12*100 + an '\n'
and '\0'
. Being generous, how about a worse case line twice that or char s[(12*100+2)*2];
?
Too many columns or rows break code
a[rows][val++]=atoi(num);
is also prone to buffer overflow as row, col
may exceed valid range [0...99] resulting in undefined behavior (UB).
No detection for uneven amount of columns
The number of columns per row may vary. The final printing cols
only reflects the last row.
Integer conversion woes
atoi(num)
lacks no conversion and overflow detection. Rather than strtok()
, atoi()
, use strtol()
to march down the line of text and detect problems.
Limited size
Code only handles a matrix up to 100 columns and 100 rows. Code uses excessive sized buffers. More advanced code would be more flexible. (not shown below)
Some improvement ideas
After reading a line ...
if (rows >= 100) {
break; // TBD code to handle excessive rows
}
char *str = s;
int column = 0;
while (*str) {
if (column >= 100) {
break; // TBD code to handle excessive columns
}
char *endptr;
errno = 0;
long number = strtol(str, &endptr, 10);
// If no conversion or out-of-range ...
if (str == endptr || errno || number < INT_MIN || number > INT_MAX) {
break; // Handle errors in some fashion
}
a[rows][column++] = (int) number;
str = endptr; // Start where prior conversion left off.
}
if (row == 0) {
cols = column;
} else if (cols != column) {
; // Handle column mis-match
}
row++;