-
Notifications
You must be signed in to change notification settings - Fork 7
Expand file tree
/
Copy pathsimpleinput.tex
More file actions
89 lines (75 loc) · 3.43 KB
/
simpleinput.tex
File metadata and controls
89 lines (75 loc) · 3.43 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
\chapter{Simple input}
%This will deal with reading in whatever types we have already seen
%Reading in chars should first deal with getchar before moving on to string functions.
%Strike that, deal with scan here.
%probably need a loop or two to do this, which constrains ordering (or we split it up ---
% start with integers only and deal with failure to read later?)
Values can be read from the user with \texttt{scanf}.
This function is quite powerful and we won't deal with all its capabilities here.
A call to \texttt{scanf} function looks a bit like a \texttt{printf} call:
\begin{codeblock}
void get_and_print(void) {
int x;
scanf("%d", &x);
printf("%d\n", x);
}
\end{codeblock}
Like \texttt{printf}, \texttt{scanf} takes a string with placeholders and some variables\footnote{Actually any expression which evaluates to a pointer will do but let's keep it simple.}.
The difference is that the variables are pointers to the variables and we are storing into the variables
rather than reading from them.
The types (and number of) placeholders must match the type of pointers given the argument list.
For example:
\begin{codeblock}
char c;
scanf("%d", &c);
\end{codeblock}
--- storing an \texttt{int} into a \texttt{char} is a bad idea.
Since \texttt{int}s are bigger than \texttt{char}s additional memory ``outside'' \texttt{c} and possibly overwrite
other variables.
Compile and run the following program:
\begin{codeblock}
#include <stdio.h>
int main(int argc, char** argv) {
int number;
do {
printf("Enter a number: ");
scanf("%d", &number);
printf("Number was %d\n", number);
} while (number != 0);
return 0;
}
\end{codeblock}
Enter a few numbers, you don't need to press enter after each number, but you will need an enter before the program
takes notice of your input.
Enter a zero to finish.
Note: make sure you know how to stop a running program before going on.
To see a problem with this program, run the program again and give the following input:
\texttt{1 2 z6}
Stop the program.
The problem is that \texttt{scanf} was told to read an integer but it saw the \texttt{z} character.
Because it couldn't make an integer from that, it failed.
But it didn't get rid of the \texttt{z} either, so when the loop ran again, \texttt{z} was still there.
Hence the infinite loop you saw.
When you use functions, you should (if possible) check to see if it worked.
\texttt{scanf} will return the number of variables it managed to read correctly.
So in this case, if the input succeeded, we would expect a return value of \texttt{1}.
Replace the \texttt{scanf} call with:
\begin{codeblock}
if (scanf("%d", &number) == 1) {
printf("Number was %d\n", number);
} else {
number = 0; // trigger the end of the loop
}
\end{codeblock}
Recompile the program and try the same sequence of input.
To read other types of variables, the placeholders are generally similar to the ones used by \texttt{printf}.
An important exception are floating point values.
Use \texttt{\%e} for \texttt{float}s and \texttt{\%le} for \texttt{double}s.
There are four main things to think about when using \texttt{scanf}:
\begin{enumerate}
\item Use the correct placeholder for the type you wish to read.
\item Pass pointers to the variables you wish to store in.
\item Be sure to check to see if \texttt{scanf} actually succeeded
before using its results.
\item Remember that bad input does not disappear automatically.
\end{enumerate}