C 语言课程总结

专题 1:字符串部分

scanf 不能输入空格、回车或制表符号(Tab)等空字符,不能被 scanf 读入,输入遇到这些字符时,系统认为字符串输入结束;gets 可以输入此类空字符。

字符输入输出:

字符串输入输出:

方法一:使用 getchar/putchar 挨个输入/出

方法二:使用 gets/puts 函数:

方法三:使用 fgets/fputs 函数:

fgets 与 gets 相比,具有的优点:能够限制输入字符串的长度。

字符串处理函数:

  • strlen(char* str); 计算字符串的长度(不包括\0的实际字符的个数),用途:可以用长度控制字符串的输出。
  • strcpy(char* dst, char* src); 字符串拷贝,方向:源字符串–>目的字符串。
  • strcat(char* dst, char* src); 字符串合并,把源字符串连接在目的字符串后面,目的字符串的长度必须足够长。
  • strcmp(char* str1, char* str2); 字符串比较,当出现第一对不相等的字符时,就由这两个字符决定所在的字符串的大小,返回其ASCII码比较的结果。
  • strcmp(str1, str2); 若 < 0 为真 <=> st1 < str2。

n 族字符串处理函数:

  • strncpy(str1, str2, n); 将 str2 的至多前n个字符拷贝到字符数组 str1 中
  • strncat(str1, str2, n); 将 str2 的至多前n个字符连接到字符串 str1 末端,str1 的结束符被 str2 的第一个字符替代。
  • strncmp(str1, str2, n); 最多比较 str1 与 str2 的前 n 个字符。

专题 2:指针(Pointer)部分

指针为函数提供修改变量值的手段。

其中,%p 表示输出变量 a 的地址值。

变量地址存入指针变量,指针变量指向的数据类型为基类型,用指针变量指向的数据类型作为指针变量的基类型。

一个指针变量只能指向与其类型相同的变量,指针变量只存放地址!

指针变量使用之前必须初始化(赋值),如果指针指向一个非你控制和的内存空间并对该空间进行访问,将可能造成危险!

使用指针变量,通过间接寻址输出变量的值:

输出信息:a is 0, &a is 0023FF74, pa is 0023FF74, *pa is 1

*pa = 9; 修改指针变量 pa 所指向的变量的值。引用指针所指向的变量的值称为指针的解应用(Pointer Dereference),可以像普通变量一样使用 *pa 。

当一个字符串常量出现于一个表达式中时,表达式所使用的值就是这些字符所储存的地址,而不是这些字符本身。因此,你可以把字符串常量赋值给一个“指向字符的指针”,后者指向字符所储存的地址,如:

但是,你不能把字符串常量赋值给一个字符数组,因为字符串常量的直接值是一个指针,而不是这些字符本身。简单的说,字符串常量的值是这些字符在内存中的地址。

指针的数值运算:指针的加减运算是以其基类型的字节长度为单位的,指针运算不能乱算,通常由下面两种情况:指针和整数的加减运算;同类型指针之间的减法运算。其它运算,比如乘除、浮点运算、指针之间的加法等,并无意义,所以也不支持。

指针的关系运算:指向同一种数据类型的两个指针才能进行关系运算,值为1或0,不能与非指针类型变量进行比较

普通变量作函数参数-按值调用:形参(parameter) <– 实参变量(variable)

指针作函数参数-按地址调用:指针形参(pointer parameter) <– &(variable)

普通变量作函数参数,形参值的改变不会影响对应的实参;指针变量作函数参数,可以修改实参的值!

专题 3:结构体

结构体类型的声明:

以上为一个类型声明的模板,用于生成结构体变量,但并未声明结构体变量,因而编译器不为其分配内存。

结构体变量的定义:

1) 先定义结构体类型再定义变量名

2) 在定义类型的同时定义变量

3)直接定义结构体变量(不指定结构体标签)

用typedef定义数据类型名:

结构体变量的初始化:

结构体的嵌套:

访问结构体变量的成员必须使用成员选择运算符(也称原点运算符),当出现结构体嵌套时,必须以连级方式访问结构体成员:

结构体变量的赋值操作和引用方法:

格式符 %02d 中 2d 前面的前导符 0 表示输出数据时,若左边有多余位,则补 0。

输入结构体变量 stu1 的内容:

结构体数组的定义和初始化:

结构体数组的指针:

访问结构体数组指针指向的结构体成员:

一般情况下我们只用只指向结构体的指针,而不用指向结构体成员的指针

结构体变量作函数参数,形参的改变不影响对应的实参;结构体指针作函数参数,形参的改变会改变相应的实参。指针作函数形参,实参必须为地址值!

结构体变量作函数返回值:

向函数传递结构体:

  • 1) 向函数传递结构体的完整地址:复制整个结构体成员的内容,多个值;函数内对结构内容的修改不影响原结构;内容传递更直观,但开销大
  • 2) 向函数传递结构体的首地址:用结构体数组/结构体指针作函数参数;仅复制该结构体的首地址,一个值;修改结构体指针所指向的结构体的内容;指针传递效率高

用户自定义的数据类型:

结构体(struct):把关系紧密且逻辑相关的多种不同类型的变量,组织到统一的名字下,占用相邻的一段内存单元

共用体/联合体(union):把情形互斥但逻辑相关的多种不同类型的变量,组织到统一的名字之下,占用同一段内存单元,每一时刻只有一个数据起作用

sizeof(union number) 取决于占空间最多的那个成员变量;同一内存单元在每一瞬间只能存放其中一种类型的成员;起作用的成员是最后一次存放的成员,不能作为函数参数;不能进行比较操作,只能对第一个成员初始化。

枚举(Enumeration)数据类型:

描述的是一组整型值的集合;用于当某些量仅由有限个数据值组成时

动态数据结构——单向链表:

链表(Linked Table):线性表的链式存储结构。

特点:用一组任意的存储单元存储线性表的数据,存储单元可以是连续的,也可以是不连续的。为表示每个元素与后续元素的逻辑关系,除存储元素本身信息外,还要存储其直接后继信息。

数据域和指针域两部分信息组成一个节点。结构体声明时不能包含本结构体类型成员,系统将无法为这样的结构体分配内存;但是可包含指向本结构体类型的指针变量:

head–>data|next–>data|next–>data|next–>……->data|NULL。n个节点链接成一个链表(因为只包含一个指针域,故又称线性链表或单向链表)。

动态内存分配函数:

  • void* malloc(unsigned int size); 向系统申请大小为 size 的内存快,把首地址返回,若申请不成功则返回 NULL
  • void* calloc(unsigned int num, unsigned int size); 向系统申请 num 个 size 大小的内存块,把首地址返回,若申请不成功则返回 NULL。
  • void* free(void* p); 释放由 malloc() 和 calloc() 申请的内存块,p 是指向此内存的指针,free 时系统标记此内存为未占用,可被重新分配。

为链表中的节点动态分配内存空间:

一.链表的建立:若原链表为非空,则将新建节点p添加到表尾。

(1) pr->next = p
(2) pr = p
(3) pr->next = NULL

二.链表的删除:若原链表为空表,则退出程序;若待删除节点p是头节点,则将 head 指向当前节点的下一个节点即可删除当前节点。

(1) head = p->next
(2) free(p)

若待删除的不是头节点,则将前一节点的指针指向当前节点的下一节点,即可删除当前节点:

(1) pr->next = p->next
(2) free(p)

若已搜索到表尾(p->next == NULL)仍未找到待删除节点,则显示”未找到”。

三.链表的插入操作:若原链表为空表,则将新节点 p 作为头节点,让 head 指向新节点p:

(1) head = p
p = (struct Link *)malloc(sizeof(struct Link));
p->next = NULL;
p->data = nodeData;

若原链表为非空,则按照节点值(假设已按升序排列)的大小确定插入新节点的位置;若在头节点前插入新节点,则将新节点的指针域指向原链表的头节点,且让 head 指向新节点:

(1) p->next = head
(2) head = p

若在链表中间插入新节点,则将新节点的指针指向下一节点且让前一节点的指针域指向新节点:

(1) p->next = pr->head
(1) p->next = p

若在表尾插入新节点,则末节点指针域指向新节点

(1) pr->net = p

四.链表的输出:

遍历链表的所有节点:

专题:文件操作

I/O设备:

输入设备:键盘、鼠标;软盘、硬盘、光驱(以文件的形式);扫描仪、视频采集卡、电视卡、游戏杆、话筒等。

输出设备:显示器、打印机;软盘、硬盘、CD/DVD-RW(以文件形式);音箱……
PS:单纯的输入设备或者输入设备越来越少。

标准输入/输出:

字符界面的操作系统(DOS、Linux、UNIX……)一般都提供标准输入与输出设备;一般情况,标准输入就是键盘,标准输出,就是终端显示器;操作系统有能力重定向标准输入与输出,比如让文件作为标准输入(标准输出);这种重定向程序本身是感觉不到的。

计算机中流(Stream)的概念:一般称为数据流,也叫字节流,比特流。文件流(File stream)等数据流可以倒流,网络上的数据流等数据流不会倒流。流的载体有磁盘文件、终端显示器或打字机、存储器等。

外存:内容容易健忘,所以数据必须保存在“不健忘”的外存上:磁盘(Magnetic disks)、光盘(CD、DVD)、U盘(Flash Memory)……容量大、断电后数据不丢失,可重复使用、永久保存。一般都以文件的形式给用户及应用程序使用。

文件(File):一般指存储在外部介质上有名字的一组相关数据的集合;用文件可长期保存数据,实现数据共享;在 C 语言中,文件可泛指磁盘文件、终端显示器或打印机等。

程序中的文件:在程序运行时由程序在磁盘上建立的一个文件,通过写操作将数据存入该文件;由程序打开磁盘上的某个已有文件,并通过该操作将文件中的数据读入内存供程序使用。

文件与流:程序通过文件打开操作把流与设备联系起来,文件打开后,可在程序和文件之间交换数据;程序通过文件关闭操作断开与文件的联系;所有流的性质都一样(因为流与设备无关,所以能写入磁盘的同一函数也能写入另一设备,如控制台终端等);文件的能力则不同(如磁盘文件支持随机存储,而键盘则不能)。

文件的类型:

二进制文件:一种字节序列,没有字符交换;按照数据在内存中的存储形式(二进制)存储到文件。如整数 123,在内存占 2 个字节,在文件中也占 2 个字节:00000000|01111011

文本文件/ ASCII 码文件:一种字符序列,文件中存储每个字符的 ASCII 码。如整数 123 在文件中占 3 个字节,分别存放这 3 个字符的 ASCII 码:
字符: ‘1’ ‘2’ ‘3’
十进制的ASCII值: 49 50 51
二进制的ASCII值: 0011001 00110010 00110011

文件的格式:数据必须按照存入的类型读出,才能恢复其本来面貌;公开的标准格式:如 bmp、tif、gif、jpg 和 mp3 等类型的文件,有大量的软件能生成和使用这些类型的文件;不公开或加密的文件格式:如 MiscroSoft Word 的 doc 格式等。

缓冲型和非缓冲型文件系统:

缓冲型文件系统:指系统自动在内存中为每一个正在使用的文件开辟一个缓冲区,在读写文件时,数据先送到缓冲区,再传给C程序或外存上;缓冲文件利用文件指针标示文件;缓冲型文件系统中文件操作,也称高级文件操作;高级文件操作函数是 ANSI C 定义的文件操作函数,具有跨平台和可移植的能力

非缓冲型文件系统:不会自动设置文件缓冲区,缓冲区需由程序员自己设定;非缓冲文件系统没有文件指针,它使用称为文件号的整数来标识文件。

高级文件操作函数:
以下介绍的函数均定义在<stdio.h>中:

文件的打开:
FILE *fopen(const char *filename, const char *mode);
FILE *fp = fopen(“C:\CONFIG.SYS”, “rw”);
filename 是文件名,包含路径。如果不包含路径,表示打开当前目录下的文件
mode 是打开方式,常用为“r”、“w”、“rw”、“a”,分别表示只读、只写、读写和添加(追加),“rb”表示只读二进制文件。详细用法如下:

  • “r”:只读,必须是已存在的文件
  • “w”:只写,不论该文件是否存在,都新建一个文件
  • “a”:追加,向该文件尾追加数据,该文件必须存在
  • “r+”:读写,打开一个已经存在的文件,用于读写
  • “w+”:读写,建立一个新文件,可读可写
  • “a+”:读写,向文件尾追加数据,也可读

对应的二进制文件打开方式分别为:”rb”、”wb”、”ab”、”rb+”、”wb+”、”ab+”;返回值为指向此文件的指针,留待以后使用;如果打开失败,返回值为NULL。

文件指针(File Pointer):
FILE *p; FILE 型的指针变量,标识一个特定的磁盘文件,与文件相关联的每一个流都有一个 FILE 类型的控制结构,定义有关文件操作的信息,用户绝对不应修改。

文件的关闭:

int fclose(FILE *fp); 把遗留在缓冲区中的数据写入文件,实际操作系统级的关闭操作;同时,释放与流联系的文件控制块,以后可以重复使用这部分空间;多数情况下,系统限制同时处于打开状态的文件总数,因此,打开文件前先关闭无用文件是必要的

fclose 函数的返回值:当顺利地执行了关闭操作,返回值为 0;如果返回值为非零值,表示关闭时有错误;一般只有驱动器中无盘或盘空间不够时才失败,关闭失败会引起数据丢失、文件的破坏和程序中的随机错误。

字符读写:

int gfetc(FILE *fp); 从 fp 读出一个字符,将位置指针指向下一个字符;若读取成功,则返回该字符,若读到文件尾,则返回 EOF(EOF 是一个符号常量,在 stdio.h 中定义为 -1)。

int fputc(int c, FILE *fp); 向 fp 输出字符 c;若写入错误,则返回 EOF,否则返回 c。实例:

函数 feof() 检查是否到达文件尾,当文件位置指向文件尾时,返回非 0 值,否则返回 0 值;

字符串读写:

char *fgets(char *s, int n, FILE *fp); 从 fp 指向的文件中读取字符串并在字符串末尾添加 ‘\0’,然后存入 s,最多读 n-1 个字符;当读到回车换行符、文件末尾或读满 n-1 个字符时,函数返回该字符串的首地址。

特例:fgets(buf, sizeof(buf), stdin);
int fputs(const char *s, FILE *fp); 将字符写入文件中;若出现写入错误,则返回EOF,否则返回一个非负数。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据