Standard Inputs of C
Review of common inputs: scanf
, getchar
, gets
(fgets
).
Remember that, when functions in the standard library, or some code snippets on the internet seems confusing, you can always refer to the following sites:
Shortcut for Quick Review:
Update (2020.11.25): Fix typo in answer description (Question 5)
Basic Formats
- What is the result of the following code?
#include <stdio.h> int main(void) { int a, b; scanf("%d%d", a, b); printf("%d %d", a, b); return 0; }
Input:
12 34
Click to expand Answer
✔️ Answer
Undefined Behavior.
scanf
requires the memory address of the variable. - What is the result of the following code?
#include <stdio.h> int main(void) { int a, b; scanf("%1d%2d", &a, &b); printf("%d %d", a, b); return 0; }
Input:
1234 5678
Click to expand Answer
✔️ Answer
1 23
The
%2d
part means to read in 2 digits. -
What is the result of the following code?
#include <stdio.h> int main(void) { int a, b; scanf("(%d,%d)", &a, &b); printf("%d %d", a, b); return 0; }
Input:
(12,34)
Click to expand Answer
✔️ Answer
12 34
What if the input becomes:(12, 34)
Click to expand Answer
✔️ Answer
12 34
If we specify a certain character to match in
scanf
, the input must include that specific character. For example, using(
inscanf
indicates the next character must be(
, the call will fail if the next character is space or\n
, … However, using%d
,%f
, … automatically ignores every whitespace characters (space,\n
, …) before the number digits.%c
is an exception that does read in whitespace characters. - What is the result of the following code?
#include <stdio.h> int main(void) { float f; double d; scanf("%f%f", &f, &d); printf("%f %f", f, d); return 0; }
Click to expand Answer
✔️ Answer
Undefined Behavior.
The input format should be
%lf
for double variables, using%f
will leave half of the variable’s memory undefined.
Usages of scanf("%c", ...)
and getchar
- What is the result of the following code?
#include <stdio.h> int main(void) { int i; char a[6]; for (i = 0; i < 6; i++) scanf("%c", &a[i]); for (i = 0; i < 6; i++) printf("%d ", (int)a[i]); return 0; }
Input:
A B C
Hint:
'A'
is65
,' '
is32
,'\n'
is10
.Click to expand Answer
✔️ Answer
65 32 66 10 67 10
Using
%c
as the input format automatically reads in every character, including whitespace characters. The visualization of variablea
is:{'A', ' ', 'B', '\n', 'C', '\n'}
. For each variable, they are stored in its binary format in the memory, regardless of its type. Takechar
as an example, the characters are stored by their ASCII code. It should be straightforward to see that:'A' + ' ' is 'a'
. (65 + 32 = 97
)The
int
cast before printing out the character is used to extend the 1-byte variable to 4-bytes to avoid undefined behavior. - What is the result of the following code?
#include <stdio.h> int main(void) { int i; char a[6]; for (i = 0; i < 6; i++) scanf(" %c", &a[i]); for (i = 0; i < 6; i++) printf("%d ", (int)a[i]); return 0; }
Input:
AB C DEF G
Hint:
'A'
is65
,' '
is32
,'\n'
is10
.Click to expand Answer
✔️ Answer
65 66 67 68 69 70
The space character before
%c
ignores all whitespace characters. - What is the result of the following code?
#include <stdio.h> int main(void) { int i; char a[6]; for (i = 0; i < 6; i++) a[i] = getchar(); for (i = 0; i < 6; i++) printf("%d ", (int)a[i]); return 0; }
Input:
AB C DEF G
Hint:
'A'
is65
,' '
is32
,'\n'
is10
.Click to expand Answer
✔️ Answer
65 66 32 67 10 68
c = getchar();
is same asscanf("%c", &c);
.
Usages of scanf("%s", ...)
- What is the result of the following code?
#include <stdio.h> int main(void) { int i; char a[5] = {-1, -1, -1, -1, -1}; scanf("%s", a); for (i = 0; i < 5; i++) printf("%d ", (int)a[i]); return 0; }
Input:
ABC DE FG
Hint:
'A'
is65
,' '
is32
,'\n'
is10
.Click to expand Answer
✔️ Answer
65 66 67 0 -1
The value of an array variable is its memory address, so using
scanf("%s", a)
should be enough. Of course, usingscanf("%s", &a)
is also valid.Using
%s
as the input format automatically ignores leading whitespace characters (like%d
). It’ll continuously read input characters until a whitespace character, and then add a'\0'
(ASCII code 0) character indicating the termination of the string. The values after'\0'
aren’t affected. - What is the result of the following code?
#include <stdio.h> int main(void) { int i; char a[3]; scanf("%s", a); for (i = 0; i < 3; i++) printf("%d ", (int)a[i]); return 0; }
Input:
ABC
Hint:
'A'
is65
,' '
is32
,'\n'
is10
.Click to expand Answer
✔️ Answer
Undefined Behavior. (May result in a segmentation fault (
SEGFAULT
))After reading
ABC
,scanf
adds an additional'\0'
at the end of the input. However,a[3]
shouldn’t be accessed in this case. If you tried to compile and run this code, the program may not crash most of the time, but the behavior is not defined in the C standard. This is the notorious Null-terminated string in C, which can easily lead to many bugs if the programmer is not careful enough.
gets
vs. fgets
- What is the result of the following code?
#include <stdio.h> int main(void) { int i; char s[6] = {-1, -1, -1, -1, -1, -1}; fgets(s, 6, stdin); for (i = 0; i < 6; i++) printf("%d ", (int)s[i]); return 0; }
Input:
ABCDEF
Hint:
'A'
is65
,' '
is32
,'\n'
is10
.Click to expand Answer
✔️ Answer
65 66 67 68 69 0
What if the input becomes:AB C
Click to expand Answer
✔️ Answer
65 66 32 67 10 0
fgets
reads in the ending newline character, so as other whitespace characters, including leading whitespaces! - What is the result of the following code?
#include <stdio.h> int main(void) { int i; char s[6] = {-1, -1, -1, -1, -1, -1}; gets(s); for (i = 0; i < 6; i++) printf("%d ", s[i]); return 0; }
Input:
AB C
Hint:
'A'
is65
,' '
is32
,'\n'
is10
.Click to expand Answer
✔️ Answer
65 66 32 67 0 -1
What if the input becomes:ABCDEF
Click to expand Answer
✔️ Answer
Undefined Behavior. (May result in a segmentation fault)
gets
is likefgets
but does not read in the newline character.scanf("%[^\n]", s)
works the same asgets
but the syntax may be difficult to memorize.%[...]
tellsscanf
to read any number of the characters specified in the brackets.^
inside the brackets indicates negation. So%[^\n]
tellsscanf
to read all characters that aren’t the newline character\n
.
scanf
’s Return Value
- What is the result of the following code?
#include <stdio.h> int main(void) { int a, b, ret; a = b = -1; ret = scanf("%d%d", &a, &b); printf("%d %d %d", ret, a, b); return 0; }
Input:
100 abc 1000
Click to expand Answer
✔️ Answer
1 100 -1
The return value of
scanf
indicates the number of variables that has been read successfully. Take the above code and input as an example, it reads in100
and stores it intoa
, then it seesabc
, which is not a number, so the matching fails. The value ofb
isn’t modified due to the failed matching. In C, the return value of many library functions indicates whether that function ran without error. - What is the result of the following code?
#include <stdio.h> int main(void) { int a, b, ret; a = b = -1; ret = scanf("(%d,%d)", &a, &b); printf("%d %d %d", ret, a, b); return 0; }
Input:
( 1 , 2 )
Click to expand Answer
✔️ Answer
1 1 -1
For
,
, whitespace characters are invalid, so the match fails.
End of File EOF
EOF
is defined to be -1
in most of the compiler implementations. When the input ends, scanf
and getchar
returns EOF
.
For gets
and fgets
, they return NULL
, which is 0
in most of the compiler implementations.
After interacting with a program on the command line / terminal, the user can tell the program that there will be no further inputs by signaling EOF
. EOF
is sent by pressing Ctrl+Z
and Enter
on Windows or pressing Ctrl+D
and Enter
on macOS or Linux.
For some common usages:
while (scanf("%d", &x) != EOF) {
// Do something.
}
while (scanf("%d%d", &a, &b) == 2) {
// Do something.
}
while ((c = getchar()) != EOF) {
// Do something.
}
// Change 'MAX_STRLEN' to a constant (max string length including null-terminator)
while (fgets(s, MAX_STRLEN, stdin) != NULL) {
// Do something.
}
A Toy Example
For reading a particular input format, there exist many different code snippets that can achieve the same result. However, one might be simpler than another.
For example, if we want to read a 5-digit number, with each of its digit stored in a different variable:
12345
And store them into 5 variables a
, b
, c
, d
, e
respectively.
- Math
int n; scanf("%d", &n); a = n / 10000 % 10; b = n / 1000 % 10; c = n / 100 % 10; d = n / 10 % 10; e = n / 1 % 10;
- Scan 1-digit at a time
scanf("%1d%1d%1d%1d%1d", &a, &b, &c, &d, &e);
- Scan by char
a = getchar() - '0'; b = getchar() - '0'; c = getchar() - '0'; d = getchar() - '0'; e = getchar() - '0';
- Scan by string
char str[6]; scanf("%s", &str); a = str[0] - '0'; b = str[1] - '0'; c = str[2] - '0'; d = str[3] - '0'; e = str[4] - '0';
- And more…
For the next practice, we’ll review the standard outputs of C.
Epilogue
A piece of code that works on your computer doesn’t necessarily mean that it will also run successfully on another person’s computer. You should be able to identify and fix codes with undefined behaviors after finishing this practice.
Photo Credit: Created on Meme Creator.
Comments