C Primer Plus(第五版)2

时间:2023-03-09 18:04:20
C Primer Plus(第五版)2

在本章中你将学习下列内容
------------------------------------------------------------------
1.运算符:=

2.函数:main(),printf()

3.编写一个简单的 C 程序。

4.创建整形变量,为其赋值,并在屏幕上显示该值。

5.换行字符。

6.如何在程序中加入注释,建立包含多个函数的程序,以及找出程序中的错误。

7.理解什么是关键字

2.1 C 语言的一个简单的实例

让我们来看一个简单的 C程序。从程序清单2.1中的程序可以看出编写 C程序的一些基本特征。请在看该程序的逐行注解之前通读程序清单2.1,看自己能否明白该程序所做的事情。

程序清单2.1 first.c 程序
-------------------------------------------------------------------
#include <stdio.h>
int main(void) /* 一个简单的 C程序*/
{
int num; /* 定义一个名为 num 的变量 */
num = 1; /* 为 num 赋一个值 */

printf ("I am a simple"); /* 使用 printf()函数 */
printf ("computer.\n");
printf ("My favorite number id %d because it is first.\n", num);
returm 0;
}
其显示结果为:

I am a simple computer.
My favorite number id 1 because it is first.

总的来说,这个结果并不使人惊讶,但是程序中的那结 "/n" 和"%d"起什么作用呢?并且程序中的某些语句看起来的确有些奇怪.下面将对此给出解释.

2.2 实例说明

典型的 C 程序

--- #include --- 预处理器指令

--- int main (void)--- main()总是第一个被调用的函数
|
|----------- statements --- 函数由语句组成

--- function a()
|
|----------- statements ---

--- function b()
|
|----------- statements ---
函数是 C 的构造块
----------------------------------------------

重点: C 语言中的 5类语句
1. declaration 声明
2. assignment分配
3. function函数
4. control控制
5. null空

重要就是这几样 1.关键字 2.标识符 3.运算符 4.数据

2.2.1 第一遍 快速简介

本小节依次在程序的每一行后面都给出一个简单的描述。下一小节则更全面地探讨这里所引起的话题。

-----------------------------------------------
#include <stdio.h> ---包含另一个文件

该行告诉编译器包含文件 stdio.h 中的全部信息。文件 stdio.h 是所有 C语言编译包的一个标准部分。这个文件对关键字输入和显示输出提供支持。

---------------------------------------------------
int main (void) --- 函数名

int表示返回整形变量 void 表示无参

/* 一个简单的 C程序 */ ---注释

符号/*和*/中包含有助于使程序更清晰的注释性内容。它们只是为了帮助读者理解,在编译时将会被编译器忽略。

-----------------------------------------------------------
{ --- 函数体的开始

这个开始花括号标志着组成函数的语句的开始。而结束花括号 (})则标志函数的结束。

------------------------------------------------------------
int num; ---声明语句

这个语句表明你将使用 num 这个变量,并且它是 int(整数)类型的。

-------------------------------------------------------------
num = 1; ---赋值语句

该语句表明把值 1 赋给 num 这个变量。

--------------------------------------------------------------
printf ("I am a simple"); --- 一个函数调用语句

第一个 printf()语句在屏幕上显示“I am a simple”,并且让光标留在同一行。这里的 printf()是 C 标准库的一部分。用术语来讲,它是一个函数。在一个程序里使用一个函数,术语称做调用一个函数。

---------------------------------------------------------------
printf("computer.\n") --- 又一个函数调用语句

接下来这个 printf()函数调用语句表示在上条语句所显示的内容后面添加“computer”。
符号 \n 告诉计算机要另起一行,也就是说把光标移到下一行的开始。

------------------------------------------------------
printf ("My favorite number id %d because it is first.\n", num);

最后使用 printf()把 num 的值(其值为1)内嵌在用引号引起来的词组中进行输出。
%d 指示输出 num 值的位置和形式。

----------------------------------------------------------
return 0; --- 返回语句

C 函数可以给它的使用者提供或返回一个数值。现在可以暂时认为这一行用来满足 ISO/ANSI C 对正确书写 main()函数所做的要求。

----------------------------------------------------------
} --- 结束

显然,程序必须以一个结束花括号终止。

----------------------------------------------------------

一. #include 指示和头文件

#include <stdio.h>

这是程序的第一行。该语句的作用相当于你在文件中该行所在的位置键入了文件 stdio.h 的完整内容。实际上,它是一种剪切和粘贴操作,这样可以方便地在多个程序间共享公用的信息。

#include 语句是 C预处理指令 (preprocessor directive)的一个例子。通常,C 编译器在编译前要对源代码做一些准备工作;这称为预处理(preprocessing)

stdio.h 文件作为所有 C编译包的一部分提供,它包含了有关输出输入函数 (例如printf())的信息以供编译器使用。这个名字代表标准输入输出头文件(standard input/output header)。在 C 世界中,人们称出现在文件顶部的信息集合为头(header),C实现通常都带有许多头文件。

最重要的是头文件包括了建立最终的可执行程序时编译器需要用到的信息。例如,它们可以定义常量,或者说明函数名以及该函数如何使用。但是函数的实际代码被包含在一个预编译代码的库文件中,而不是在头文件中。编译器的链接部分负责找到你所需要的库代码。简言之,头文件指引编译器把你的程序正确地组合在一起。

二. main()函数

int main(void)

接下来的这行代码声明了一个 main函数。的确,main是一个极其普通的名字,但它是唯一的选择。一个 C程序(我们将不考虑一些例外的情况)总是从称为 main()的函数开始执行的。

如果浏览老版本的 C代码,你将发现程序常常以:
main()

这种形式开始。C90标准勉强允许这种形式,但是 C99标准不允许。因此即使你当前的编译器允许,也不要这么做。

你还将看到另一种形式
void main()

三.注释

/* 一个简单的 C程序 */

包含在/* */之间的部分是程序注释。

/* 这是有效的 C注释 */

/* 将注释分成两行写,
也是可以的。 */

/*
也可以这样写
*/

/* 但这是无效的注释,因为没有结束的标记。

// 这种注释必须被限制在一行内。

int rigue; //这种注释也可以写在此处。

五. 声明
int num;

程序中的这一行叫做声明语句 (declaration statement)。

传统上,C语言要求必须在一个代码块的开始处声明变量,在这之前不允许任何其他语句。也就是说,main()函数将如下所示:

int main() //traditional rules (传统的用法)
{
int doors;
int dogs;
doors = 5;
dogs =3;
// other statements (其他的语句)
}

现在 C99遵循 C++的惯例,允许把声明放在代码块中的任何位置。然而,在首次使用变量之前仍然必须先声明它。

为了为旧系统更好的兼容,本书将遵守初始的约定

现在你可能有三个问题。首先,数据类型是什么?第二,可以选择什么样的名字?第三,为什么必须对变量进行声明? 下面来看这些问题的答案。

2.名字的选择

你应该尽量使用有意义的变量名

能够使用的字符的数量与 C语言的不同实现有关。C99标准允许一个标识符最多可以有 个字符,除了外部标识符(见第12章“存储类,链接和内存管理”),后者只识别31个字符。与C90分别要求的31个字符和6个字符相比较,这是一个相当可观的进步,而更旧的编译器通常最多只允许8个字符。实际上,你使用的字符数量可以超过规定的最大值,但是编译器不会识别额外的字符。因此,如果一个系统最大字符数为8,那么 Shakespeare 和 shakespeare 将被看作是一个名字,因为它们的前8个字符相同。

可供使用的字符有小写字母,大写字母,数字和下划线。第一个字符必须是字母或者下划线。

操作系统和 C库通常使用以一个或两个下划线开始的名字(例如_kcab),因此你自己最好避免这种用法。

六. 赋值

num = 1; // = (赋值运算符)

这行程序是一个赋值语句(assignment statement)。赋值语句是 C语言的基本操作之一。这个特殊的例子的意思是“把值1赋给变量 num”。前面的 int num;语句在计算机内存中为变量 num 分配了空间,该赋值语句在那个地方为变量存储了一个值。如果你想的话,以后你还可以给 num 赋另一个值;这就是把 num 称为变量的原因。注意赋值语句赋值的顺序是从右到左。同样,该语句也用分号结束。

七. printf()函数

printf ("computer.\n");
printf ("My favorite number is %d because it is first.\n", num);

那么下一个 printf()行呢?引号中有字符\n,但并没有输出它们!发生了什么事情呢? \n字符的意思是开始新的一行。 \n 组合(依次键入这两个字符)代表一个称为换行符(newline character)的字符,它意味着“在下一行的最左边开始新的一行”。换句话说,打印换行字符的效果和在普通键盘上按下回键一样。当键入 printf()这个参数时,为什么不直接按回车键呢?因为那将看作是直接针对编辑器的命令,而不是作为存在源代码中的指令。也就是说,当你按回车键时,编辑器退出你正在输入的当前行,并开始新的一行。而换行符则影响程序的输出如何显示。

换行符是转义字符(Escape Sequence)的一个例子。转义字符通常用于代表难于表达的或是无法键入的字符。其他的例子比如 \t 代表 Tab键, \b 代表退格键盘。每个转义字符都用斜线字符(\)开始。在第3章“数据和C”中我们将回来讨论这个问题。

%告诉程序把一个变量在这个位置输出,d告诉程序将输出一个十进制(以10为基数)整数变量。printf()函数允许多种输出变量格式,包括十六进制(以16为基数)整数和带小数点的数。实际上,printf()中的 f 暗示着这是一种格式化(format)的输出函数。每一种数据都有自己的说明符,本书在介绍新的数据类型时,也会介绍与之相应的说明符。

八. Return 语句

return 0;

return 语句(返回语句)是程序的最后一个语句。在 int main(void)中 int 表示 main()函数的返回值应该是一个整数。C标准要求 main()这样做。带有返回值的 C语言函数要使用一个 return 语句,该语句包括关键字 return,后面紧跟着要返回的值,然后是一个分号。对于 main()函数来说,如果你漏掉了 return语句,则大多数编译器将对你的疏忽提出警告,但仍将编译该程序。此时,你可以暂时把 main()中的 return语句看作是保持逻辑连贯性所需的内容。但对于某些操作系统(包括 DOS 和 UNIX )而言,它有实际的用途。第11章将具体讨论这个话题。

2.3 一个简单程序的结构

你已经看过一个具体的例子,下面可以了解一些 C程序的基本规则了。程序(program)由一个或多个函数组成,其中必须一个名为 main()的函数。函数的描述由头和函数体组成。函数头(heaber)包括预处理语句(如 #include)和函数名。可以通过圆括号识别一个函数名,圆括号里面可能是空的。而函数体(body)位于花括号({})中并由一系列语句组成,每个语句以一个分号结束 (参见图2.4)

图2..4 一个包含函数头和函数体的函数
----------------------------------------------------
函数头
#include <stdio.h> ---预处理指令

int main(void) ---带有参数的函数名

函数体
{
int q; ---声明语句
q = 1; ---赋值语句
printf("%d is neat..\n",q); ---函数语句
return 0; ---默认返回值
}
--------------------------------------------------

2.6 多个函数

到目前为止,这些程序只使用了标准的 printf()函数。程序清单 2.3说明除了 main()函数之外,怎样把你自己的函数加入到程序中。

程序清单 2.3 tow_fuc.c程序
------------------------------------------------------------------
/* two_func.c -- 在一个文件中使用两个函数 */
#include <stdio.h>
void butler (void); // ISO/ANSI C 函数原型
int main (void)
{
printf ("I will summon the butler function.\n");
butler ();
printf (" Yes.Bring me some tea and writeable CD-ROMS.\n");
getchar();
return 0;
}

void butler (void) // 函数定义的开始
{
printf("You rang,sir?\n");
}

输出应该像下面这样:

I will summon the butler function.
You rang,sir?
yes,bring me some tea writeable CD-ROMS.

butler()函数在程序中出现了 3次。第一次出现在原型中,通知编译器要用到的该函数。第二次是在
main()函数中以函数调用的形式出现的。最后,程序给出了函数的定义,即函数本身的源代码。让我们依次看一下它在程序中的每一次出现。

C90标准添加了原型,以前的编译器可能并不认识它们(稍后我们将告诉你使用这种编译器时应该怎样做)。原型是一种声明的形式,用于告诉编译器你正在用一个特殊的函数。它也指明了函数的属性。
例如 butler()函数原型的第一个 void 说明 butler 不返回值(通常,一个函数可以给调用它的函数返回一个值以供使用,但是 butler 函数不返回值)。第二个 void 也就是 butler(void)中的 void, 意思是 butler()函数没有参数。因此,当编译器到达 main()函数中的 butler()调用处时会检查 butler()的使用是否正确。注意 void 的意思是“空的”,而不是“无效的”。

早期的 C支持一种形式更为有限的函数声明,其中你仅指定函数的返回类型而省略对参数的描述。

void butler();

检查程序状态的第三种方法是使用调试器。调试器是一种程序,让你能够一步一步运行另一个程序并检查该程序的变量值。不同的调试器具有不同的易用性和复杂度。较高级的调试器可以显示出正在执行的源代码行。这对于有多条可选执行路径的程序来说是非常方便的,因为可以很容易地知道执行了哪条特殊路径。如果你的编译器带有调试器,那么现在请花点时间去学会怎么用它。例如,试着去调试一下程序清单 2.4

2.8 关键字和保留标识符

关键字是 C语言中的词汇。因为它们对 C来说比较特殊,所以你不能将它们用作标识符,例如作为变量名。许多关键字用于指定不同的类型,比如 int。其他的关键字,比如 if,用来控制程序中语句的执行顺序。

如果试图把一个关键字用作变量名,编译器把它作为一个语法错误捕获到。还有一些你不该用的其他字符,称为保留标识符(reserved identifier)。因为它们是合法的名字,所以并不引起语法错误。保留标识符包括那些以下划线字符开始的标识符和标准库函数的名字, 例如 printf()。

2.11 复习题

-------------------------------------------------------------
1.如何称呼 C程序的基本模块?

答:它们被称为函数。

-------------------------------------------------------------------
4. Indiana Sloth 已经编好了下面的程序,并想征求你的意见,请帮助他评定
include studio.h
int main{void} /* 该程序可显示出一年中有多少周 /* */

int s

s: = 56;
print(There are s weeks in a year.);
return 0;

答:第一行:以一个 #开始,拼写出文件名 stdio.h 然后把文件名放在一对尖括号中。
#icnlude <stdio.h>

第二行: void应该使用() 注释符号结束应该是使用 */
int main (void) /* 该程序可显示出一年中有多少周 */

第三行: 应该使用花括号 { 而不是使用圆括号 ( 来用为函数体的开头
{

第四行: 语句结束要使用分号来表示 ;
int s;

第五行: 这行空白是正确的

第六行: 赋值变量应用使用 = 而不是 := 。 Pascal的赋值才是:=。另一年有52周。
s = 52;

第七行: 除了使用的函数正确 其他基本错误。
printf (" There are %d weeks in a year.\n", s);

第九行: 少了一个用来结束的 } 花括号。

-------------------------------------------------------------------------------------

5. 假设下面的每一个例子都是某个完整程序的一部分,它们每个将输出什么结果?
a. printf("baa baa black sheep.");
printf("Have you any wool?\n");
b printf("Begone!\n0 creature of lard!");
c printf("What? \nNo/nbonzo?\n");
d int num;

num = 2;
printf("%d + %d =%d", num, num,num+num);

答:a: baa baa black sheep.Have you any wool? (光标闪在下一行开头)

b: begone!
0 creature of lard! (光标仍在第二行结束处)

c: What?
No/nbonxo? (/ 没有“\”所具有的作用,只是简单的被打印出来)

d 2 + 2 = 4 (注意每个 %d 是如何被列表中对应的变量值所替换的。也要注意 + 的意思就是 加法,可以在 printf()语句里进行计算)

------------------------------------------------------------------------------------------
6. 下面哪几个是 C 的关键字? main, int,function,char,=

答: int,char 是关键字
main,function 是函数名 (属于 C语言中的一个技术术语)
= 是赋值运算符号

-----------------------------------------------------------------------------------------
7. 如何以下面的格式输出 words 和 lines 的值:“There were 3020 words and 350 lines”?
这里,3020 和 350 代表两个变量的值。

答:printf ("There were %d words and %d lines.\n", words,lines);

--------------------------------------------------------------------------------------

8. 考虑下面的程序:

#include <stdio.h>
int main (void)
{
int a,b;

a = 5;
b = 2; //第7行
b = a; //第8行
a = b; //第9行
printf("%d %d\n",b,a);
return 0;
}

请问在第7行,第8行和第9行之后程序的状态分别是什么?

答: 第7行 a = 5; b = 2;
第8行 b = 5; a = 5;
第9行 a = 5; b = 5;

-----------------------------------------------------------------------------------------

2.12 编程练习
------------------------------------------------------------------------------------------
1. 编写一个程序,调用 printf()函数在一行上输出你的名和姓,再调用一次printf()函数在两个单独的行上输出你的名和姓,然后调用一对 printf()函数在一行输出你的名和姓。

答:
#include <stdio.h>
int main (void)
{
printf ("黄尚\n");
printf ("黄 \n 尚\n");
printf ("黄");
printf ("尚");
getchar();
return 0;
}
-----------------------------------------------------------------------------------------

2. 编写一个程序输出你的姓名及地址

答:
#include <stdio.h>
int main (viod)
{
printf ("黄尚 \n");
printf ("广西兴业县石南镇环江城里村38号");
getchar();
return 0;
}

------------------------------------------------------------------------------------------
4. 编写一个程序,把你的年龄转换成天数并显示二者的值,按一年 365 天来计算。

答:
#include <stdio.h>
int main (viod)
{
int age,day;

age = 30;
day = 365 * age;
printf ("我的年龄是 %d ,一共是 %d 天。\n",age,day);
getchar();
return 0;
}

------------------------------------------------------------------------------------------
5. 编写一个能够产生下面输出的程序:
for he's a jolly good fellow!
for he's a jolly good fellow!
for he's a jolly good fellow!
Which nobody can deny!

程序中除了 main()函数之外,要使用两个用户定义的函数:一个用于把上面夸奖消息输出一次;
另一个用于把最后一行输出一次。

答:
#include <stdio.h>
void good (void);
void nobody (void);

void good (void)
{
printf ("for he's a jolly good fellow!\n");
}

void nobody (void)
{
printf ("Which nobody can deny!");
}

int main (void)
{
printf ("for he's a jolly good fellow!\nfor he's a jolly good fellow!\n");
good();
nobody();
getchar();
return 0;
}

-----------------------------------------------------------------------------------------
5. 编写一个程序,创建一个名为 toes 的整数变量。让程序把 toes 设置为 10.再让程序计算两个 toes的和以及toes的平方。程序应该输出所有的3个值, 并分别标识它们。

答:
#include <stdio.h>
int main (void)
{
int toes;

toes = 10;
printf (" toes= %d, toes square= %d, toes cube=%d \n",toes,toes*toes,toes*toes*toes);
getchar();
return ;
}

-----------------------------------------------------------------------------------------
6. 编写一个能够产生下列输出的程序:

Smile!Smile!Smile!
Smile!Smile!
Smile!

在程序中定义一个能显示字符串 smile!一次的函数,并在需要时使用该函数。

答:
#include <stdio.h>
void smile (void);

void smile (void)
{
printf ("Smlie!");
}

int main (void)
{
printf("Smile!Smile!Smile!\nSmile!Smile!\n");
smile();
getchar();
return 0;
}

----------------------------------------------------------------------------------------
7 .编写一个程序,程序中要调用名为 one_three()的函数。该函数要在一行中显示单词“one”,再调用 tow()函数,然后再在另一行显示单词 “three”。 函数two()应该能在一行中显示单词“two”。 main()函数应该在调用 one_three()函数之前显示短语“starting now”,函数调用之后要显示“done!”。这样,最后的输出结果应如下所示:

starting now;
one
two
three
done!

答:
#include <stdio.h>
void one_three (void);
void two (void);

void one_three (void)
{
printf ("one\n");
}

void two (void)
{
printf ("two\n");
}

int main (void)
{
printf ("starting now\n");
one_three();
two();
printf("three\ndone!");
getchar();
return 0;
}

---------------------------------------------------------------------------------------