C语言程序(第一版) 1

来源:互联网 发布:太阳伞黑胶在外面 知乎 编辑:程序博客网 时间:2024/05/15 06:27

第一章 指导性的介绍

Let us begin with a quick introduction in C. Our aim is to show the

让我们开始一个快速的C语言介绍。我们的目标是直接用代码展现必要的语言元

essential elements of the language in real programs, but without getting

素,而不是陷入到细节,规则或其他的一些东西上。

bogged down in details, rules, and exceptions. At this point, we are not

                                             从这个意义上说,我们不准

trying to be complete or even precise (save that the examples are meant

备做到完整或精确(但是例子是完全正确的)。

to be correct). We want to get you as quickly as possible to the point

                我们希望你能尽快地写出有用的程序,并且把注意力放在基础

where you can write useful programs, and to do that we have to concentrate

要素上:变量和常量,算法,循环控制,函数,输入输出的基本原理。

on the basics: variables and constants, arithmetic, control flow, functions, and the rudiments of input and output. We are intentionally

                                                 我们在这章中有意回避

leaving out of this chapter features of C that are important for writing

了写大型程序的C语言特色。

bigger programs. These include pointers, structures, most of C's rich set

                这些特色包括:指针,结构体,C语言丰富的运算符,一些循

of operators, several control-flow statements, and the standard library. 环控制语句,还有标准库。

This approach and its drawbacks. Most notable is that the complete storyon

这个入门和它的不足之处。       最显著的是在这儿找不到完整的语言特征,

any particular feature is not found here, and the tutorial, by being brief,

还有这个简单的导言,可能会给予误导。

may also be misleading. And because the examples do not use the full power

                       因为这些例子没有用到C语言的完整功能,所以它们

of C, they are not as concise and elegant as they might be. We have tried

不会像它们本来的那样简洁优美。                            我们曾尝试着

to minimize these effects, but be warned. Another drawback is that later

降低这种效果,但是被劝告不要。          另一个不足之处是在以后的章节中

chapters will necessarily repeat some of this chapter. We hope that the

将必须重复这章的一些东西。                            比起困扰你,我们

repetition will help you more than it annoys.

希望这些重复更能帮助你。

In any case, experienced programmers should be able to extrapolate from

另外,有经验的程序员可以从本章的材料中推断出对他们编程有用的东西来。

the material in this chapter to their own programming needs. Beginners

                                                            初学者可

should supplement it by writing small, similar programs of their own. Both

以写一些小的,类似例子的程序作为提高。

groups can use it as a framework on which to hang the more detailed

而团队成员可以用第二章中的内容作为架构。

descriptions that begin in Chapter 2.

1.1          Getting Started开始吧

The only way to learn a new programming language is by writing programs

只有一个办法可以学习新语言,用它写程序。

in it. The first program to write is the same for all languages:

第一个程序和其他任何语言一样:
 Print the words
 
打印字母“hello, world

hello, world

This is a big hurdle; to leap over it you have to be able to create the

这是个问题:为了得到打印你必须创建一个文档,并成功地编译它,装载它,运

program text somewhere, compile it successfully, load it, run it, and find

行它,然后找到它的输出信息。

out where your output went. With these mechanical details mastered,

                            只要掌握了这些枯燥的细节,其他一切都会变

everything else is comparatively easy.

得简单。

In C, the program to print ``hello, world'' is

hello, world”用C语言写的程序如下:
#include <stdio.h>
 
   main()
   {
     printf("hello, world/n");
   }

Just how to run this program depends on the system you are using. As a specific example, on the

你的系统决定如何运行这个程序。                         作为一个详细的例子,我需

UNIX operating system you must create the program in a file whose name ends in ``.c'', such as

要告诉你,在UNIX系统中你创建的程序文件必须以“.c”结尾,像hello.c,用命令

hello.c, then compile it with the command

cc hello.c 编译

   cc hello.c

If you haven't botched anything, such as omitting a character or misspelling something, the

如果你没有遗漏任何东西,编译过程会完全安静,它会产生一个可执行文件a.out

compilation will proceed silently, and make an executable file called a.out. If you run a.out by

敲上a.out,你就可以运行它了

typing the command

   a.out

it will print

hello, world就会出现在你的眼前

   hello, world

On other systems, the rules will be different; check with a local expert.

在其他系统上,命令可能会不一样,找个高手试试。

Now, for some explanations about the program itself. A C program, whatever its size, consists of

现在来聊聊程序吧。                          一个C程序,不论它有多大,都由函数

functions and variables. A function contains statements that specify the computing operations to

和变量组成。        一个函数包括完成特定计算的计算机指令,变量保存在计算过程中的

be done, and variables store values used during the computation. C functions are like the

值。                                                 C语言的函数类似于Fortran

subroutines and functions in Fortran or the procedures and functions of Pascal. Our example is a

言的子程序和函数,或Pascal语言的步骤和函数。                     我们的例子中就

function named main. Normally you are at liberty to give functions whatever names you like, but

有个函数叫main  通常你可以给函数起任何你喜欢的名字,但main是个例外---程序从

``main'' is special - your program begins executing at the beginning of main. This means that

Main函数开始。                                                这就是说每个程序

every program must have a main somewhere.

都必须有个main函数。

main will usually call other functions to help perform its job, some that you wrote, and others

main函数调用其他的函数去完成它的工作,一些是你写的,另一些在提供给你的库中。

from libraries that are provided for you. The first line of the program,

                             程序的第一行
#include <stdio.h>

tells the compiler to include information about the standard input/output library; the line

告诉编译器包含这个标准输入输出库;这行在大多数C源程序的开始都可以看到。

appears at the beginning of many C source files. The standard library is described in Chapter 7

                                        你可以在第七章和附录B中找到它。

and Appendix B.

One method of communicating data between functions is for the calling function to provide a list

函数之间通信的其中一个办法是,建立一个调用值的表,对调用它的函数而言,它叫做参数。

of values, called arguments, to the function it calls. The parentheses after the function name

                                          它就放在函数名后面的圆括号中。

surround the argument list. In this example, main is defined to be a function that expects no

                       在这个例子中,main函数被定义成一个用()表明没有参数的函

arguments, which is indicated by the empty list ( ).

数。


#include <stdio.h>                 include information about standard library  包含标准库文件的信息
main()                                          define a function called main   定义一个没有参数叫main的函数
                                             that received no argument values
{                                   statements of main are enclosed in braces函数被大括号包围着
    printf("hello, world/n");              main calls library function printf调用库函数printf打印这组字符,“/n”表示换行。
                                         to print this sequence of characters
}                                         /n represents the newline character

The first C program 第一个C程序


The statements of a function are enclosed in braces { }. The function main contains only one

整个函数用大括号{ }括起来。                     这个main函数只有一个语句,

statement,

   printf("hello, world/n");

A function is called by naming it, followed by a parenthesized list of arguments, so this calls the

调用一个函数名就可以调用这个函数,再在后面的括号内跟上参数,像上面的printf函数

function printf with the argument "hello, world/n". printf is a library function that

带上参数”hello, world/n”的调用。                    Printf是个打印输出的函数,打印

prints output, in this case the string of characters between the quotes.

引号之间的字符串。

A sequence of characters in double quotes, like "hello, world/n", is called a character string

一组字符有两种说法,像“hello, world/n”,可以叫字符串,也可以叫字符常量。

or string constant. For the moment our only use of character strings will be as arguments for

                这里这个字符串的唯一用途是作为printf或其他函数的参数。

printf and other functions.

The sequence /n in the string is C notation for the newline character, which when printed

字符串中的字符/n是一个新行的C语言标志,当打印时,光标移至新行的左边第一个标志

advances the output to the left margin on the next line. If you leave out the /n (a worthwhile

处。                                         如果在代码中去掉/n(值得一试),你会

experiment), you will find that there is no line advance after the output is printed. You must use

发现没有任何新行的打印信息。                                       printf参数

/n to include a newline character in the printf argument; if you try something like

中你必须用/n来包含一个新的换行符;如果你尝试下面的代码

   printf("hello, world
   ");

the C compiler will produce an error message.

C编译器会报一个错误信息。

printf never supplies a newline character automatically, so several calls may be used to build

printf不会自动地提供一个换行符,

up an output line in stages. Our first program could just as well have been written

                      我们第一个程序也可以这样写

   #include <stdio.h>
 
   main()
   {
     printf("hello, ");
     printf("world");
     printf("/n");
   }

to produce identical output.

输出的打印信息是相同的。

Notice that /n represents only a single character. An escape sequence like /n provides a general

注意/n仅代表一个字符。                  类似/n的字符提供了一种方式,用于显示

and extensible mechanism for representing hard-to-type or invisible characters.  Among the

难以打印出来的和一些隐藏的字符。                               另外,C语言还

others that C provides are /t for tab, /b for backspace, /" for the double quote and // for the

提供了/t对应tab/b对应退回键,/”对应引号,//对应反斜杠。

backslash itself. There is a complete list in Section 2.3.

             你能在2.3章节中找到完整的表。

Exercise 1-1. Run the ``hello, world'' program on your system. Experiment with leaving out

练习 1-1 在系统上运行”hello, world”程序。试着移除程序的某些部分,看看你能得到什么

parts of the program, to see what error messages you get.

样的错误。

Exercise 1-2. Experiment to find out what happens when prints's argument string contains /c,

练习 1-2 试试在printf函数的参数中包含/c,并打印看看有什么不同。

where c is some character not listed above.

1.2 Variables and Arithmetic Expressions

变量和算术表达式

The next program uses the formula oC=(5/9)(oF-32) to print the following table of Fahrenheit

下一个程序用于打印华氏温度与其对应的摄氏温度表

temperatures and their centigrade or Celsius equivalents:

   1    -17
   20   -6
   40   4
   60   15
   80   26
   100  37
   120  48
   140  60
   160  71
   180  82
   200  93
   220  104
   240  115
   260  126
   280  137
   300  148

The program itself still consists of the definition of a single function named main. It is longer

当然这个程序同样包含一个叫main的函数。                           它比打印

than the one that printed ``hello, world'', but not complicated.  It introduces several new

“hello, world”的程序要长些,但并不复杂。                   它显示了一些新的东西,

ideas, including comments, declarations, variables, arithmetic expressions, loops , and formatted

像注释,声明,变量,算术表达式,循环和格式化输出。

output.

   #include <stdio.h>
 
   /* print Fahrenheit-Celsius table
       for fahr = 0, 20, ..., 300 */
   main()
   {
     int fahr, celsius;
     int lower, upper, step;
 
     lower = 0;      /* lower limit of temperature scale */
     upper = 300;    /* upper limit */
     step = 20;      /* step size */
 
     fahr = lower;
     while (fahr <= upper) {
         celsius = 5 * (fahr-32) / 9;
         printf("%d/t%d/n", fahr, celsius);
         fahr = fahr + step;
     }
   }

The two lines

  /* print Fahrenheit-Celsius table
      for fahr = 0, 20, ..., 300 */

are a comment, which in this case explains briefly what the program does.  Any characters

这两行是注释,简单地解释程序的作用。                         /**/之间的任何

between /* and */ are ignored by the compiler; they may be used freely to make a program

字符都会被编译器忽略;这些注释可以使程序的可读性提高。

easier to understand. Comments may appear anywhere where a blank, tab or newline can.

                  这些注释可以出现在任何空格、tab或新行能出现的地方。

In C, all variables must be declared before they are used, usually at the beginning of the function

C中,所有的变量必须在使用它们之前声明,通常在执行语句的前面,即函数的开始。

before any executable statements. A declaration announces the properties of variables; it

                            一个声明告诉计算机这个变量的属性;它包括一个名字和

consists of a name and a list of variables, such as

一个变量表,像这样

    int fahr, celsius;
    int lower, upper, step;

The type int means that the variables listed are integers; by contrast with float, which means

类型int表示变量都是整数;对照类型float,表示变量是浮点型的,即可能含有小数部分。

floating point, i.e., numbers that may have a fractional part. The range of both int and float

                                                 intfloat的范围依靠于你所用的

depends on the machine you are using; 16-bits ints, which lie between -32768 and +32767, are

机器;通常的16-bitsint,在范围-32768+32767之间,当然,你可以推断出32-bit

common, as are 32-bit ints.  A float number is typically a 32-bit quantity, with at least six

int表示的范围。        一个float类型通常是32-bit,它有最少6位有效数字,表示的

significant digits and magnitude generally between about 10-38 and 1038.

范围在10-38 1038之间。

C provides several other data types besides int and float, including:

C语言在intfloat之外,还提供了其他几种数据类型,包括:

 char 

 character – a single byte

 short 

 short integer

 long 

 long integer

 double 

 double-precision floating point 

The size of these objects is also machine-dependent. There are also arrays, structures and unions

这些类型的大小同样由机器来决定。           另外还有由这些基础类型组成的数组、结

of these basic types, pointers to them, and functions that return them, all of which we will meet

构体、共用体类型,指向它们的指针,返回它们的函数,所有这些我们都将在接下来的章节

in due course. Computation in the temperature conversion program begins with the assignment

中遇到。    温度转换的计算程序从这些值开始

statements

    lower = 0;
    upper = 300;
    step = 20;

which set the variables to their initial values. Individual statements are terminated by semicolons.

设置初始值。                         每一行单独的语句都以分号结束。

Each line of the table is computed the same way, so we use a loop that repeats once per output

表的每一行数据都进行着相同的计算,所以我们可以用一个循环来重复计算输出的每一行;

line; this is the purpose of the while loop

    这是while循环的效果

    while (fahr <= upper) {
       ...
    }

The while loop operates as follows: The condition in parentheses is tested. If it is true (fahr is

While循环是这样工作的:首先测试圆括号里的条件。若它为真(fahr小于或等于upper),

less than or equal to upper), the body of the loop (the three statements enclosed in braces) is

则循环内的语句将被执行。

executed. Then the condition is re-tested, and if true, the body is executed again. When the test

        然后条件再进行测试,若为真,循环语句将再次执行。          当测试为假(fahr

becomes false (fahr exceeds upper) the loop ends, and execution continues at the statement

大于upper)时,循环结束,然后执行循环体之后的语句。

that follows the loop. There are no further statements in this program, so it terminates.

                  在这个程序中循环体之后没有其他语句了,所以它结束了。

The body of a while can be one or more statements enclosed in braces, as in the temperature

While的循环体可以有一句或更多的语句,像上面的温度转换,或一行没有大括号的语句,

converter, or a single statement without braces, as in

如下所示

   while (i < j)
       i = 2 * i;

In either case, we will always indent the statements controlled by the while by one tab stop

不论是何种情况,我们通常把while体中的语句缩进一个tab的距离(像例子里一样,四个

(which we have shown as four spaces) so you can see at a glance which statements are inside the

空格的距离),这样在循环体中的语句会更清晰。

loop. The indentation emphasizes the logical structure of the program.  Although C compilers do

     这样的缩进突出了程序的逻辑结构。                      虽然C编译器并不关心

not care about how a program looks, proper indentation and spacing are critical in making

一个程序的长相,但合适的缩进和空格决定了程序易读与赏心悦目。

programs easy for people to read. We recommend writing only one statement per line, and using

                            我们推荐每行只写一个语句,使用空格来更清晰地表示含有

blanks around operators to clarify grouping. The position of braces is less important, although

算术运算符的结构。                  大括号的位置不是很重要,虽然人们一直认为它很

people hold passionate beliefs. We have chosen one of several popular styles. Pick a style that

重要。(I don’t think so)      我们在流行的格式中选择了一种。        挑一种合适你的格

suits you, then use it consistently.

式,然后一直用下去。

Most of the work gets done in the body of the loop. The Celsius temperature is computed and

大多数工作是在循环内部完成的。            下面这条语句用于计算摄氏温度和给celsius assigned to the variable celsius by the statement

赋值

        celsius = 5 * (fahr-32) / 9;

The reason for multiplying by 5 and dividing by 9 instead of just multiplying by 5/9 is that in C, as

C语言语句中先乘5后除9而不是5/9的原因是,整数相除得出的结果会忽略小数(从

in many other languages, integer division truncates: any fractional part is discarded. Since 5 and

而得到的结果不正确,或不精确)。                                     59都是

9 are integers. 5/9 would be truncated to zero and so all the Celsius temperatures would be

整数。      所以5/9得出的结果是0,这样用上面的语句计算出的结果还是0(这是个错reported as zero.

误)。

This example also shows a bit more of how printf works. printf is a general-purpose output

这个例子还告诉你printf工作的更多内容。          Printf是一个一般的格式化输出函数,

formatting function, which we will describe in detail in Chapter 7. Its first argument is a string of

我们将在第七章详细讨论它的细节。                     它的第一个参数是一个即将打

characters to be printed, with each % indicating where one of the other (second, third, ...)

印的字符串,其中%字符将被之后的一个参数所代替,而%之后的一个字符将决定以何种格

arguments is to be substituted, and in what form it is to be printed. For instance, %d specifies an

式打印。                                               例如,%d指定了整形的打印

integer argument, so the statement

格式,所以语句

        printf("%d/t%d/n", fahr, celsius);

causes the values of the two integers fahr and celsius to be printed, with a tab (/t) between

打印出两个整形值,fahrcelsius,并且输出一个tab距离在两者之间。

them.

Each % construction in the first argument of printf is paired with the corresponding second

在函数printf第一个参数中的每一个%符号都有一个printf参数与之匹配,第二个,第三个

argument, third argument, etc.; they must match up properly by number and type, or you will get

等等;它们必须有相同的类型和相同数量,否则你只能得到错误的输出。

wrong answers.

By the way, printf is not part of the C language; there is no input or output defined in C itself.

顺便说下,printf并不是c语言的一部分;c语言本身并没有输入输出的定义。

printf is just a useful function from the standard library of functions that are normally

printf只是c语言标准库中的一个函数。

accessible to C programs. The behaviour of printf is defined in the ANSI standard, however, so

                     它的功能已在ANSI标准中定义,然而,对于任何与标准一致的编译

its properties should be the same with any compiler and library that conforms to the standard.

器和库,它的属性是相同的。

In order to concentrate on C itself, we don't talk much about input and output until chapter 7. In

为了把注意力放在C本身,我们不会讨论太多的输入输出,直到第七章。           特别

particular,  we will defer formatted input until then.  If you have to input numbers,  read the

的,我们将延迟到第七章再讨论格式化输入。     如果你需要输入数字,在第七章有关于

discussion of the function scanf in Section 7.4. scanf is like printf, except that it reads input

函数scanf的讨论。                      Scanfprintf类似,只是它读入输入的数据。

instead of writing output.

There are a couple of problems with the temperature conversion program. The simpler one is

这个温度转换程序还有一些问题。                               其中一个简单的问题

that the output isn't very pretty because the numbers are not right-justified. That's easy to fix; if

是,输出不怎么漂亮,因为数字没有右对齐。                      这可不难;如果我们

we augment each %d in the printf statement with a width, the numbers printed will be

增加每一个%d的打印宽度,打印的数字就会漂亮的右对齐。

right-justified in their fields. For instance, we might say

                       像这样写,我们会打印

   printf("%3d %6d/n", fahr, celsius);

to print the first number of each line in a field three digits wide, and the second in a field six

第一个数字3个数字宽,第二个6个数字宽,像这样:

digits wide, like this:

     0     -17
    20      -6
    40       4
    60      15
    80      26
   100      37
   ...

The more serious problem is that because we have used integer arithmetic, the Celsius

更严重点儿的问题是,因为我们在运算中用的是整型数据,所以摄氏温度不准确;例如,

temperatures are not very accurate; for instance, 0oF is actually about -17.8oC, not -17. To get

0oF准确的计算后应是-17.8oC而不是-17                                   为了得到

more accurate answers, we should use floating-point arithmetic instead of integer. This requires

更精确的数据,我们应该用浮点型的数据代替整型的来进行计算。         这需要改动一

some changes in the program. Here is the second version:

下原程序。               这是改动后的版本:

   #include <stdio.h>
 
   /* print Fahrenheit-Celsius table
       for fahr = 0, 20, ..., 300; floating-point version */
   main()
   {
     float fahr, celsius;
     float lower, upper, step;
 
     lower = 0;      /* lower limit of temperatuire scale */
     upper = 300;    /* upper limit */
     step = 20;      /* step size */
 
     fahr = lower;
     while (fahr <= upper) {
         celsius = (5.0/9.0) * (fahr-32.0);
         printf("%3.0f %6.1f/n", fahr, celsius);
         fahr = fahr + step;
     }
   }

This is much the same as before, except that fahr and celsius are declared to be float and

这与以前的没什么大区别,除了fahrcelsius被申明为浮点型的数据,而计算的方程式则

the formula for conversion is written in a more natural way. We were unable to use 5/9 in the

更自然。                                         我们不能在先前的版本中用5/9

previous version because integer division would truncate it to zero. A decimal point in a constant

因为整数除法,它会等于0                             常量中的小数点表明这家伙

indicates that it is floating point, however, so 5.0/9.0 is not truncated because it is the ratio of

是个浮点型,所以5.0/9.0不简写是因为这是两个浮点数据的比值。

two floating-point values.

If an arithmetic operator has integer operands, an integer operation is performed. If an

如果算术运算符的运算对象是整型,则整个运算以整型为头。            若一个算术运算

arithmetic operator has one floating-point operand and one integer operand, however, the

符有一个浮点型的和一个整型的运算对象,则整型的对象将在运算结束前转换成浮点型的。

integer will be converted to floating point before the operation is done. If we had written

                                                          如果代码是这样的(fahr-32), the 32 would be automatically converted to floating point. Nevertheless, writing

(fahr-32),则32自动转换成浮点型的。                         尽管如此,为了方便其

floating-point constants with explicit decimal points even when they have integral values

他人阅读代码,我们可以在浮点型常量后加上小数点,以突出它的类型:浮点型。

emphasizes their floating-point nature for human readers.

The detailed rules for when integers are converted to floating point are in Chapter 2. For now,

在第二章中将说明整型向浮点型转换的规则。                             现在,注意

notice that the assignment

这行语句

   fahr = lower;

and the test

和测试语句

   while (fahr <= upper)

also work in the natural way - the int is converted to float before the operation is done.

同样工作在自然模式下---在计算之前完成浮点地转换。

The printf conversion specification %3.0f says that a floating-point number (here fahr) is to

Printf中的格式说明符%3.0f表示一个浮点型数据(fahr)将被打印至少3个字符宽,没有小

be printed at least three characters wide, with no decimal point and no fraction digits. %6.1f

数部分的数据。                                                        %6.1f表示

describes another number (celsius) that is to be printed at least six characters wide, with 1

打印另一个数据(celsius),显示有6个字符宽,并且有一位小数。

digit after the decimal point. The output looks like this:

                        这是输出的数据:

     0   -17.8
    20    -6.7
    40     4.4
   ...

Width and precision may be omitted from a specification: %6f says that the number is to be at

%6f说明打印出的数据至少有6个字符宽,宽度和精度被省略了;%.2格式表示在小数点之

least six characters wide; %.2f specifies two characters after the decimal point, but the width is

后有两位小数,但是宽度没有被限定;而%f仅仅表示按照浮点的方式打印数据。

not constrained; and %f merely says to print the number as floating point.

 %d

 print as decimal integer

 %6d

 print as decimal integer, at least 6 characters wide

 %f

 print as floating point

 %6f

 print as floating point, at least 6 characters wide

 %.2f

 print as floating point, 2 characters after decimal point

 %6.2f  

 print as floating point, at least 6 wide and 2 after decimal point 

Among others, printf also recognizes %o for octal, %x for hexadecimal, %c for character, %s for 其他的格式还有%o表示八进制,%x表示十六进制,%c表示字符,%s表示字符串,%%

character string and %% for itself.

示打印%符号本身。

Exercise 1-3. Modify the temperature conversion program to print a heading above the table.

练习 1-3. 修改温度转换程序,在列表上面打印一行标题。

Exercise 1-4. Write a program to print the corresponding Celsius to Fahrenheit table.

练习 1-4.写一个打印摄氏温度转换为华氏温度的程序。