forked from DlangRen/Programming-in-D
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathinput.d
237 lines (173 loc) · 6.99 KB
/
input.d
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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
Ddoc
$(DERS_BOLUMU $(IX input) Reading from the Standard Input)
$(P
Any data that is read by the program must first be stored in a variable. For example, a program that reads the number of students from the input must store this information in a variable. The type of this specific variable can be $(C int).
)
$(P
As we've seen in the previous chapter, we don't need to type $(C stdout) when printing to the output, because it is implied. Further, what is to be printed is specified as the argument. So, $(C write(studentCount)) is sufficient to print the value of $(C studentCount). To summarize:
)
$(MONO
stream: stdout
operation: write
data: the value of the studentCount variable
target: commonly the terminal window
)
$(P
$(IX readf) The reverse of $(C write) is $(C readf); it reads from the standard input. The "f" in its name comes from "formatted" as what it reads must always be presented in a certain format.
)
$(P
We've also seen in the previous chapter that the standard input stream is $(C stdin).
)
$(P
In the case of reading, one piece of the puzzle is still missing: where to store the data. To summarize:
)
$(MONO
stream: stdin
operation: readf
data: some information
target: ?
)
$(P
The location of where to store the data is specified by the address of a variable. The address of a variable is the exact location in the computer's memory where its value is stored.
)
$(P
$(IX &, address of) In D, the $(C &) character that is typed before a name is the address of what that name represents. For example, the address of $(C studentCount) is $(C &studentCount). Here, $(C &studentCount) can be read as "the address of $(C studentCount)" and is the missing piece to replace the question mark above:
)
$(MONO
stream: stdin
operation: readf
data: some information
target: the location of the studentCount variable
)
$(P
Typing a $(C &) in front of a name means $(I pointing) at what that name represents. This concept is the foundation of references and pointers that we will see in later chapters.
)
$(P
I will leave one peculiarity about the use of $(C readf) for later; for now, let's accept as a rule that the first argument to $(C readf) must be $(STRING "%s"):
)
---
readf("%s", &studentCount);
---
$(P
$(I $(B Note:) As I explain below, in most cases there must also be a space: $(STRING " %s").)
)
$(P
$(STRING "%s") indicates that the data should automatically be converted in a way that is suitable to the type of the variable. For example, when the '4' and '2' characters are read to a variable of type $(C int), they are converted to the integer value 42.
)
$(P
The program below asks the user to enter the number of students. You must press the Enter key after typing the input:
)
---
import std.stdio;
void main() {
write("How many students are there? ");
/* The definition of the variable that will be used to
* store the information that is read from the input. */
int studentCount;
// Storing the input data to that variable
readf("%s", &studentCount);
writeln("Got it: There are ", studentCount, " students.");
}
---
$(H5 $(IX %s, with whitespace) $(IX whitespace) Skipping the whitespace characters)
$(P
Even the Enter key that we press after typing the data is stored as a special code and is placed into the $(C stdin) stream. This is useful to the programs to detect whether the information has been input on a single line or multiple lines.
)
$(P
Although sometimes useful, such special codes are mostly not important for the program and must be filtered out from the input. Otherwise they $(I block) the input and prevent reading other data.
)
$(P
To see this $(I problem) in a program, let's also read the number of teachers from the input:
)
---
import std.stdio;
void main() {
write("How many students are there? ");
int studentCount;
readf("%s", &studentCount);
write("How many teachers are there? ");
int teacherCount;
readf("%s", &teacherCount);
writeln("Got it: There are ", studentCount, " students",
" and ", teacherCount, " teachers.");
}
---
$(P
Unfortunately, the program cannot use that special code when expecting an $(C int) value:
)
$(SHELL
How many students are there? 100
How many teachers are there? 20
$(SHELL_NOTE_WRONG An exception is thrown here)
)
$(P
Although the user enters the number of teachers as 20, the special code(s) that represents the Enter key that has been pressed when entering the previous 100 is still in the input stream and is blocking it. The characters that appeared in the input stream are similar to the following representation:
)
$(MONO
100$(HILITE [EnterCode])20[EnterCode]
)
$(P
I have highlighted the Enter code that is blocking the input.
)
$(P
The solution is to use a space character before $(STRING %s) to indicate that the Enter code that appears before reading the number of teachers is not important: $(STRING " %s"). Spaces that are in the format strings are used to read and ignore zero or more invisible characters that would otherwise appear in the input. Such characters include the actual space character, the code(s) that represent the Enter key, the Tab character, etc. and are called the $(I whitespace characters).
)
$(P
As a general rule, you can use $(STRING " %s") for every data that is read from the input. The program above works as expected with the following changes:
)
---
// ...
readf(" %s", &studentCount);
// ...
readf(" %s", &teacherCount);
// ...
---
$(P
The output:
)
$(SHELL
How many students are there? 100
How many teachers are there? 20
Got it: There are 100 students and 20 teachers.
)
$(H5 Additional information)
$(UL
$(LI
$(IX comment) $(IX /*) $(IX */) Lines that start with $(COMMENT //) are useful for single lines of comments. To write multiple lines as a single comment, enclose the lines within $(COMMENT /*) and $(COMMENT */) markers.
$(P
$(IX /+) $(IX +/) In order to be able to comment even other comments, use $(COMMENT /+) and $(COMMENT +/):
)
---
/+
// A single line of comment
/*
A comment that spans
multiple lines
*/
/+
It can even include nested /+ comments +/
+/
A comment block that includes other comments
+/
---
)
$(LI
Most of the whitespace in the source code is insignificant. It is good practice to write longer expressions as multiple lines or add extra whitespace to make the code more readable. Still, as long as the syntax rules of the language are observed, the programs can be written without any extra whitespace:
---
import std.stdio;void main(){writeln("Hard to read!");}
---
$(P
It can be hard to read source code with small amounts of whitespace.
)
)
)
$(PROBLEM_TEK
$(P
Enter non-numerical characters when the program is expecting integer values and observe that the program does not work correctly.
)
)
Macros:
SUBTITLE=Reading from the Standard Input
DESCRIPTION=Getting information from the input in D
KEYWORDS=d programming language tutorial book read stdin
MINI_SOZLUK=