目录
C语言入门
程序段和代码段
(1)text段:存放程序代码。
(2)data段:存放有初值的全局变量和常量。
(3)bss段:存放未被初始化的全局变量。
C语言入门实例
让我们看一段简单的代码,可以输出单词"Hello World"。
#include <stdio.h> int main() { /*我的第一个C程序*/ printf("Hello,World!\n"); return 0; } |
程序的第一行#include <stdio.h>是预处理器指令,告诉C编译器在实际编译之前要包含stdio.h文件。
下一行int main()是主函数,程序从这里开始执行,C语言程序都是从main函数开始执行。
下一行/*…*/将会被编译器忽略,这里放置程序的注释内容。它们被称为程序的注释。下一行printf(…)是C中另一个可用的函数,会在屏幕上显示消息"Hello,World!"。
下一行return 0;终止main()函数,并返回值0。
英文分号(;)
在C程序中,分号是语句结束符。也就是说,每个语句必须以分号结束。它表明一个逻辑实体的结束。
注释
C语言有两种注释方式:
(1)以//开始的单行注释,这种注释可以单独占一行。
(2)/**/这种格式的注释可以单行或多行。
不能在注释内嵌套注释,注释也不能出现在字符串或字符值中。
标识符
C标识符是用来标识变量、函数,或任何其他用户自定义项目的名称。一个标识符以字母A~Z或a~z或下划线(_)开始,不能以数字开始,后跟零个或多个字母、下划线和数字(0~9)。C标识符内不允许出现标点字符,比如@、$和%。C是区分大小写的编程语言。
保留字
C语言自己保留的关键字,编写程序时不能与之重复,如变量定义int/char/double等保留字。
C中的空格
只包含空格的行,被称为空白行,可能带有注释,C编译器会完全忽略它。在C中,空格用于描述空白符、制表符、换行符和注释。空格分隔语句的各个部分,让编译器能识别语句中的某个元素(比如int)在哪里结束,下一个元素在哪里开始。因此,在下面的语句中:
int age;
int 和age之间必须至少有一个空格字符(通常是一个空白符),这样编译器才能够区分它们。
另一方面,在下面的语句中:
fruit = apples+oranges;//获取水果的总数
fruit和=或者=和apples之间的空格字符不是必需的,但是为了增强可读性,可以根据需要适当增加一些空格。
C数据类型
基本类型
在不同字长编译器中,各类型长度见表
数据类型长度
字长 | 类型 | |||||||
char | char* | short | int | long | long long | float | double | |
16位 | 8 | 16 | 16 | 16 | 32 | 64 | 32 | 64 |
32位 | 8 | 32 | 16 | 32 | 32 | 64 | 32 | 64 |
64位 | 8 | 64 | 16 | 32 | 64 | 64 | 32 | 64 |
sizeof获取存储字节
为了得到某个类型或某个变量在特定平台上的准确大小,可以使用sizeof运算符。表达式sizeof(type)得到对象或类型的存储字节大小。
void类型
void类型指定没有可用的值。它通常用于以下三种情况。
(1)函数返回为空。C中有各种函数都不返回值,或者您可以说它们返回空。不返回值的函数的返回类型为空。例如void exit(int status);
(2)函数参数为空。C中有各种函数不接受任何参数。不带参数的函数可以接受一个void。例如int rand(void):
(3)指针指向void。类型为void*的指针代表对象的地址,而不是类型。例如,内存分配函数void*malloc(size_tsize);返回指向void的指针,可以转换为任何数据类型。
变量
变量其实只不过是程序可操作的存储区的名称。C中每个变量都有特定的类型,类型决定了变量存储的大小和布局,该范围内的值都可以存储在内存中,运算符可应用于变量上。
变量的名称可以由字母、数字和下划线字符组成。它必须以字母或下划线开头。大写字母和小写字母是不同的,因为C是大小写敏感的。
变量定义:指定一个数据类型,并包含了该类型的一个或多个变量的列表,如下所示:
type variable list
在这里,type必须是一个有效的C数据类型,可以是char、w_char、int、float、double或任何用户自定义的对象,variable_list可以由一个或多个标识符名称组成,多个标识符之间用逗号分隔。下面列出几个有效的声明:
int i,j,k;
变量可以在声明的时候被初始化(指定一个初始值)。初始化器由一个等号,后跟一个常量表达式组成,如下所示:
type variable_name =value;
下面列举几个实例:
int d = 3,f = 5; //定义并初始化整型变量d和f char x = ‘x’; //字符型变量x的值为 'x' |
C数组
定义一维数组,语法如下:
type arrayName [arraySize];
C枚举
枚举语法定义格式为:
enum枚举名{枚举元素1,枚举元素2,…};
枚举元素1默认为0,可以赋其他值;
枚举元素的值默认在前一个元素基础上加1;
定义枚举变量:
C中的左值(lvalue)和右值(rvalue)
C中有两种类型的表达式:
(1)左值(lvalue):指向内存位置的表达式被称为左值表达式。左值可以出现在赋值号的左边或右边。
(2)右值(rvalue):术语右值(rvalue)指的是存储在内存中某些地址的数值。右值是不能对其进行赋值的表达式,也就是说,右值可以出现在赋值号的右边,但不能出现在赋值号的左边。
变量是左值,因此可以出现在赋值号的左边。数值型的字面值是右值,因此不能被赋值,不能出现在赋值号的左边。
下面这个不是一个有效的语句,会生成编译时错误:
10=20;
C常量
整数常量可以是十进制、八进制或十六进制的常量。前缀指定基数:0x或0X表示十六进制,0表示八进制,不带前缀则默认表示十进制。
浮点常量由整数部分、小数点、小数部分和指数部分组成。可以使用小数形式或者指数形式来表示浮点常量,如:
字符常量是括在单引号中,可以是一个普通的字符(例如'x')、一个转义序列(例如^t),或一个通用的字符(例如'u02C0')。在C中,有一些特定的字符,当它们前面有反斜杠时,它们就具有特殊的含义,被用来表示如换行符(\n)或制表符(\t)等。
字符串字面值或常量是括在双引号("")中的。一个字符串包含类似于字符常量的字符:普通的字符、转义序列和通用的字符。
变量存储类型
变量存储类型是指数据在内存中存储的方法,即确定所定义的变量在内存中的存储位置,也确定了变量的作用域和生存期,内部变量存储类型有三种,分别是:自动内部变量、寄存器内部变量、静态内部变量。
自动(auto)存储型变量又称自动变量,它是最常用的一种变量的存储类型,在函数内部或复合语句内部定义的局部变量(或称为内部变量)。只要存储类型是缺省的,均为自动变量。它的特点是其生命期域定义它的函数或复合语句的执行期同长,且有效范围仅在定义它的函数或复合语句内。
寄存器(register)存储型变量一般存储在计算机CPU的通用寄存器中,因而定义的这种类型变量存取速度快,适合于频繁使用的变量,可加快程序的运行速度,由于CPU中通用寄存器的数目有限,且每次可供C语言使用的通用寄存器数更有限,因而在程序中不宜大量使用这种存储类型的变量,以二三个为宜,当然超过可用的寄存器数,也不会出错,编译程序会将超过可用寄存器数的寄存器型变量当作auto变量处理。一般将最频繁使用的变量定义成寄存器型变量。
静态(static)存储型变量是分配在存储器中C程序占据的数据段内,对运行的C程序而言,这是一个程序所用的固定内存区域,因而静态变量的存储地址在整个程序的运行执行期间均保留,不会被别的变量占据。静态变量可以定义成全局变量或局部变量,当定义成全局变量时,它在定义它的整个程序执行期间均存在,其原来的存储位置不会变化。当定义成局部变量时,虽然在定义它的函数内或复合语句中有效,但在执行完该函数或复合语句后,静态变量最后取得的值仍然保存,不会消失,因为它所占的存储地址不会被别的变量占用,这样,当程序再次调用该函数或执行该复合语句时,该静态变量当前值就是再次进入该函数或执行该复合语句的初始值。
假设有一个内部整型变量aa,按不同存储类型的变量声明如下:
(1)自动内部变量:int aa;或auto int aa;
(2)寄存器内部变量:register int aa;或register aa;
(3)静态内部变量:static int aa;
C常用关键字(保留字)
宏定义#define
用来定义一个可以代替值的宏,语法格式如下:
#define 宏名称 值
实例:
#define LENGTH 10 /后续使用可用LENGTH代替10这个常量
const关键字
定义一个只读的变量,本质是修改了变量的存储方式为只读。
const int LENGTH=10;//定义变量LENGTH=10,且只读,即无法修改LENGTH值
static关键字
static关键字指示编译器在程序的生命周期内保持局部变量的存在,而不需要在每次它进入和离开作用域时进行创建和销毁。因此,使用static修饰局部变量可以在函数调用之间保持局部变量的值。
static修饰符也可以应用于全局变量或函数。当static修饰全局变量或函数时,会使变量或函数的作用域限制在声明它的文件内。
extern关键字
extern关键字用于提供一个全局变量的引用,全局变量对所有的程序文件都是可见的。
可以这么理解,extern是用来在另一个文件中声明一个全局变量或函数。extern修饰符通常用于当有两个或多个文件共享相同的全局变量或函数的时候。
typedef关键字
C语言提供了typedef关键字,您可以使用它来为类型取一个新的名字。下面的实例为单字节数字定义了一个术语BYTE:
typedef unsigned char BYTE;
在这个类型定义之后,标识符BYTE可作为类型unsigned char的缩写,例如:
BYTE b1,b2;
也可以使用typedef来为用户自定义的数据类型取一个新的名字。
条件编译
C语言中提供控制编译器流程的语句为条件编译语句,在一般情况下,C源程序中所有的行都参加编译过程,但有时出于对程序代码优化的考虑,希望对其中一部分内容只是在满足一定条件时才进行编译,形成目标代码,这种对一部分内容指定编译的条件称为条件编译。
下面是关于#ifdef语句的使用规则:
或者
该语句的作用是,如果#ifdef后面的“宏名”在此前已用#define语句定义,则编译“程序段1”或“程序段”;否则编译“程序段2”。如果没有#else部分,则当“宏名”未定义时直接跳过#endif。
下面是关于#ifndef语句的使用规则:
或者
#ifndef语句的功能与#ifdef语句的功能正好相反,如果#ifndef后面的“宏名”未定义,则编译“程序段1”或“程序段”;否则编译“程序段2”。如果没有#else部分,则当“宏名”已定义时直接跳过#endif。
C运算符
算术运算符
表显示了C语言支持的所有算术运算符。假设变量A的值为10,变量B的值为20,则运算结果见表。
算术运算符应用实例
运算符 | 描述 | 实例 |
+ | 把两个操作数相加 | A+B将得到30 |
- | 从第一个操作数中减去第二个操作数 | A-B将得到-10 |
* | 把两个操作数相乘 | A*B将得到200 |
/ | 分子除以分母 | B/A将得到2 |
% | 取模运算符,整除后的余数 | B%A将得到0 |
++ | 自增运算符,整数值增加1 | A++将得到11 |
-- | 自减运算符,整数值减少1 | A--将得到9 |
关系运算符
表显示了C语言支持的所有关系运算符。假设变量A的值为10,变量B的值为20,则运算结果见表
关系运算符应用实例
运算符 | 描述 | 实例 |
== | 检查两个操作数的值是否相等,如果相等则条件为真 | (A==B)不为真 |
!= | 检查两个操作数的值是否相等,如果不相等则条件为真 | (A!=B)为真 |
> | 检查左操作数的值是否大于右操作数的值,如果是则条件为真 | (A>B)不为真 |
< | 检查左操作数的值是否小于右操作数的值,如果是则条件为真 | (A<B)为真 |
>= | 检查左操作数的值是否大于或等于右操作数的值,如果是则条件为真 | (A>=B)不为真 |
<= | 检查左操作数的值是否小于或等于右操作数的值,如果是则条件为真 | (A<=B)为真 |
逻辑运算符
表显示了C语言支持的所有逻辑运算符。假设变量A的值为1,变量B的值为0,则运算结果见表
逻辑运算符应用实例
运算符 | 描述 | 实例 |
&& | 称为逻辑与运算符。如果两个操作数都非零,则条件为真 | (A&&B)为假 |
Ⅱ | 称为逻辑或运算符。如果两个操作数中有任意一个非零,则条件为真 | (A||B)为真 |
! | 称为逻辑非运算符。用来逆转操作数的逻辑状态。如果条件为真则逻辑非运算符将使其为假 | !(A&&B)为真 |
位运算符
位运算符作用于位,并逐位执行操作。&、|和^的真值表见表
&、|和^的真值有
p | q | p&q | p|q | p^g |
0 | 0 | 0 | 0 | 0 |
0 | 1 | 0 | 1 | 1 |
1 | 1 | 1 | 1 | 0 |
1 | 0 | 0 | 1 | 1 |
假设如果A=60,且B=13,现在以二进制格式表示为如下所示:
A=00111100
B=00001101
A&B=00001100
A|B=00111101
A^B=00110001
~A=11000011
下表显示了C语言支持的位运算符。假设变量A的值为60,变量B的值为13,则:
位运算符应用实例
运算符 | 描述 | 实例 |
& | 按位与操作,按二进制位进行“与”运算。运算规则: 0&0=0; 0&1=0; 1&0=0; 1&1=1; | (A&B)将得到12,即为00001100 |
| | 按位或运算符,按二进制位进行“或”运算。运算规则: 0|0=0; 0|1=1; 1|0=1; 1|1=1; | (A|B)将得到61,即为00111101 |
^ | 异或运算符,按二进制位进行“异或”运算。运算规则: 0^0=0; 0^1=1: 1^0=1; 1^1=0; | (A^B)将得到49,即为00110001 |
~ | 取反运算符,按二进制位进行“取反”运算。运算规则: ~1=0; ~0=1; | (~A)将得到-61,即为11000011,一个有符号二进制数的补码形式 |
<< | 二进制左移运算符。将一个运算对象的各二进制位全部左移若干位(左边的二进制位丢弃,右边补0) | A<<2将得到240,即为11110000 |
>> | 二进制右移运算符。将一个数的各二进制位全部右移若干位,正数左补0,负数左补1,右边丢弃 | A>>2将得到15,即为00001111 |
赋值运算符
下表列出了C语言支持的赋值运算符。
赋值运算符
运算符 | 描述 | 实例 |
= | 简单的赋值运算符,把右边操作数的值赋给左边操作数 | C=A+B将把A+B的值赋给C |
+= | 加且赋值运算符,把右边操作数加上左边操作数的结果赋值给左边操作数 | C+=A相当于C=C+A |
-= | 减且赋值运算符,把左边操作数减去右边操作数的结果赋值给左边操作数 | C-=A相当于C=C-A |
*= | 乘且赋值运算符,把右边操作数乘以左边操作数的结果赋值给左边操作数 | C*=A相当于C=C*A |
/= | 除且赋值运算符,把左边操作数除以右边操作数的结果赋值给左边操作数 | C/=A相当于C=C/A |
%= | 求模且赋值运算符,求两个操作数的模赋值给左边操作数 | C%=A相当于C=C%A |
<<= | 左移且赋值运算符 | C<<=2等同于C=C<<2 |
>>= | 右移且赋值运算符 | C>>=2等同于C=C>>2 |
&= | 按位与且赋值运算符 | C&=2等同于C=C&2 |
^= | 按位异或且赋值运算符 | C^=2等同于C=C^2 |
|= | 按位或且赋值运算符 | C|=2等同于C=C|2 |
下表列出了C语言支持的其他一些重要的运算符,包括sizeof和?:。
C语言支持的其他重要运算符
运算符 | 描述 | 实例 |
sizeof() | 返回变量的大小 | sizeof(a)将返回4,其中a是整数 |
& | 返回变量的地址 | &a;将给出变量的实际地址 |
* | 指向一个变量 | *a;将指向一个变量 |
?: | 条件表达式 | 如果条件为真?则值为X:否则值为Y |
C中的运算符优先级
优先级最高者其实并不是真正意义上的运算符,包括:数组下标、函数调用操作符、各结构成员选择操作符。它们都是自左向右结合。
单目运算符的优先级仅次于上述运算符,在所有的真正意义的运算符中,它们的优先级最高。
双目运算符的优先级低于单目运算符的优先级。在双目运算符中,算术运算符的优先级最高,移位运算符次之,关系运算符再次之,接着就是逻辑运算符,赋值运算符,最后是条件运算符。总结以下两点:
(1)任何一个逻辑运算符的优先级低于任何一个关系运算符。
(2)移位运算符的优先级比算术运算符要低,但是比关系运算符要高。
C语言运算符优先级见下表
C语言运算符优先级
运算符 | 结合性 |
() [] -->. | 自左向右 |
! ~ ++ -- -(type) * & sizeof | 自右向左 |
*/% | 自左向右 |
+- | 自左向右 |
<< >> | 白左向右 |
< <= > >= | 自左向右 |
== != | 自左向右 |
& | 自左向右 |
^ | 自左向右 |
| | 自左向右 |
&& | 自左向右 |
|| | 自左向右 |
?: | 自右向左 |
Assignments | 自右向左 |
, | 自左向右 |
C语法结构
C判断
判断结构要求程序员指定一个或多个要评估或测试的条件,以及条件为真时要执行的语句(必需的)和条件为假时要执行的语句(可选的)。
C语言把任何非零和非空的值假定为true,把零或null假定为false。
判断语句格式:
(1)if语句。
(2)ifelse语句(扩展if elseif else)。
(3)switch case语句。
#include <stdio.h> int main() { int choice;
printf("请选择一个数字(1-3):"); scanf("%d", &choice);
switch(choice) { case 1: printf("您选择了数字1\n"); break; case 2: printf("您选择了数字2\n"); break; case 3: printf("您选择了数字3\n"); break; default: printf("无效的选择\n"); }
return 0; } |
C循环
循环语句允许我们多次执行一个语句或语句组,C语言提供了以下几种循环类型:
(1)while语句。
(2)for语句。
(3)do while语句(至少保证执行一次循环体)。
循环控制语句
(1)break语句。C语言中break语句有以下两种用法:
1)当break语句出现在一个循环内时,循环会立即终止,且程序流将继续执行紧接着循环的下一条语句。
它可用于终止switch语句中的一个case。
2)如果使用的是嵌套循环(即一个循环内嵌套另一个循环),break语句会停止执行最内层的循环,然后开始执行该块之后的下一行代码。
(2)continue语句。C语言中的continue语句会跳过当前循环中的代码,强迫开始下一次循环。
对于for循环,continue语句执行后自增语句仍然会执行。对于while和do…while循环,continue语句重新执行条件判断语句。
(3)goto语句(不建议使用)。C语言中的goto语句允许把控制无条件转移到同一函数内的被标记的语句。
C函数和作用域
C函数
C语言中的函数定义的一般形式如下:
在C语言中,函数由一个函数头和一个函数主体组成。下面列出一个函数的所有组成部分。
(1)返回类型:一个函数可以返回一个值。return_type是函数返回值的数据类型。有些函数执行所需的操作而不返回值,在这种情况下,return_type是关键字void。
(2)函数名称:这是函数的实际名称。函数名和参数列表一起构成了函数签名。
(3)参数:参数就像是占位符。当函数被调用时,您向参数传递一个值,这个值被称为实际参数。参数列表包括函数参数的类型、顺序、数量。参数是可选的,也就是说,函数可能不包含参数。
(4)函数主体:函数主体包含一组定义函数执行任务的语句。
以下是max()函数的源代码。该函数有两个参数num1和num2,会返回这两个数中较大的那个数。
函数声明会告诉编译器函数名称及如何调用函数。函数的实际主体可以单独定义。
函数声明语法格式如下:
return_type function_name(parameter list);
针对上面定义的函数max(),以下是函数声明:
int max(int num1,int num2);
在函数声明中,参数的名称并不重要,只有参数的类型是必需的,因此下面也是有效的声明:
int max(int,int);
调用函数时,传递所需参数,如果函数返回一个值,则可以存储返回值。例如:
ret =max(a,b);
C作用域
局部变量:在某个函数或块的内部声明的变量称为局部变量。它们只能被该函数或该代码块内部的语句使用。局部变量在函数外部是不可知的。
全局变量:定义在函数外部,通常是在程序的顶部。全局变量在整个程序生命周期内都是有效的,在任意的函数内部能访问全局变量。全局变量可以被任何函数访问。也就是说,全局变量在声明后整个程序中都是可用的。
在程序中,局部变量和全局变量的名称可以相同,但是在函数内,如果两个名字相同,会使用局部变量值,全局变量不会被使用。
形式参数:函数的参数,被当作该函数内的局部变量,如果与全局变量同名它们会优先使用。
C指针
C指针
每一个变量都有一个内存位置,每一个内存位置都定义了可使用连字号(&)运算符访问的地址,它表示在内存中的一个地址。
指针是一个变量,其值为另一个变量的地址,即内存位置的直接地址。就像其他变量或常量一样,必须在使用指针存储其他变量地址之前,对其进行声明。指针变量声明的一般形式为:
type *var-name;
在这里,type是指针的基类型,它必须是一个有效的C数据类型,var-name是指针变量的名称。用来声明指针的星号(*)与乘法中使用的星号是相同的。但是,在这个语句中,星号是用来指定一个变量是指针。以下是有效的指针声明:
int *ip;/*一个整型的指针*/
使用指针时会频繁进行以下几个操作:①定义一个指针变量;②把变量地址赋值给指针;③访问指针变量中可用地址的值。这些是通过使用一元运算符“*”来返回位于操作数所指定地址的变量的值。
函数指针
函数指针是指向函数的指针变量。通常我们说的指针变量是指向一个整型、字符型或数组等变量,而函数指针是指向函数。函数指针可以像一般函数一样,用于调用函数、传递参数。
函数指针变量的声明:
typedef int (*fun_ptr)(int,int);/声明一个指向同样参数、返回值的函数指针类型
传值与传址
传值调用:将实参的值传递给形参,形参的改变不会导致调用点所传的实参的值改变。实参可以是合法的变量、常量和表达式。
传址调用:即引用调用,将实参的地址传递给形参,即相当于实参存储单元的地址引用,因此其值改变的同时就改变了实参的值。实参不能为常量,只能是合法的变量和表达式。
因此,在编程时,要改变参数值就传址,不改变就传值。
内存管理
定义一个指针必须使其指向某个存在的内存空间的地址才能使用,否则使用野指针会造成段错误,内存分配与释放函数如下:
结构体和联合体
C结构体
C数组允许定义可存储相同类型数据项的变量,结构是C编程中另一种用户自定义的可用的数据类型,它允许存储不同类型的数据项。
为了定义结构,必须使用struct语句。struct语句定义了一个包含多个成员的新的数据类型,struct语句的格式如下:
tag是结构体标签。
member-list是标准的变量定义,比如int i;或者float f,或者其他有效的变量定义。
variable-list结构变量,定义在结构的末尾,最后一个分号之前,可以指定一个或多个结构变量。
在一般情况下,tag、member-list、variable-list这三个部分至少要出现两个。以下为实例:
为了访问结构的成员,使用成员访问运算符英文句号(.)。
C联合体(共用体)
共用体是一种特殊的数据类型,允许在相同的内存位置存储不同的数据类型。可以定义一个带有多成员的共用体,但是任何时候只能有一个成员带有值。共用体提供了一种使用相同的内存位置的有效方式。
为了定义共用体,您必须使用union语句,方式与定义结构类似。union语句定义了一个新的数据类型,带有多个成员。union语句的格式如下:
union tag是可选的,每个member definition是标准的变量定义,比如int i;或者float f;或者其他有效的变量定义。在共用体定义的末尾,最后一个分号之前,可以指定一个或多个共用体变量,这是可选的。下面定义一个名为Data的共用体类型,有三个成员i、f和str:
共用体占用的内存应足够存储共用体中最大的成员。
为了访问联合体的成员,使用成员访问运算符英文句号(.)。
C文件操作
打开文件方式
可以使用fopen()函数来创建一个新的文件或者打开一个已有的文件,这个调用会初始化类型FILE的一个对象,类型FILE包含了所有用来控制流的必要的信息。下面是这个函数调用的原型:
其中,filename是字符串,用来命名文件,访问模式mode的值可以是下列值中的一个:r代表read,+代表可读可写,w代表write,b代表bit二进制文件,t代表text,a代表追加。默认处理的是text文件,如果处理的是二进制文件,则需使用下面的访问模式来取代上面的访问模式(加字母b):"rb”,"wb","ab”,“rb+”,“r+b”,"wb+”,"w+b”,"ab+","a+b"。访问模式见表
访问模式
模式 | 描述 |
r | 打开一个已有的文本文件,允许读取文件 |
W | 打开一个文本文件,允许写入文件。如果文件不存在,则会创建一个新文件。在这里,您的程序会从文件的开头写入内容。如果文件存在,则该会被截断为零长度,重新写入 |
a | 打开一个文本文件,以追加模式写入文件。如果文件不存在,则会创建一个新文件。在这里,您的程序会在已有的文件内容中追加内容 |
r+ | 打开一个文本文件,允许读写文件 |
w+ | 打开一个文本文件,允许读写文件。如果文件已存在,则文件会被截断为零长度,如果文件不存在,则会创建一个新文件 |
a+ | 打开一个文本文件,允许读写文件。如果文件不存在,则会创建一个新文件。读取会从文件的开头开始,写入则只能是追加模式 |
关闭文件
使用fclose()函数关闭文件,函数的原型如下:
int fclose(FILE *fp);
如果成功关闭文件,fclose()函数返回零,如果关闭文件时发生错误,函数返回EOF。
文件的读写操作
fgetc:从文件中读取一个字符。
fputc:写一个字符到文件中去。
fgets:从文件中读取一个字符串。
fputs:写一个字符串到文件中去。
fread:以二进制形式读取文件中的数据。
fwrite:以二进制形式写数据到文件中去。
文件定位函数
fseek:函数设置文件指针stream的位置。
文件检错函数
Feof()函数用于检测文件当前读写位置是否处于文件尾部。只有当当前位置不在文件尾部时,才能从文件读数据。
函数定义:int feof(FILE*fp)
返回值:0或非0
feof()是检测流上的文件结束符的函数,如果文件结束,则返回非0值,没结束则返回0。
文件结束函数
文件操作的每个函数在执行中都有可能出错,C语言提供了相应的标准函数ferror用于检测文件操作是否出现错误。
函数定义:int ferror(FILE*fp)
返回值:0或非0
Ferror函数检查上次对文件fp所进行的操作是否成功,如果成功则返回0;出错返回非0。因此,应该及时调用ferror函数检测操作执行的情况,以免丢失信息。
C字符串操作
C语言里的字符串操作函数都定义在头文件string.h中。string.h头文件定义了一个变量类型、一个宏和各种操作字符数组的函数。下面是头文件string.h中定义的变量和宏:
下面是头文件string.h中定义的函数,以下常用的函数需要掌握,见表
常用的函数
函数 | 描述 |
void *memcpy(void *dest,const void *src,size_t n) | 从src复制n个字符到dest |
void *memset(void *str,int c,size_t n) | 复制字符c(一个无符号字符)到参数str所指向的字符串的前n个字符 |
char *strcat(char *dest,const char *src) | 把src所指向的字符串追加到dest所指向的字符串的结尾 |
char *strncat(char *dest,const char *src,size_t n) | 把src所指向的字符串追加到dest所指向的字符串的结尾,直到n字符长度为止 |
char *strchr(const char *str,int c) | 在参数str所指向的字符串中搜索第一次出现字符c(一个无符号字符)的位置 |
int strcmp(const char *strl,const char *str2) | 把strl所指向的字符串和str2所指向的字符串进行比较 |
int strncmp(const char*strl,const char *str2,size_t n) | 把strl和str2进行比较,最多比较前n个字节 |
char *strcpy(char *dest,const char *src) | 把src所指向的字符串复制到dest |
char*strncpy(char *dest,const char *src,size_t n) | 把src所指向的字符串复制到dest,最多复制n个字符 |
size_t strlen(const char *str) | 计算字符串str的长度,直到空结束字符,但不包括空结束字符 |
char*strrchr(const char *str,int c) | 在参数str所指向的字符串中搜索最后一次出现字符c(一个无符号字符)的位置 |
char*strstr(const char *haystack,const char *needle) | 在字符串haystack中查找第一次出现字符串needle(不包含空结束字符)的位置 |