📄 chapter1.html
字号:
word per line.<h2><a name="s1.6">1.6 Arrays</a></h2>Let is write a program to count the number of occurrences of each digit, ofwhite space characters (blank, tab, newline), and of all other characters.This is artificial, but it permits us to illustrate several aspects of C inone program.<p>There are twelve categories of input, so it is convenient to use an array tohold the number of occurrences of each digit, rather than ten individualvariables. Here is one version of the program:<pre> #include <stdio.h> /* count digits, white space, others */ main() { int c, i, nwhite, nother; int ndigit[10]; nwhite = nother = 0; for (i = 0; i < 10; ++i) ndigit[i] = 0; while ((c = getchar()) != EOF) if (c >= '0' && c <= '9') ++ndigit[c-'0']; else if (c == ' ' || c == '\n' || c == '\t') ++nwhite; else ++nother; printf("digits ="); for (i = 0; i < 10; ++i) printf(" %d", ndigit[i]); printf(", white space = %d, other = %d\n", nwhite, nother); }</pre>The output of this program on itself is<pre> digits = 9 3 0 0 0 0 0 0 0 1, white space = 123, other = 345</pre>The declaration<pre> int ndigit[10];</pre>declares <tt>ndigit</tt> to be an array of 10 integers. Array subscripts alwaysstart at zero in C, so the elements are <tt>ndigit[0], ndigit[1], ...,ndigit[9]</tt>. This is reflected in the <tt>for</tt> loops that initializeand print the array.<p>A subscript can be any integer expression, which includes integer variableslike <tt>i</tt>, and integer constants.<p>This particular program relies on the properties of the characterrepresentation of the digits. For example, the test<pre> if (c >= '0' && c <= '9')</pre>determines whether the character in <tt>c</tt> is a digit. If it is, thenumeric value of that digit is<pre> c - '0'</pre>This works only if <tt>'0', '1', ..., '9'</tt> have consecutive increasingvalues. Fortunately, this is true for all character sets.<p>By definition, <tt>char</tt>s are just small integers, so <tt>char</tt>variables and constants are identical to <tt>int</tt>s in arithmeticexpressions. This is natural and convenient; for example <tt>c-'0'</tt> is aninteger expression with a value between 0 and 9 corresponding to thecharacter <tt>'0'</tt> to <tt>'9'</tt> stored in <tt>c</tt>, and thus a validsubscript for the array <tt>ndigit</tt>.<p>The decision as to whether a character is a digit, white space, or somethingelse is made with the sequence<pre> if (c >= '0' && c <= '9') ++ndigit[c-'0']; else if (c == ' ' || c == '\n' || c == '\t') ++nwhite; else ++nother;</pre>The pattern<pre> if (<em>condition<sub>1</sub></em>) <em>statement<sub>1</sub></em> else if (<em>condition<sub>2</sub></em>) <em>statement<sub>2</sub></em> ... ... else <em>statement<sub>n</sub></em></pre>occurs frequently in programs as a way to express a multi-way decision. The<em>conditions</em> are evaluated in order from the top until some<em>condition</em> is satisfied; at that point the corresponding<em>statement</em> part is executed, and the entire construction is finished.(Any <em>statement</em> can be several statements enclosed in braces.) Ifnone of the conditions is satisfied, the <em>statement</em> after the final<tt>else</tt> is executed if it is present. If the final <tt>else</tt> and<em>statement</em> are omitted, as in the word count program, no action takesplace. There can be any number of<p><tt>else if</tt>(<em>condition</em>)<br> <em>statement</em><p>groups between the initial <tt>if</tt> and the final <tt>else</tt>.<p>As a matter of style, it is advisable to format this construction as we haveshown; if each <tt>if</tt> were indented past the previous <tt>else</tt>, a longsequence of decisions would march off the right side of the page.<p>The <tt>switch</tt> statement, to be discussed in <a href="chapter4.html">Chapter 4</a>,provides another way to write a multi-way branch that is particulary suitablewhen the condition is whether some integer or character expression matchesone of a set of constants. For contrast, we will present a <tt>switch</tt>version of this program in <a href="chapter3.html#s3.4">Section 3.4</a>.<p><strong>Exercise 1-13.</strong> Write a program to print a histogram of thelengths of words in its input. It is easy to draw the histogram with the barshorizontal; a vertical orientation is more challenging.<p><strong>Exercise 1-14.</strong> Write a program to print a histogram of thefrequencies of different characters in its input.<h2><a name="s1.7">1.7 Functions</a></h2>In C, a function is equivalent to a subroutine or function in Fortran, or aprocedure or function in Pascal. A function provides a convenient way toencapsulate some computation, which can then be used without worrying aboutits implementation. With properly designed functions, it is possible toignore <em>how</em> a job is done; knowing <em>what</em> is done is sufficient. Cmakes the sue of functions easy, convinient and efficient; you will oftensee a short function defined and called only once, just because it clarifiessome piece of code.<p>So far we have used only functions like <tt>printf</tt>, <tt>getchar</tt> and<tt>putchar</tt> that have been provided for us; now it's time to write a fewof our own. Since C has no exponentiation operator like the <tt>**</tt> ofFortran, let us illustrate the mechanics of function definition by writing afunction <tt>power(m,n)</tt> to raise an integer <tt>m</tt> to a positiveinteger power <tt>n</tt>. That is, the value of <tt>power(2,5)</tt> is 32.This function is not a practical exponentiation routine, since it handlesonly positive powers of small integers, but it's good enough forillustration.(The standard library contains a function <tt>pow(x,y)</tt> thatcomputes <em>x<sup>y</sup></em>.)<p>Here is the function <tt>power</tt> and a main program to exercise it, so youcan see the whole structure at once.<pre> #include <stdio.h> int power(int m, int n); /* test power function */ main() { int i; for (i = 0; i < 10; ++i) printf("%d %d %d\n", i, power(2,i), power(-3,i)); return 0; } /* power: raise base to n-th power; n >= 0 */ int power(int base, int n) { int i, p; p = 1; for (i = 1; i <= n; ++i) p = p * base; return p; }</pre>A function definition has this form:<pre>return-type function-name(parameter declarations, if any){ declarations statements}</pre>Function definitions can appear in any order, and in one source file orseveral, although no function can be split between files. If the sourceprogram appears in several files, you may have to say more to compile andload it than if it all appears in one, but that is an operating systemmatter, not a language attribute. For the moment, we will assume that bothfunctions are in the same file, so whatever you have learned about running Cprograms will still work.<p>The function <tt>power</tt> is called twice by <tt>main</tt>, in the line<pre> printf("%d %d %d\n", i, power(2,i), power(-3,i));</pre>Each call passes two arguments to <tt>power</tt>, which each time returns aninteger to be formatted and printed. In an expression, <tt>power(2,i)</tt> is aninteger just as <tt>2</tt> and <tt>i</tt> are. (Not all functions produce aninteger value; we will take this up in <a href="chapter4.html">Chapter 4</a>.)<p>The first line of <tt>power</tt> itself,<pre> int power(int base, int n)</pre>declares the parameter types and names, and the type of the result that thefunction returns. The names used by <tt>power</tt> for its parameters are localto <tt>power</tt>, and are not visible to any other function: other routinescan use the same names without conflict. This is also true of the variables<tt>i</tt> and <tt>p</tt>: the <tt>i</tt> in <tt>power</tt> is unrelated tothe <tt>i</tt> in <tt>main</tt>.<p>We will generally use <em>parameter</em> for a variable named in theparenthesized list in a function. The terms <em>formal argument</em> and<em>actual argument</em> are sometimes used for the same distinction.<p>The value that <tt>power</tt> computes is returned to <tt>main</tt> by the<tt>return</tt>: statement. Any expression may follow <tt>return</tt>:<pre> return <em>expression</em>;</pre>A function need not return a value; a return statement with no expressioncauses control, but no useful value, to be returned to the caller, as does``falling off the end'' of a function by reaching the terminating rightbrace. And the calling function can ignore a value returned by a function.<p>You may have noticed that there is a <tt>return</tt> statement at the end of<tt>main</tt>. Since <tt>main</tt> is a function like any other, it may return avalue to its caller, which is in effect the environment in which the programwas executed. Typically, a return value of zero implies normal termination;non-zero values signal unusual or erroneous termination conditions. In theinterests of simplicity, we have omitted <tt>return</tt> statements from our<tt>main</tt> functions up to this point, but we will include them hereafter, asa reminder that programs should return status to their environment.<p>The declaration<pre> int power(int base, int n);</pre>just before <tt>main</tt> says that <tt>power</tt> is a function that expects two<tt>int</tt> arguments and returns an <tt>int</tt>. This declaration, which iscalled a <em>function prototype</em>, has to agree with the definition and usesof <tt>power</tt>. It is an error if the definition of a function or any uses ofit do not agree with its prototype.<p>parameter names need not agree. Indeed, parameter names are optional in afunction prototype, so for the prototype we could have written<pre> int power(int, int);</pre>Well-chosen names are good documentation however, so we will often use them.<p>A note of history: the biggest change between ANSI C and earlier versions ishow functions are declared and defined. In the original definition of C, the<tt>power</tt> function would have been written like this:<pre> /* power: raise base to n-th power; n >= 0 */ /* (old-style version) */ power(base, n) int base, n; { int i, p; p = 1; for (i = 1; i <= n; ++i) p = p * base; return p; }</pre>The parameters are named between the parentheses, and their types aredeclared before opening the left brace; undeclared parameters are taken as<tt>int</tt>. (The body of the function is the same as before.)<p>The declaration of <tt>power</tt> at the beginning of the program would havelooked like this:<pre> int power();</pre>No parameter list was permitted, so the compiler could not readily check that<tt>power</tt> was being called correctly. Indeed, since by default <tt>power</tt>would have been assumed to return an <tt>int</tt>, the entire declaration mightwell have been omitted.<p>The new syntax of function prototypes makes it much easier for a compiler todetect errors in the number of arguments or their types. The old style ofdeclaration and definition still works in ANSI C, at least for a transitionperiod, but we strongly recommend that you use the new form when you have acompiler that supports it.<p><strong>Exercise 1.15.</strong> Rewrite the temperature conversion program of<a href="#s1.2">Section 1.2</a> to use a function for conversion.<h2><a name="s1.8">1.8 Arguments - Call by Value</a></h2>One aspect of C functions may be unfamiliar to programmers who are used tosome other languages, particulary Fortran. In C, all function arguments arepassed ``by value.'' This means that the called function is given the valuesof its arguments in temporary variables rather than the originals. This leadsto some different properties than are seen with ``call by reference''languages like Fortran or with <tt>var</tt> parameters in Pascal, in which thecalled routine has access to the original argument, not a local copy.<p>Call by value is an asset, however, not a liability. It usually leads to morecompact programs with fewer extraneous variables, because parameters can betreated as conveniently initialized local variables in the called routine.For example, here is a version of <tt>power</tt> that makes use of this property.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -