* remove "\r" nonsense
[mascara-docs.git] / C / the.ansi.c.programming.language / c.programming.notes / homework / PS5a.html
blob9b814b65a1ca233abedfc54d2c1e7bfaccafc229
1 <!DOCTYPE HTML PUBLIC "-//W3O//DTD W3 HTML 2.0//EN">
2 <!-- This collection of hypertext pages is Copyright 1995-7 by Steve Summit. -->
3 <!-- This material may be freely redistributed and used -->
4 <!-- but may not be republished or sold without permission. -->
5 <html>
6 <head>
7 <link rev="owner" href="mailto:scs@eskimo.com">
8 <link rev="made" href="mailto:scs@eskimo.com">
9 <title>Assignment #5 Answers</title>
10 </head>
11 <body>
12 <H1>Assignment #5 Answers</H1>
18 <B>Introductory C Programming
19 <br>
20 <br>
21 UW Experimental College
22 <br>
23 <br>
24 Assignment #5 ANSWERS
25 </B><br>
26 <br>
27 <p>Question 1.
28 <I>What's wrong with
29 <TT>#define N 10;
30 </TT>?
31 </I><p>The semicolon at the end of the line
32 will become part of <TT>N</TT>'s definition,
33 which is hardly ever what you want.
34 <p>Question 2.
35 <I>Suppose you had the definition
36 <TT>#define SIX 2*3
37 </TT>.
38 What value would the declaration
39 <TT>int x = 12 / SIX;
40 </TT>initialize <TT>x</TT> to?
41 </I><p>18.
42 (18?
43 How could it be 18?
44 It sure looks like it should be 2, doesn't it?)
45 <p>The preprocessor performs a simple textual substitution;
46 it knows nothing about operator precedence,
47 or even much about the syntax of C.
48 After the preprocessor substitutes the value of the macro
49 <TT>SIX</TT>,
50 the declaration looks like
51 <pre>
52 int x = 12 / 2*3;
53 </pre>
54 Since multiplication and division ``group''
55 (or ``associate'')
56 from left to right,
57 this is interpreted as
58 <pre>
59 int x = (12 / 2) * 3;
60 </pre>
61 To guard against these ``surprises,''
62 it's a very good idea to parenthesize the values of macros which
63 are not simple constants.
64 In this case, a safer definition of the macro would have been
65 <pre>
66 #define SIX (2*3)
67 </pre>
68 This way, when the preprocessor performs its simple textual substitution,
69 the resulting expression is automatically parenthesized
70 so that the compiler gives you the result you expect.
71 (Of course,
72 this hypothetical <TT>SIX</TT> macro is useless in any case,
73 but the point is that whenever a macro's value is an expression
74 of any kind,
75 it needs extra parentheses
76 to avoid surprises.)
77 <p>Question 3.
78 <I>If the header file <TT>x.h</TT> contains
79 an external prototype declaration for a function <TT>q()</TT>,
80 where should <TT>x.h</TT> be included?
81 </I><p>It should be included in each source file where <TT>q()</TT>
82 is called, so that the compiler will see the prototype declaration
83 and be able to generate correct code.
84 It should <em>also</em> be included
85 in the source file where <TT>q()</TT> is <em>defined</em>,
86 so that the compiler will be able to notice, and complain about,
87 any mismatches between the prototype declaration and the actual definition.
88 (It's vital that the prototype
89 which will be
90 used where a function is called be accurate;
91 an incorrect prototype is worse than useless.)
92 <p>Question 4.
93 <I>How many differences can you think of between <TT>i</TT> and <TT>J</TT></I>?
94 <p>The line
95 <pre>
96 int i = 10;
97 </pre>
98 declares a conventional run-time variable, named <TT>i</TT>,
99 initially containing the value 10.
100 It will be possible to change <TT>i</TT>'s value at run time.
101 <TT>i</TT> may appear in expressions
102 (i.e., its value may be fetched),
103 but since it is not constant,
104 it could not be used where C requires a constant,
105 such as in the dimension of an array declaration.
106 <p>The line
107 <pre>
108 #define J 10
109 </pre>
110 on the other hand,
111 defines a preprocessor macro named <TT>J</TT> having the value <TT>10</TT>.
112 For the rest of the current source file, anywhere you write a single <TT>J</TT>,
113 the preprocessor will replace it with <TT>10</TT>.
114 An array declaration such as
115 <pre>
116 int a[J];
117 </pre>
118 will be fine;
119 it will be just as if you had written
120 <pre>
121 int a[10];
122 </pre>
123 However, <TT>J</TT> exists only at compile time.
124 It is not a run-time variable; if you tried to
125 ``change its value'' at run time by writing
126 <pre>
127 J = 20;
128 </pre>
129 it would be just as if you had written
130 <pre>
131 10 = 20;
132 </pre>
133 and the compiler would complain.
134 <p>(One more little difference is that the line
135 <TT>int i = 10;
136 </TT>ends in a semicolon,
137 while the line
138 <TT>#define J 10
139 </TT>does not.)
140 <p>Exercise 2.
141 <I>Write a program to read its input and write it out, double-spaced.
142 </I><p>This is easy if we realize that
143 all we have to do is
144 read the input a character at a time,
145 copying each input character through to the output,
146 except that whenever we see a <TT>'\n'</TT> character,
147 write a second one out, too.
148 <pre>
149 #include &lt;stdio.h&gt;
151 int main()
153 int c;
155 while((c = getchar()) != EOF)
157 putchar(c);
158 if(c == '\n')
159 putchar('\n');
162 return 0;
164 </pre>
165 The program won't be too interesting if you type text at it interactively.
166 If you're using a Unix or MS-DOS system,
167 you can run it on a file by typing
168 <pre>
169 doublespace &lt; filename
170 </pre>
171 The <TT>&lt;</TT> mechanism indicates that
172 the program should be run
173 with its ``standard input''
174 (i.e. the stream of characters read by <TT>getchar</TT>)
175 connected to the file with the given <TT>filename</TT>,
176 rather than to the keyboard.
177 <p>Exercise 3.
178 <I>Write a function
179 which counts the number of times a character appears in a string.
180 </I><p>Here is the function.
181 Notice that it is very similar to the <TT>mystrlen</TT> function in the notes,
182 except that rather than counting all characters in the string,
183 it only counts those matching the argument <TT>c</TT>.
184 <pre>
185 int countnchars(char string[], int ch)
187 int i;
188 int count = 0;
189 for(i = 0; string[i] != '\0'; i++)
191 if(string[i] == ch)
192 count++;
194 return count;
196 </pre>
197 Here is a tiny little main program, to test it out:
198 <pre>
199 #include &lt;stdio.h&gt;
201 extern int countnchars(char string[], int ch);
203 int main()
205 char string[] = "Hello, world!";
206 char c = 'o';
208 printf("The letter %c appears in \"%s\" %d times.\n",
209 c, string, countnchars(string, c));
210 return 0;
212 </pre>
213 <p>Exercise 4.
214 <I>Write a short program to read two lines of text,
215 and concatenate them using <TT>strcat</TT>.
216 </I><br>
217 <br>
218 <pre>
219 #include &lt;stdio.h&gt;
220 #include &lt;string.h&gt; /* for strcpy and strcat */
222 #define MAXLINE 100
224 extern int getline(char [], int);
226 int main()
228 char string1[MAXLINE], string2[MAXLINE];
229 int len1, len2;
230 char newstring[MAXLINE*2];
232 printf("enter first string:\n");
233 len1 = getline(string1, 100);
234 printf("enter second string:\n");
235 len2 = getline(string2, 100);
237 if(len1 == EOF || len2 == EOF)
238 exit(1);
240 strcpy(newstring, string1);
241 strcat(newstring, string2);
243 printf("%s\n", newstring);
245 return 0;
246 }</pre>
247 <p>Exercise 5.
248 <I>Write a function
249 to find a substring in a larger string
250 and replace it with a different substring.
251 </I><p>Here is one way.
252 (Since the function doesn't return anything,
253 I've defined it with a return type of <TT>void</TT>.)
254 <pre>
255 void replace(char string[], char from[], char to[])
257 int start, i1, i2;
258 for(start = 0; string[start] != '\0'; start++)
260 i1 = 0;
261 i2 = start;
262 while(from[i1] != '\0')
264 if(from[i1] != string[i2])
265 break;
266 i1++;
267 i2++;
269 if(from[i1] == '\0')
271 for(i1 = 0; to[i1] != '\0'; i1++)
272 string[start++] = to[i1];
273 return;
277 </pre>
278 This code is very similar to
279 the <TT>mystrstr</TT>
280 function
281 in the notes, chapter 10, section 10.4, p. 8.
282 (Since <TT>strstr</TT>'s job is to find one string within
283 another, it's a natural for the first half of <TT>replace</TT>.)
284 <p><I>Extra credit:
285 Think about what <TT>replace()</TT> should do
286 if the <TT>from</TT> string appears multiple times
287 in the input string.
288 </I><p>Our first
289 implementation
290 replaced only the first occurrence
291 (if any)
292 of the <TT>from</TT> string.
293 It happens, though, that it's trivial to rewrite our first version
294 to make it replace all occurrences--just omit the
295 <TT>return</TT> after the first string has been replaced:
296 <pre>
297 void replace(char string[], char from[], char to[])
299 int start, i1, i2;
300 for(start = 0; string[start] != '\0'; start++)
302 i1 = 0;
303 i2 = start;
304 while(from[i1] != '\0')
306 if(from[i1] != string[i2])
307 break;
308 i1++;
309 i2++;
311 if(from[i1] == '\0')
313 for(i1 = 0; to[i1] != '\0'; i1++)
314 string[start++] = to[i1];
318 </pre>
319 <hr>
320 <hr>
322 This page by <a href="http://www.eskimo.com/~scs/">Steve Summit</a>
323 // <a href="copyright.html">Copyright</a> 1995-9
324 // <a href="mailto:scs@eskimo.com">mail feedback</a>
325 </p>
326 </body>
327 </html>