home *** CD-ROM | disk | FTP | other *** search
/ minnie.tuhs.org / 2014.11.minnie.tuhs.org.tar / minnie.tuhs.org / UnixArchive / PDP-11 / Trees / V6 / usr / doc / ctut / ct2 < prev    next >
Text File  |  1975-06-27  |  9KB  |  427 lines

  1. .NH
  2. If; relational operators; compound statements
  3. .PP
  4. The basic conditional-testing statement in C
  5. is the
  6. .UL if
  7. statement:
  8. .E1
  9. c = getchar( );
  10. if( c \*= '?' )
  11.     printf("why did you type a question mark?\\n");
  12. .E2
  13. The simplest form of
  14. .UL if
  15. is
  16. .E1
  17. if (expression) statement
  18. .E2
  19. .PP
  20. The condition to be tested is any expression enclosed in parentheses.
  21. It is followed by a statement.
  22. The expression is evaluated, and if its value is non-zero,
  23. the statement is executed.
  24. There's an
  25. optional
  26. .UL else
  27. clause, to be described soon.
  28. .PP
  29. The character sequence `=='  is one of the relational operators in C;
  30. here is the complete set:
  31. .E1
  32. \*=    equal to (\*.EQ\*. to Fortraners)
  33. !=    not equal to
  34. >    greater than
  35. <    less than
  36. >=    greater than or equal to
  37. <=    less than or equal to
  38. .E2
  39. .PP
  40. The value of
  41. .UL ``expression
  42. .UL relation
  43. .UL expression''
  44. is 1 if the relation is true,
  45. and 0 if false.
  46. Don't forget that the equality test is `==';
  47. a single `=' causes an assignment, not a test,
  48. and invariably leads to disaster.
  49. .PP
  50. Tests can be combined with the operators 
  51. .UL `&&'
  52. .UC (AND),
  53. .UL `\*|'
  54. .UC (OR),
  55. and
  56. .UL `!'
  57. .UC (NOT).
  58. For example, we can test whether a character is blank or tab or newline
  59. with
  60. .E1
  61. if( c\*=' ' \*| c\*='\\t' \*| c\*='\\n' ) \*.\*.\*.
  62. .E2
  63. C guarantees that
  64. .UL `&&'
  65. and
  66. .UL `\*|'
  67. are evaluated left to right _
  68. we shall soon see cases where this matters.
  69. .PP
  70. One of the nice things about C is that the
  71. .UL statement
  72. part of an 
  73. .UL if
  74. can be made arbitrarily complicated
  75. by enclosing a set of statements
  76. in {}.
  77. As a simple example,
  78. suppose we want to ensure that
  79. .UL a
  80. is bigger than
  81. .UL b,
  82. as part of a sort routine.
  83. The interchange of
  84. .UL a
  85. and
  86. .UL b
  87. takes three statements in C,
  88. grouped together by {}:
  89. .E1
  90. .ne 5
  91. if (a < b) {
  92.     t = a;
  93.     a = b;
  94.     b = t;
  95. }
  96. .E2
  97. .PP
  98. As a general rule in C, anywhere you can use a simple statement,
  99. you can use any compound statement, which is just a number of simple
  100. or compound ones enclosed in {}.
  101. There is no semicolon after the } of a compound statement,
  102. but there
  103. .ul
  104. is
  105. a semicolon after the last non-compound statement inside the {}.
  106. .PP
  107. The ability to replace single statements by complex ones at will
  108. is one feature that makes C much more pleasant to use than Fortran.
  109. Logic (like the exchange in the previous example) which would require several GOTO's and labels in Fortran can
  110. and should
  111. be
  112. done in C without any, using compound statements.
  113. .NH
  114. While Statement; Assignment within an Expression; Null Statement
  115. .PP
  116. The basic looping mechanism in C is the
  117. .UL while
  118. statement.
  119. Here's a program that copies its input to its output
  120. a character at a time.
  121. Remember that `\\0' marks the end of file.
  122. .E1
  123. main(~) {
  124.     char c;
  125.     while( (c=getchar(~)) != '\\0' )
  126.         putchar(c);
  127. }
  128. .E2
  129. The
  130. .UL while
  131. statement is a loop, whose general form
  132. is
  133. .E1
  134. while (expression) statement
  135. .E2
  136. Its meaning is
  137. .E1
  138. (a) evaluate the expression
  139. (b) if its value is true (i\*.e\*., not zero)
  140.         do the statement, and go back to (a)
  141. .E2
  142. Because the expression is tested before the statement
  143. is executed,
  144. the statement part can be executed zero times,
  145. which is often desirable.
  146. As in the
  147. .UL if
  148. statement, the expression and the statement can both be
  149. arbitrarily complicated, although we haven't seen that yet.
  150. Our example gets the character,
  151. assigns it to
  152. .UL c,
  153. and then tests if it's a `\\0''.
  154. If it is not a `\\0',
  155. the statement part of the 
  156. .UL while 
  157. is executed,
  158. printing the character.
  159. The
  160. .UL while
  161. then repeats.
  162. When the input character is finally a `\\0',
  163. the
  164. .UL while
  165. terminates,
  166. and so does
  167. .UL main\*.
  168. .PP
  169. Notice that we used an assignment statement
  170. .E1
  171. c = getchar(~)
  172. .E2
  173. within an expression.
  174. This is a handy notational shortcut which often produces clearer code.
  175. (In fact it is often the only way to write the code cleanly.
  176. As an exercise, re-write the file-copy without
  177. using an assignment inside an expression.)
  178. It works because an assignment statement has a value, just as any
  179. other expression does.
  180. Its value is the value of the right hand side.
  181. This also implies that we can use multiple assignments like
  182. .E1
  183. x = y = z = 0;
  184. .E2
  185. Evaluation goes from right to left.
  186. .PP
  187. By the way, the extra parentheses in the assignment statement
  188. within the conditional were really necessary:
  189. if we had said
  190. .E1
  191. c = getchar(~) != '\\0'
  192. .E2
  193. .UL c
  194. would be set to 0 or 1 depending on whether the character fetched
  195. was an end of file or not.
  196. This is because in the absence of parentheses the assignment operator `='
  197. is evaluated after the relational operator `!='.
  198. When in doubt, or even if not,
  199. parenthesize.
  200. .PP
  201. Since
  202. .UL putchar(c)
  203. returns
  204. .UL c
  205. as its function value,
  206. we could also copy the input to the output by nesting the calls to
  207. .UL getchar
  208. and
  209. .UL putchar:
  210. .E1
  211. main(~) {
  212.     while( putchar(getchar(~)) != '\\0' ) ;
  213. }
  214. .E2
  215. What statement is being repeated?~
  216. None, or technically, the
  217. .ul
  218. null
  219. statement,
  220. because all the work is really done within the test part of the
  221. .UL while\*.
  222. This version is slightly different from the previous one,
  223. because the final `\\0' is copied to the output
  224. before we decide to stop.
  225. .NH
  226. Arithmetic
  227. .PP
  228. The arithmetic operators are the usual `+', `\(mi', `*', and `/'
  229. (truncating integer division if the operands are
  230. both
  231. .UL int),
  232. and the remainder or mod operator `%':
  233. .E1
  234. x = a%b;
  235. .E2
  236. sets
  237. .UL x
  238. to the remainder after
  239. .UL a
  240. is divided by
  241. .UL b
  242. (i.e.,
  243. .UL a
  244. .UL mod
  245. .UL b)\*.
  246. The results are machine dependent unless
  247. .UL a
  248. and
  249. .UL b
  250. are both positive.
  251. .PP
  252. In arithmetic,
  253. .UL char
  254. variables can usually be treated like
  255. .UL int
  256. variables.
  257. Arithmetic on characters
  258. is quite legal, and often makes sense:
  259. .E1
  260. c = c + 'A' - 'a';
  261. .E2
  262. converts a single lower case ascii character stored in
  263. .UL c
  264. to upper case,
  265. making use of the fact that
  266. corresponding ascii letters are a fixed distance apart.
  267. The rule governing this arithmetic is that all
  268. .UL chars
  269. are converted to
  270. .UL int
  271. before the arithmetic is done.
  272. Beware that conversion may involve sign-extension _
  273. if the leftmost bit of a character is 1,
  274. the resulting integer might be negative.
  275. (This doesn't happen with genuine characters on any current machine.)
  276. .PP
  277. So to convert a file into lower case:
  278. .E1
  279. main( ) {
  280.     char c;
  281.     while( (c=getchar( )) != '\\0' )
  282.         if( 'A'<=c && c<='Z' )
  283.             putchar(c+'a'-'A');
  284.         else
  285.             putchar(c);
  286. }
  287. .E2
  288. Characters have different sizes on different machines.
  289. Further, this code won't work
  290. on an IBM machine,
  291. because the letters
  292. in the ebcdic alphabet are not contiguous.
  293. .NH
  294. Else Clause; Conditional Expressions
  295. .PP
  296. We just used an
  297. .UL else
  298. after an 
  299. .UL if\*.
  300. The most general form of
  301. .UL if
  302. is
  303. .E1
  304. if (expression) statement1 else statement2
  305. .E2
  306. the
  307. .UL else
  308. part is optional, but often useful.
  309. The canonical example sets
  310. .UL x
  311. to the
  312. minimum of
  313. .UL a
  314. and
  315. .UL b:
  316. .E1
  317. .ne 4
  318. if (a < b)
  319.     x = a;
  320. else
  321.     x = b;
  322. .E2
  323. Observe that there's a semicolon after
  324. .UL x=a\*.
  325. .PP
  326. C provides an alternate form of conditional which is often more
  327. concise.
  328. It is called the ``conditional expression'' because it is a conditional
  329. which actually has a value
  330. and can be used anywhere an expression can.
  331. The value of
  332. .E1
  333. a<b ? a : b;
  334. .E2
  335. is
  336. .UL a
  337. if
  338. .UL a
  339. is less than
  340. .UL b;
  341. it is
  342. .UL b
  343. otherwise.
  344. In general, the form
  345. .E1
  346. expr1 ? expr2 : expr3
  347. .E2
  348. means
  349. ``evaluate
  350. .UL expr1\*.
  351. If it is not zero, the value of the whole thing is
  352. .UL expr2;
  353. otherwise the value is
  354. .UL expr3\*.''
  355. .PP
  356. To set
  357. .UL x
  358. to the minimum of
  359. .UL a
  360. and
  361. .UL b,
  362. then:
  363. .E1
  364. x = (a<b ? a : b);
  365. .E2
  366. The parentheses aren't necessary because 
  367. .UL `?:'
  368. is evaluated before `=',
  369. but safety first.
  370. .PP
  371. Going a step further,
  372. we could write the loop in the lower-case program as
  373. .E1
  374. while( (c=getchar( )) != '\\0' )
  375.     putchar( ('A'<=c && c<='Z') ? c-'A'+'a' : c );
  376. .E2
  377. .PP
  378. .UL If's
  379. and
  380. .UL else's
  381. can be used to construct logic that
  382. branches one of several ways and then rejoins, a common
  383. programming structure, in this way:
  384. .E1
  385. if(\*.\*.\*.)
  386.     {\*.\*.\*.}
  387. else if(\*.\*.\*.)
  388.     {\*.\*.\*.}
  389. else if(\*.\*.\*.)
  390.     {\*.\*.\*.}
  391. else
  392.     {\*.\*.\*.}
  393. .E2
  394. The conditions are tested in order,
  395. and exactly one block is executed _ either the first one whose
  396. .UL if
  397. is satisfied,
  398. or the one for the last
  399. .UL else\*.
  400. When this block is finished,
  401. the next statement executed is the one after the last
  402. .UL else\*.
  403. If no action is to be taken for the ``default'' case,
  404. omit
  405. the last
  406. .UL else\*.
  407. .PP
  408. For example, to count letters, digits and others in a file,
  409. we could write
  410. .E1
  411. .ne 9
  412. main( ) {
  413.     int let, dig, other, c;
  414.     let = dig = other = 0;
  415.     while( (c=getchar( )) != '\\0' )
  416.         if( ('A'<=c && c<='Z') \*| ('a'<=c && c<='z') )  \*+let;
  417.         else if( '0'<=c && c<='9' )  \*+dig;
  418.         else  \*+other;
  419.     printf("%d letters, %d digits, %d others\\n", let, dig, other);
  420. }
  421. .E2
  422. The
  423. `++' operator means
  424. ``increment
  425. by 1'';
  426. we will get to it in the next section.
  427.