您好,欢迎来到意榕旅游网。
搜索
您的当前位置:首页C基础

C基础

来源:意榕旅游网
Chapter1—5

1、在C语言中,所有变量都必须先声明后使用。声明通常放在函数起始处,在任何可执行语句之前。

2、指出,printf函数并不是C语言本身的一部分,C语言本身并没有定义输入/输出功能。printf 仅仅是标准库函数中一个有用的函数而已。

3、

4、符号常量:#define 指令可以把符号名(或称为符号常量)定义为一个特定的字

符串

#define 名字 替换文本 //末尾没有分号,符号常量名通常用大写字母拼写

#define后的名字在预处理阶段被替换,但#define前的名字不会被替换

5、标准库提供了一次读/写一个字符的函数,其中最简单的是 getchar 和putchar 两个函数。每次调用时,getchar 函数从文本流中读入下一个输入字符,并将其作为结果值返回。

6、EOF 定义在头文件中,是个整型数。

7、不等于运算符!=的优先级比赋值运算符=的优先级要高

8、运算符&&代表 AND(逻辑与),它仅比||高一个优先级。由&&或||连接的表达式由左至右求值,并保证在求值过程中只要能够判断最终的结果为真或假,求值就立即终止。 9、在 C 语言中,所有函数参数都是“通过值”传递的。也就是说,传递给被调用函数的参数值存放在临时变量中,而不是存放在原来的变量中。

10、当把数组名用作参数时,传递给函数的值是数组起始元素的位置或地址——它并不复制数组元素本身。

11、在源文件中,如果外部变量的定义出现在使用它的函数之前,那么在那个函数中就没有必要使用 extern 声明。

12、如果程序包含在多个源文件中,而某个变量在 file1 文件中定义、在 file2 和 file3文件中使用,那么在文件 file2 与 file3 中就需要使用 extern 声明来建立该变量与其之间的联系。人们通常把变量和函数的 extern 声明放在一个单独的文件中(习惯上称头文件),并在每个源文件的开头使用#include 语句把所要用的头文件包含进来。

13、在ANSI C 中,如果要声明空参数表,则必须使用关键字 void 进行显式声明。

14、“定义”表示创建变量或分配存储单元,而“声明”指的是说明变量的性质,但并不分配存储单元。

15、有关数据类型长度定义的符号常量以及其它与机器和编译器有关的属性可以在

标准头文

16、件中找到。

17、常量表达式是仅仅只包含常量的表达式。这种表达式在编译时求值,而不在运行时求值。

18、字符常量'\\0'表示值为 0 的字符,也就是空字符(null)。

19、字符串常量就是字符数组,字符串的内部表示使用一个空字符'\\0'作为串的结尾,因此。存储字符串的物理存储单元数比括在双引号中的字符数多一个。

20、标准库函数strlen(s)可以返回字符串参数s 的长度,但长度不包括末尾的'\\0'。

21、标准头文件中声明了 strlen 和其它字符串函数。

22、枚举是一个常量整型值的列表,例如:enum boolean { NO, YES };在没有显式说明的情况下,enum 类型中第一个枚举名的值为 0,第二个为 1,依此类推。如果只指定了部分枚举名的值,那么未指定值的枚举名的值将依着最后一个指定值向后递增。

23、不同枚举中的名字必须互不相同。同一枚举中不同的名字可以具有相同的值。

24、默认情况下,外部变量与静态变量将被初始化为 0。未经显式初始化的自动变量的值为未定义值(即无效值)。

25、一般来说,自动转换是指把“比较窄的”操作数转换为“比较宽的”操作数,并

且不丢失信息的转换。

26、一个声明指定一种变量类型,后面所带的变量表可以包含一个或多个该类型的变量。

27、在声明的同时对变量进行初始化。在声明中,如果变量名的后面紧跟一个等号以及一个表达式,该表达式就充当对变量进行初始化的初始化表达式。如果变量不是自动变量,则只能进行一次初始化操作,从概念上讲,应该是在程序开始执行之前进行,并且初始化表达式必须为常量表达式。

28、标准头文件定义了一组与字符集无关的测试和转换函数。例如,tolower(c)函数将 c 转换为小写形式。语句c >= '0' && c <= '9'可以用该标准库中的函数isdigit(c)替代。

29、const 限定符也可配合数组参数使用,它表明函数不能修改数组元素的值:

int strlen(const char[]);

30、当把较长的整数转换为较短的整数或 char 类型时,超出的高位部分将被丢弃。

31、在对 unsigned 类型的无符号值进行右移位时,左边空出的部分将用 0 填补。当对 signed 类型的带符号值进行右移时,某些机器将对左边空出的部分用符号位填补(即“算术移位”),而另一些机器则对左边空出的部分用 0填补(即“逻辑移位”)。

32、当把 float 类型转换为 int 类型时,小数部分将被截取掉;当把 double 类型转换为 float 类型时,是进行四舍五入还是截取取决于具体的实现。

33、函数 getbits(x, p, n),它返回 x 中从右边数第 p 位开始向右数 n 位的字段。这里假定最右边的一位是第 0 位,n 与 p 都是合理的正值。

34、

35、continue 语句只用于循环语句,不用于 switch 语句。

36、internal 用于描述定义在函数内部的函数参数及变量。

34、外部变量或函数的作用域从声明它的地方开始,到其所在的(待编译的)文件的末尾结束。

35、如果要在外部变量的定义之前使用该变量,或者外部变量的定义与变量的使用不在同一个源文件中,则必须在相应的变量声明中强制性地使用关键字 extern。

36、将外部变量的声明与定义严格区分开来很重要。变量声明用于说明变量的属性(主要是变量的类型),而变量定义除此以外还将引起存储器的分配。

37、对于数组类型的外部变量,在定义时必须指定数组的长度,但 extern 声明则不一定要指定数组的长度。外部变量的初始化只能出现在其定义中。

38、用 static声明限定外部变量与函数,可以将其后声明的对象的作用域限定为被编译源文件的剩余部分。 39、static 也可用于声明内部变量。static 类型的内部变量同自动变量一样,是某个特定函数的局部变量,只能在该函数中使用,但它与自动变量不同的是,不管其所在函数是否被调用,它一直存在,而不像自动变量那样,随着所在函数的被调用和退出而存在和消失。

40、register 声明告诉编译器,它所声明的变量在程序中使用频率较高。其思想是,将register 变量放在机器的寄存器中,这样可以使程序更小、执行速度更快。

41、register 声明只适用于自动变量以及函数的形式参数. 42、过量的寄存器声明并没有什么害处,这是因为编译器可以忽略过量的或不支持的寄存器变量声明。无论寄存器变量实际上是不是存放在寄存器中,它的地址都是不能访问的。

43、变量的声明(包括初始化)除了可以紧跟在函数开始的花括号之后,还可以紧跟在任何其它标识复合语句开始的左花括号之后。以这种方式声明的变量可以隐藏程序块外

与之同名的变量,它们之间没有任何关系,并在与左花括号匹配的右花括号出现之前一直存在。

44、在不进行显式初始化的情况下,外部变量和静态变量都将被初始化为 0,而自动变量和寄存器变量的初值则没有定义(即初值为无用的信息)。

45、对于外部变量与静态变量来说,初始化表达式必须是常量表达式,且只初始化一次。 46、对于自动变量与寄存器变量来说,初始化表达式可以不是常量表达式:表达式中可以包

47、含任意在此表达式之前已经定义的值,包括函数调用。

48、数组的初始化可以在声明的后面紧跟一个初始化表达式列表,初始化表达式列表用花括

49、号括起来,各初始化表达式之间通过逗号分隔。如果初始化表达式的个数比数组元素数少,则对外部变量、静态变量和自动变量来说,没有初始化表达式的元素将被初始化为 0,如果初始化表达式的个数比数组元素数多,则是错误的。

50、字符数组的初始化比较特殊:可以用一个字符串来代替用花括号括起来并用逗号分隔的

51、初始化表达式序列。例如:char pattern[] = \"ould \";

52、从概念上讲,预处理器是编译过程中单独执行的第一个步骤。两个最常用的预处理器指令是:#include 指令(用于在编译期间把指定文件的内容包含进当前文件中)和#define 指令(用任意字符序列替代一个标记)

53、文件包含指令:#include \"文件名\" 或#include <文件名>

54、如果文件名用引号引起来,则在源文件所在位置查找该文件;如果在该位置没有找到文件,或者如果文件名是用尖括号<与>括起来的,则将根据相应的规则查找该文件,这个规则同具体的实现有关。被包含的文件本身也可包含#include 指令。

55、通常情况下,#define 指令占一行,替换文本是#define 指令行尾部的所有剩余部分内容,但也可以把一个较长的宏定义分成若干行,这时需要在待续的行末尾加上一个反斜杠符\\。#define 指令定义的名字的作用域从其定义点开始,到被编译的源文件的末尾处结束。

56、#define max(A, B) ((A) > (B) ? (A) : (B))

57、头文件中有一个很实用的例子:getchar 与putchar 函数在实际中常常被定义为宏,这样可以避免处理字符时调用函数所需的运行时开销。头文件中定义的函数也常常是通过宏实现的。

58、预处理器运算符##为宏扩展提供了一种连接实际参数的手段。如果替换文本中的参数与##相邻,则该参数将被实际参数替换,##与前后的空白符将被删除,并对替换后的结果重新扫描。下面定义的宏 paste 用于连接两个参数:#define paste(front, back) front ## back。因此,宏调用 paste(name, 1)的结果将建立记号 name1。

59、可以通过#undef 指令取消名字的宏定义,这样做可以保证后续的调用是函数调用,而不

60、是宏调用:#undef getchar

40、为了保证 hdr.h 文件的内容只被包含一次,可以将该文件的内容包含在下列形式

的条件语句中:

41、

42、

43、ANSI C 使用类型 void * (指 向 void的指针)代替 char *作为通用指针的

类型。

44、地址运算符&只能应用于内存中的对象,即变量与数组元素。它不能作用于表达式、常量或register 类型的变量。

45、指向 void 类型的指针可以存放指向任何类型的指针, 但它不能间接引用其自身。

46、一元运算符*和&的优先级比算术运算符的优先级高。

47、*p++和(*p)++的区别:类似于*和++这样的一元运算符遵循从右至左的结合顺序。 48、对数组元素 a[i]的引用也可以写成*(a+i)这种形式。对第一次接触这种写法的人来说,可能会觉得很奇怪。在计算数组元素 a[i]的值时,C 语言实际上先将其转换为*(a+i)的形式,然后再进行求值。

49、当把数组名传递给一个函数时,实际上传递的是该数组第一个元索的地址。在被调用函数中,该参数是一个局部变量,因此,数组名参数必须是一个指针,也就是一个存储地址值的变量。

50、类似于p[-1]、p[-2]这样的表达式在语法上都是合法的,它们分别引用位于 p[0]之前的两个元素。当然,引用数组边界之外的对象是非法的。

51、通常,对指针有意义的初始化值只能是 0 或者是表示地址的表达式。

52、程序中经常用符号常量 NULL 代替常量 0。符号常量 NULL 定义在标准头文中。C 语言保证,0 永远不是有效的数据地址,因此,返回值 0 可用来表示发生了异常事件。

53、任何指针与 0 进行相等或不等的比较运算都有意义。但是,指向不同数组的元素的指针之间的算术或比较运算没有定义。

54、指针的算术运算中可使用数组最后一个元素的下一个元素的地址。

55、在计算 p+n 时,n 将根据 p 指向的对象的长度按比例缩放,而 p 指向的对象的长度则取决于 p 的声明。

56、指针的减法运算也是有意义的:如果 p 和 q 指向相同数组中的元索,且 p57、如果指针 p 和 q 指向同一个数组的成员,那么它们之间就可以进行类似于==、!=、<、>=的关系比较运算。

58、有效的指针运算包括相同类型指针之间的赋值运算;指针同整数之间的加法或减法运算;指向相同数组中元素的两个指针间的减法或比较运算;将指针赋值为 0 或指针与 0 之间的比较运算。

59、Size_t 是由运算符 sizeof 返回的无符号整型

60、字符串常量最常见的用法也许是作为函数参数:princf(\"hello, world\\n\当类似于这样的一个字符串出现在程序中时,实际上是通过字符指针访问该字符串的。printf 接

受的是一个指向字符数组第一个字符的指针。

61、

amessage 是一个仅仅足以存放初始化字符串以及空字符'\\0'的一维数组。数组中的单个字符可以进行修改, 但 amessage 始终指向同一个存储位置。 另一方面, pmessage是一个指针,其初值指向一个字符串常量,之后它可以被修改以指向其它地址,但如果试图修改字符串的内容,结果是没有定义的。

58、进栈和出栈的标准用法

59、char *lineptr[MAXLINES];它表示 1ineptr 是一个具有 MAXLINES 个元素的一维数组,其中数组的每个元素是一个指向字符类型对象的指针。也就是说,lineptr[i]是一个字符指针,而*lineptr[i]是该指针指向的第 i 个文本行的首字符。

60、在 C 语言中,二维数组实际上是一种特殊的一维数组,它的每个元素也是一个一维数组。

61、数组元素按行存储,因此,当按存储顺序访问数组时,最右边的数组下标(即列)变化得最快。

62、数组可以用花括号括起来的初值表进行初始化,二维数组的每一行由相应的子列表进行初始化。如果将二维数组作为参数传递给函数,那么在函数的参数声明中必须指明

数组的列数。数组的行数没有太大关系。

63、二维数组初始化后,分配的是连续的固定大小的存储空间。指针数组指向的元素地址不连续,空间大小不一(可以指向单个元素,也可以指向数组)。

64、如果将二维数组 daytab 作为参数传递给函数 f,那么 f 的声明应该写成下列形式:

这种声明形式表明参数是一个指针,它指向具有 13 个整型元素的一维数组。因为方括号[]的优先级高于*的优先级,所以上述声明中必须使用圆括号。

65、int *daytab[13] 这相当于声明了一个数组,该数组有 13 个元素,其中每个元素都是一个指向整型对象的指针。

66、在支持 C 语言的环境中,可以在程序开始执行时将命令行参数传递给程序。调用主函数main 时,它带有两个参数。第一个参数(习惯上称为 argc,用于参数计数)的值表示运行程序时命令行中参数的数目;第二个参数(称为 argv,用于参数向量)是一个指向字符串数组的指针,其中每个字符串对应一个参数。

67、按照 C 语言的约定,argv[0]的值是启动该程序的程序名,因此 argc 的值至少为 1。

68、ANSI 标准要求argv[argc]的值必须为一空指针。

69、main(int argc, char *argv[]){xxx;}//argv 是一个指向指针数组的指针,也可以看成是指针数组的数组名。

70、argv的使用:P115

argv[i]或*(argv+i):第i个字符串的地址

*(argv[i]+j): 第i个字符串的第j个字符

*++argv[0]: 对指针 argv[0]进行了自增运算

[]与操作数的结合优先级比*和++高

71、在 C 语言中,函数本身不是变量,但可以定义指向函数的指针。这种类型的指针可以被赋值、存放在数组中、传递给函数以及作为函数的返回值等等。

72、*是一个前缀运算符,其优先级低于()。

73、int (*comp)(void *, void *),它表明 comp 是一个指向函数的指针,该函数具有两个 void *类型的参数,其返回值类型为int。(*comp)(a, b) 表示调用comp函数,其中a b是void *参数,comp表示函数地址,* comp表示函数本身。

74、int *f(); /* f: function returning pointer to int */

75、int (*pf)(); /* pf: pointer to function returning int */

76、ANSI 标准在结构方面最主要的变化是定义了结构的赋值操作——结构可以拷贝、赋值、

77、传递给函数,函数也可以返回结构类型的返回值。

78、结构的初始化可以在定义的后面使用初值表进行。初值表中同每个成员对应的初值必须是常量表达式。如:struct point maxpt = {320, 200};

79、结构类型的参数和其它类型的参数一样,都是通过值传递的。

80、(*pp).x 中的圆括号是必需的,因为结构成员运算符“.”的优先级比“*”的优先级高。

81、在所有运算符中,下面 4 个运算符的优先级最高:结构运算符“.”和“->” 、用于函数

82、调用的“()”以及用于下标的“[]”。

83、运算顺序:

++p->len、(++p)->len 、(p++)->len

*p->str:读取的是指针 str 所指向的对象的值

*p->str++:先读取指针str 指向的对象的值,然后再将 str 加 1(与*s++相同)

(*p->str)++:将指针str 指向的对象的值加 1

*p++->str 先读取指针 str 指向的对象的值,然后再将 p 加 1

84、C 语言提供了一个编译时(compile-time)一元运算符 sizeof,它可用来计算任一对象的长度。sizeof 对象或sizeof(类型名),将返回一个整型值,它等于指定对象或类型占用的存储空间字节数。 (严格地说,sizeof 的返回值是无符号整型值,其类型为 size_t,该类型在头文件中定义。 )其中,对象可以是变量、数组或结构;类型可以是基本类型,如 int、double,也可以是派生类型,如结构类型或指针类型。

85、isspace 函数跳过空白符,isalpha 函数识别字母,isalnum 函数识别字母和数字。所有这些函数都定义在标准头文件中。

86、千万不要认为结构的长度等于各成员长度的和。因为不同的对象有不同的对齐要求,所以,结构中可能会出现未命名的“空穴“ (hole)。

87、在 C 语言中,一种合适的方法是将 malloc 的返回值声明为一个指向 void 类型的指针,然后再显式地将该指针强制转换为所需类型。malloc 及相关函数声明在标准头文件中。

88、C 语言提供了一个称为 typedef 的功能,它用来建立新的数据类型名。typedef char* String;将 String 定义为与 char *或字符指针同义,此后,便可以在类型声明和类型转换中使用String。

89、typedef 声明并没有创建一个新类型,它只是为某个已存在的类型增加了一个新的名称而已。

90、typedef int (*PFI)(char *, char *);该语句定义了类型 PFI 是“一个指向函数的指针,该函数具有两个 char *类型的参数,返回值类型为 int” 。

91、对于各种不同大小的整型值来说,都使用通过 typedef 定义的类型名,然后,分别为各个不同的宿主机选择一组合适的 short、int 和 long 类型大小即可。标准库中有一些例子,例如

92、size_t 和 ptrdiff_t 等。

93、联合是可以(在不同时刻)保存不同类型和长度的对象的变量,编译器负责跟踪对象的长度和对齐要求——一个变量可以合法地保存多种数据类型中任何一种类型的对象。

94、

变量 u 必须足够大,以保存这 3 种类型中最大的一种,具体长度同具体的实现有关。这

些类型中的任何一种类型的对象都可赋值给 u,且可使用在随后的表达式中,但必须保证是一

致的:读取的类型必须是最近一次存入的类型。程序员负责跟踪当前保存在联合中的类型。如果保存的类型与读取的类型不一致,其结果取决于具体的实现。

95、可以通过下列语法访问联合中的成员:联合名.成员 或 联合指针->成员

96、实际上,联合就是一个结构,它的所有成员相对于基地址的偏移量都为 0,此结构空间要

97、大到足够容纳最“宽”的成员,并且,其对齐方式要适合于联合中所有类型的成员。对联合允许的操作与对结构允许的操作相同:作为一个整体单元进行赋值、复制、取地址及访问其中一个成员。

98、联合只能用其第一个成员类型的值进行初始化。

99、

这里定义了一个变量 flags,它包含 3 个一位的字段。冒号后的数字表示字段的宽度(用二进制位数表示)。字段被声明为 unsigned int 类型,以保证它们是无符号量。

100、最简单的输入机制是使用 getchar 函数从标准输入中(一般为键盘) 一次读取一个字符。

101、putchar(c)将字符 c 送至标准输出上,在默认情况下,标准输出为屏幕显示。如果没有发生错误,则函数 putchar 将返同输出的字符;如果发生了错误,则返回 EOF。

102、int printf(char *format, arg1, arg2, ...);函数 printf 在输出格式 format 的控制下,将其参数进行转换与格式化,并在标准输出设备上打印出来。它的返回值为打印的字符数。

103、int sprintf(char *string, char *format, arg1, arg2, ...);sprintf 函数和 printf 函数一样,按照 format 格式格式化参数序列 arg1、arg2、…,但它将输出结果存放到 string 中,而不是输出到标准输出中。

104、具有变长参数表的函数 scanf 的声明形式如下:int scanf(char *format, ...)。scanf 函数从标准输入中读取字符序列,按照 format 中的格式说明对字符序列进行解释,并把结果保存到其余的参数中。其它所有参数都必须是指针,用于指定经格式转换后的相应输入保存的位置。

105、当 scanf 函数扫描完其格式串,或者碰到某些输入无法与格式控制说明匹配的情况时,该函数将终止,同时,成功匹配并赋值的输入项的个数将作为函数值返回,所以,该函数的返回值可以用来确定已匹配的输入项的个数。如果到达文件的结尾,该函数将返回 EOF。注意,返回 EOF 与 0 是不同的,0 表示下一个输入字符与格式串中的第一个格式说明不匹配。下一次调用 scanf 函数将从上一次转换的最后一个字符的下一个字符开始继续搜索。

106、scanf 函数忽略格式串中的空格和制表符。此外,在读取输入值时,它将跳过空白符(空

107、格、制表符、换行符等等) 。如果要读取格式不固定的输入,最好每次读入一行,然后再用

108、sscanf 将合适的格式分离出来读入。

109、fopen 函数返回一个指向结构 FILE 的指针。注意,FILE 像 int 一样是一个类型名,而不是结构标记。它是通过 typedef 定义的。

110、FILE *fopen(char *name, char *mode);fopen 的第一个参数是一个字符串,它包含文件名。第二个参数是访问模式,也是一个字符串,用于指定文件的使用方式。允许的模式包括:读( “r” ) 、写( “w” )及追加( “a” ) 。某些系统还区分文本文件和二进制文件,对后者的访问需要在模式字符串中增加字符“b” 。如果发生错误,fopen 将返回 NULL。

111、int getc(FILE *fp)getc 函数返回 fp 指向的输入流中的下一个字符。如果到达文件尾或出现错误,该函数将返回 EOF。

112、int putc(int c, FILE *fp)该函数将字符 c 写入到 fp 指向的文件中,并返回写入的字符。如果发生错误,则返回 EOF。

113、启动一个 C 语言程序时,操作系统环境负责打开 3 个文件,并将这 3 个文件的指针提供给该程序。 这 3 个文件分别是标准输入、标准输出和标准错误, 相应的文件指针分别为stdin、stdout 和 stderr,它们在中声明。在大多数环境中,stdin 指向键盘,而stdout 和 stderr 指向显示器。stdin 和 stdout 可以被重定向到文件或管道。

114、

115、对于文件的格式化输入或输出,可以使用函数 fscanf 和 fprintf。它们与 scanf 和printf 函数的区别仅仅在于它们的第一个参数是一个指向所要读写的文件的指针, 第二个参

116、数是格式串。如下所示:

int fscanf(FILE *fp, char *format, ...)

int fprintf(FILE *fp, char *format, ...)

117、文件指针 stdin 与 stdout 都是 FILE *类型的对象。但它们是常量,而非变量。因此不能对它们赋值。

118、int fclose(FILE *fp),执行和 fopen 相反的操作,它断开由 fopen 函数建立的文件指针和外部名之间的连接,并释放文件指针以供其它文件使用。

119、标准库函数 exit,当该函数被调用时,它将终止调用程序的执行。任何调用该程序的进程都可以获取 exit 的参数值,因此,可通过另一个将该程序作为子进程的程序来测试该程序的执行是否成功。按照惯例,返回值 0 表示一切正常,而非 0 返回值通常表示出现了异常情况。exit 为每个已打开的输出文件调用 fclose 函数,以将缓冲区中的所有输出写到相应的文件中。

120、如果流 fp 中出现错误,则函数 ferror 返回一个非 0 值。int ferror(FILE *fp)。尽管输出错误很少出现,但还是存在的(例如,当磁盘满时) ,因此,成熟的产品程序应该检查这种类型的错误。

121、char *fgets(char *line, int maxline, FILE *fp),fgets 函数从 fp 指向的文件中读取下一个输入行(包括换行符) ,并将它存放在字符数组line 中,它最多可读取 maxline-1 个字符。读取的行将以'\\0'结尾保存到数组中。通常情况下,fgets 返回 line,但如果遇到了文件结尾或发生了错误,则返回 NULL。

122、int fputs(char *line, FILE *fp)。输出函数 fputs 将一个字符串(不需要包含换行符)写入到一个文件中。如果发生错误,该函数将返回 EOF,否则返回一个非负值。

123、库函数gets和puts的功能与fgets和fputs函数类似, 但它们是对stdin和stdout

124、进行操作。有一点我们需要注意,gets 函数在读取字符串时将删除结尾的换行符('\\n') ,

125、而 puts 函数在写入字符串时将在结尾添加一个换行符。

输入/输出函数:

<1>int getchar(void)

getchar 函数在每次被调用时,从标准输入读取下一个输入字符并返回。若遇到文件结尾,则返回 EOF。

<2>int putchar(int)

putchar(c)将字符 c 送至标准输出上,在默认情况下,标准输出为屏幕显示。如果没

有发生错误,则函数 putchar 将返同输出的字符;如果发生了错误,则返回 EOF。

<3>int printf(char *format, arg1, arg2, ...)

函数 printf 在输出格式 format 的控制下,将其参数进行转换与格式化,并在标准输出设备上打印出来。它的返回值为打印的字符数。(P149) <4>int sprintf(char *string, char *format, arg1, arg2, ...)

sprintf 函数和 printf 函数一样,按照 format 格式格式化参数序列 arg1、arg2、…,但它将输出结果存放到 string 中,而不是输出到标准输出中。当然,string 必须足够大以存放输出结果。

<5>int scanf(char *format, ...)

scanf 函数从标准输入中读取字符序列,按照 format 中的格式说明对字符序列进行解释,并把结果保存到其余的参数中。当 scanf 函数扫描完其格式串,或者碰到某些输入无法与格式控制说明匹配的情况时,该函数将终止,同时,成功匹配并赋值的输入项的个数将作为函数值返回,所以,该函数的返回值可以用来确定已匹配的输入项的个数。如果到达文件的结尾,该函数将返回 EOF。

<6>int sscanf(char *string, char *format, arg1, arg2, ...)

它按照格式参数 format 中规定的格式扫描字符串 string,并把结果分别保存到 arg1、arg2、…这些参数中。这些参数必须是指针。

<7>FILE *fopen(char *name, char *mode);

fopen 函数返回一个指向结构 FILE 的指针。该指针称为文件指针,它指向一个包含文件信息的结构,这些信息包括:缓冲区的位置、缓冲区中当前字符的位置、文件的读或写状态、是否出错或是否已经到达文件结尾等等。FILE 像 int 一样是一个类型名,而不是结构标记。它是通过 typedef 定义的。中已经定义了一个包含这些信息的结构 FILE。fopen 的第一个参数是一个字符串,它包含文件名。第二个参数是访问模式,也是一个字符串,用于指定文件的使用方式。允许的模式包括:读( “r” ) 、写( “w” )及追加( “a” ) 。某些系统还区分文本文件和二进制文件,对后者的访问需要在模式字符串中增加字符“b”。如果打开一个不存在的文件用于写或追加,该文件将被创建(如果可能的话) 。当以写方式打开一个已存在的文件时,该文件原来的内容将被覆盖。但是,如果以追加方式打开一个文件,则该文件原来的内容将保留不变。读一个不存在的文件会导致错误,其它一些操作也可能导致错误,比如试图读取一个无读取权限的文件。如果发生错误,fopen 将返回 NULL。

<8>int getc(FILE *fp)

getc 函数返回 fp 指向的输入流中的下一个字符。如果到达文件尾或出现错误,该函数将返

回 EOF。

<9>int putc(int c, FILE *fp)

putc函数将字符 c 写入到 fp 指向的文件中,并返回写入的字符。如果发生错误,

则返回 EOF。类似于 getchar 和 putchar,getc 和 putc 是宏而不是函数。

启动一个 C 语言程序时,操作系统环境负责打开 3 个文件,并将这 3 个文件的指针提供

给该程序。这 3 个文件分别是标准输入、 标准输出和标准错误, 相应的文件指针分别为 stdin、stdout 和 stderr,它们在中声明。在大多数环境中,stdin 指向键盘,而stdout 和 stderr 指向显示器。stdin 和 stdout 可以被重定向到文件或管道。文件指针 stdin 与 stdout 都是 FILE *类型的对象。但它们是常量,而非变量。因此不能对它们赋值。

getchar 和 putchar 函数可以通过 getc、putc、stdin 及 stdout 定义如下:

#define getchar() getc(stdin)

#define putchar(c) putc((c), stdout)

<10>int fscanf(FILE *fp, char *format, ...)

<11>int fprintf(FILE *fp, char *format, ...)

对于文件的格式化输入或输出,可以使用函数 fscanf 和 fprintf。它们与 scanf 和printf 函数的区别仅仅在于它们的第一个参数是一个指向所要读写的文件的指针, 第二个参数是格式串。

<12>int fclose(FILE *fp)

fclose执行和 fopen 相反的操作,它断开由 fopen 函数建立的文件指针和外部名之间的连接,并释放文件指针以供其它文件使用。大多数操作系统都限制了一个程序可以同时打开的文件数,所以,当文件指针不再需要时就应该释放。对输出文件执行 fclose 还有另外一个原因:它将把缓冲区中由 putc函数正在收集的输出写到文件中。

<13>void exit(int status)

stdlib.h中定义。标准库函数 exit,当该函数被调用时,它将终止调用程序的执行。任何调用该程序的进程都可以获取 exit 的参数值,因此,可通过另一个将该程序作为子进程的程序来测试该程序的执行是否成功。按照惯例,返回值 0 表示一切正常,而非 0 返回值通常表示出现了异常情况。exit 为每个已打开的输出文件调用 fclose 函数,以将缓冲区中的所有输出写到相应的文件中。在主程序 main 中,语句 return expr 等价于 exit(expr)。

<14>int ferror(FILE *fp)

如果流 fp 中出现错误,则函数 ferror 返回一个非 0 值。

int feof(FILE *fp)

函数 feof(FILE *)与 ferror 类似。如果指定的文件到达文件结尾,它将返回一个非0 值。

<15>char *fgets(char *line, int maxline, FILE *fp)

fgets 函数从 fp 指向的文件中读取下一个输入行(包括换行符) ,并将它存放在字

符数组line 中,它最多可读取 maxline-1 个字符。读取的行将以'\\0'结尾保存到数组中。通常情况下,fgets 返回 line,但如果遇到了文件结尾或发生了错误,则返回 NULL。

<16>int fputs(char *line, FILE *fp)

输出函数 fputs 将一个字符串(不需要包含换行符)写入到一个文件中,如果发生错误,该函数将返回 EOF,否则返回一个非负值。

<17>库函数gets和puts的功能与fgets和fputs函数类似, 但它们是对stdin和stdout进行操作。gets 函数在读取字符串时将删除结尾的换行符('\\n') ,而 puts 函数在写入字符串时将在结尾添加一个换行符。

<18>int ungetc(int c, FILE *fp)

该函数将字符 c 写回到文件 fp 中。如果执行成功,则返回 c,否则返回 EOF。每个文件只能

接收一个写回字符。

字符串操作函数:

中的函数:

头文件中定义了一些用于字符测试和转换的函数:

命令执行函数

函数 system(char* s)执行包含在字符申 s 中的命令,然后继续执行当前程序。s 的内容在很大程度上与所用的操作系统有关。Unix中的system(“date”),将执行程序 date,它在标准输出上打印当天的日期和时间。system 函数返回一个整型的状态值,其值来自于执行的命令,并同具体系统有关。在 UNIX 系统中,返回的状态是 exit 的返回值。

存储管理函数

void *malloc(size_t n)

当分配成功时,它返回一个指针,设指针指向 n 字节长度的未初始化的存储空间,否则返回NULL。

void *calloc(size_t n, size_t size)

当分配成功时,它返回一个指针,该指针指向的空闲空间足以容纳由 n 个指定长度的对象组

成的数组,否则返回 NULL。该存储空间被初始化为 0。

如:int * ip = (int *) calloc(n, sizeof(int));

free(p)函数释放 p 指向的存储空间,其中,p 是此前通过调用 malloc 或 calloc 函数得到的指针。 存储空间的释放顺序没有什么限制, 但是, 如果释放一个不是通过调用 malloc或 calloc 函数得到的指针所指向的存储空间,将是一个很严重的错误。

数学函数:(中定义)

随机数发生器函数:

函数 rand()生成介于 0 和 RAND_MAX 之间的伪随机整数序列。其中 RAND_MAX 是在头文件中定义的符号常量。下面是一种生成大于等于 0 但小于 1 的随机浮点数的方法:

#define frand() ((double) rand() / (RAND_MAX+1.0))

函数 srand(unsigned)设置 rand 函数的种子数。

Unix系统接口:

1、当命令解释程序(即“shell” )运行一个程序的时候,它将打开 3 个文件,对应的文件描述符分别为 0,1,2,依次表示标准输入,标准输出和标准错误。

2、程序的使用者可通过<和>重定向程序的 I/O:prog < 输入文件名 > 输出文件名,这种情况下,shell 把文件描述符 0 和 1 的默认赋值改变为指定的文件。通常,文件描述符 2仍与显示器相关联,这样,出错信息会输出到显示器上。

3、输入与输出是通过read和write系统调用实现的。 在 C语言程序中, 可以通过函数read和 write 访问这两个系统调用。这两个函数中,第一个参数是文件描述符,第二个参数是程序中存放读或写的数据的字符数组,第三个参数是要传输的字节数。

int n_read = read(int fd, char *buf, int n);

int n_written = write(int fd, char *buf, int n);

每个调用返回实际传输的字节数。在读文件时,函数的返回值可能会小于请求的字节数。如果返回值为 0,则表示已到达文件的结尾;如果返回值为-1,则表示发生了某种错误。在写文件时,返回值是实际写入的字节数。如果返回值与请求写入的字节数不相等,则说明发生了错误。

4、int open(char *name, int flags, int perms);

与 fopen 一样,参数 name 是一个包含文件名的字符串。第二个参数 flags 是一个 int 类型的值,它说明以何种方式打开文件,主要的几个值如下所示:

5、int creat(char *name, int perms);

如果 creat 成功地创建了文件,它将返回一个文件描述符,否则返回-1。如果此文件已存在,

creat 将把该文件的长度截断为 0,从而丢弃原先已有的内容。使用 creat 创建一个已存在

的文件不会导致错误。如果要创建的文件不存在,则 creat 用参数 perms 指定的权限创建文件。在 UNIX 文件系统中,每个文件对应一个 9 比特的权限信息,它们分别控制文件的所有者、所有者组和其他成员对文件的读、写和执行访问。因此,通过一个 3 位的八进制数就可方便地说明不同的权限,例如,0755 说明文件的所有者可以对它进行读、写和执行操作,而所有者组和其他成员只能进行读和执行操作。

6、函数 close(int fd)用来断开文件描述符和已打开文件之间的连接,并释放此文件描述符,以供其它文件使用。close 函数与标准库中的fclose 函数相对应,但它不需要清洗(flush)缓冲区。如果程序通过 exit 函数退出或从主程序中返回,所有打开的文件将被关闭。

7、函数 unlink(char *name)将文件 name 从文件系统中删除,它对应于标准库函数remove。

8、long lseek(int fd, long offset, int origin);

系统调用 lseek 可以在文件中任意移动位置而不实际读写任何数据。将文件描述符为 fd 的文件的当前位置设置为 offset,其中,offset 是相对于 orgin 指定的位置而言的。随后进行的读写操作将从此位置开始,origin 的值可以为 0、1 或 2,分别用于指定 offset 从文件开始、从当前位置或从文件结束处开始算起。lseek 系统调用返回一个 long 类型的值,此值表示文件的新位置,若发生错误,则返回-1。

为了向一个文件的尾部添加内容(在 UNIX shell 程序中使用重定向符>>或在系统调用 fopen 中使用参数“a” ) ,则在写操作之前必须使用下列系统调用找到文件的末尾:lseek(fd, 0L, 2); 若要返回文件的开始处(即反绕) ,则可以使用下列调用:lseek(fd, 0L, 0);

标准库函数 fseek 与系统调用 lseek 类似,所不同的是,前者的第一个参数是 FILE *类型,

且在发生错误时返回一个非 0 值。

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- yrrf.cn 版权所有

违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务