第 15 章 预处理器
15.4 条件编译 #if
——— 和if、else if、if用法相同
1. #if :用于预处理器的条件判断,满足条件时,内部的行会被编译,否则就被编译器忽略。
1.1 单向分支
#if
#endif
1.2 双向分支
#if
#else
#endif
1.3 多向分支
#if
#elif ——>对应:else
#elif
...
#else
#endif
2. #ifdef :用于判断某个宏是否定义过。
2.1 单向分支
#ifdef
#endif
2.2 双向分支
#ifdef
#else
#endif
---------2、3用法相同
3. #if defined
3.1 单向分支
#if defined
#endif
3.2 双向分支
#if defined
#else
#endif
3.3 多向向分支
#if defined
#elif
...
#else
#endif
4. #ifndef :用来判断,如果某个宏没有被定义过,则执行指定的操作。
——宏 名称 是对应文件名 的大写
4.1 单向分支
#ifndef
#endif
4.2 双向分支
#ifndef
#else
#endif
预处理指令总结
*指令* | *说明* |
---|---|
#include | 包含一个源代码文件 |
#define | 定义宏 |
#undef | 取消已定义的宏 |
#if | 如果给定条件为真,则编译下面代码 |
#ifdef | 如果宏已经定义,则编译下面代码 |
#ifndef | 如果宏没有定义,则编译下面代码 |
#elif | 如果前面的#if给定条件不为真,当前条件为真,则编译下面代码 |
#endif | 结束一个#if……#else条件编译块 |
第 16 章 IO流(文件操作)
Ø 输入流(Input Stream):数据从数据源(例如文件、键盘等)到程序(内存)的传输路径。
Ø 输出流(Output Stream):数据从程序(内存)到数据源(例如文件、屏幕等)的传输路径。
输入 与 输出:
-
输入:这意味着要向程序(内存)中写入一些数据
(C语言提供了一系列内置的函数来读取给定的输入,并根据需要写入到程序中。)
-
输出:意味着要在屏幕上、打印机上或文件中显示(或保存)一些数据
(C语言提供了一系列内置的函数来 输出数据 到指定的载体上。)
16.1 输入输出
① 输入
1、scanf()
2、getchar():函数用于从标准输入流(通常是键盘输入)读取一个字符。这个函数在同一个时间内只会读取一个单一的字符。
函数原型:int getchar(void);
返回值说明:
返回一个整数值,表示读取的字符。
3、gets():用于从标准输入流(通常是键盘)读取一行文本,并将其存储在一个字符数组中(gets() 的参数),直到遇到换行符为止。
函数原型:char *gets(char *str);
返回值说明:
返回一个指向存储在 str 中的字符串的指针
参数说明:
字符数组(字符串)的指针,用于存储读取的输入数据。
不安全,不会检查终端输入的字符串长度;使用fgets() 代替 gets()
// 相对于fgets: ①所有的空白字符(换行、空格、制表符)都表示输入结束
② 获取的字符串中不包括换行
② 输出
1、printf()
2、putchar():用于将一个字符写入到标准输出流(通常是屏幕)。这个函数在同一个时间内只会输出一个单一的字符。
函数原型:int putchar(int character);
返回值说明:
返回一个整数值,是写入的字符的ASCII码值。
参数说明:
character是要写入的字符的ASCII码值。
3、puts():用于将字符串输出到标准输出流(通常是屏幕),并自动添加换行符。它接受一个字符串作为参数,然后将其显示在屏幕上。
函数原型:int puts(const char *str);
返回值说明:
返回成功写入的字符数,如果写入失败或出现错误,它会返回 特殊值EOF((EOF 是一个定义在 stdio.h 头文件中的常量,值通常为 -1))。
参数说明:
str 是要输出的字符串。
16.2 文件读写
*标准文件* | *文件指针* | *设备* |
---|---|---|
*标准输入* | stdin | 键盘 |
*标准输出* | stdout | 屏幕 |
*标准错误* | stderr | 屏幕 |
文件指针是访问文件的方式,我们会讲解如何从键盘获取输入值以及如何把结果输出到屏幕上。
① 文件打开关闭
fopen() fclose()
1. fopen():创建一个新的文件或者打开一个已有的文件。该函数位于标准库的 stdio.h 头文件中。
函数原型:FILE *fopen( const char *filename, const char *mode );
返回值说明:
返回一个指向 FILE 结构的指针,该结构表示文件流,可以使用这个指针来进行文件的读取和写入操作。如果打开文件失败,返回一个空指针(NULL)。
参数说明:
(1)filename是一个以字符串形式指定的文件名,表示要打开的文件的名称,可以包括文件路径和文件名。
(2)mode 是一个以字符串形式指定的打开模式,表示打开文件的方式
2. fclose():可以关闭文件。该函数位于标准库的 stdio.h 头文件中。
函数原型:int fclose(FILE *stream);
返回值说明:
返回一个整数值,通常为零(0),表示关闭操作成功。如果关闭失败,它返回特殊值EOF (EOF 是一个定义在 stdio.h 头文件中的常量,值通常为 -1)。
参数说明:
stream是一个指向 FILE 结构的指针,表示要关闭的文件流。
打开模式
r 只读
w 只写(清空写,文件不存在自动创建)
a 只写(追加写,文件不存在自动创建)
r+ 读写
w+ 读写(清空原内容)
a+ 读写
② 读文件(对应输入)
fscanf() fgets() fgetc()
1. fscanf():格式化读取文件内容
用于从文件中解析数据并存储到变量中,使用空白字符(空格、制表符、换行符等)分隔内容赋值给不同的变量。该函数位于标准库的stdio.h 头文件中。
函数原型:int fscanf(FILE *stream, const char *format, ...);
返回值说明:
返回成功读取和分配的参数数目,如果没有成功读取任何参数,它返回 0;如果读取过程中发生错误,它返回特殊值 EOF。
参数说明:
(1)stream是一个指向 FILE 结构的指针,表示要从中读取数据的文件流。
(2)format是一个格式化字符串,类似于 printf() 函数中的格式化字符串。
(3)... 表示可变数量的参数,根据格式化字符串中的格式指定要存储数据的变量。
2. fgets(): 一次读取一行或指定长度 ——推荐!
只有换行才表示输入结束,换行也会被获取到字符串
从文件中逐行读取,遇到换行符即读取结束,读取的内容中包含换行符。该函数位于标准库的stdio.h 头文件中。
函数原型:char *fgets(char *str, int num, FILE *stream);
返回值说明:
如果读取成功,它返回指向 str 的指针;如果到达文件结束或发生错误,它返回一个空指针(NULL)。
参数说明:
(1)str是一个指向字符数组的指针,用于存储读取的字符串。
(2)num是要读取的最大字符数(包括字符串终止符 \0),通常是str的长度。
(3)stream是一个文件流,通常是标准输入流(stdin)或其他文件流,用于指定从哪里读取数据。
3. fgetc():一次读一个字符。用于从文件中逐字符读取。位于标准库的stdio.h 头文件中。
函数原型:int fgetc(FILE *stream);
返回值说明:
如果读取成功,它返回所读取字符的ASCII码值(0-255之间的整数),如果到达文件结束或发生错误,它返回特殊值 EOF。
参数说明:
stream是一个指向 FILE 结构的指针,表示要写入字符的文件流。
③ 写文件(对应输出)
fprintf() fputc() fputs()
1. fprintf():用于格式化写入文件。位于标准库的stdio.h 头文件中。
函数原型:int fprintf(FILE *stream, const char *format, ...);
返回值说明:
返回一个整数值,如果写入成功,则返回非负整数(通常是成功写入的字符数,具体取决于编译器),否则返回特殊值 EOF。
参数说明:
(1)stream是一个指向 FILE 结构的指针,表示要写入的文件流。
(2)format是一个格式化字符串,类似于 printf() 函数中的格式化字符串。
(3)...表示可变数量的参数,根据格式化字符串中的格式占位符对应。
2.fputc():用于逐字符写入文件。位于标准库的stdio.h 头文件中。
函数原型:int fputc(int character, FILE *stream);
返回值说明:
返回一个整数值,如果写入成功,则返回非负整数(通常是成功写入的字符数,具体取决于编译器),否则返回特殊值 EOF。
参数说明:
(1)str是要写入的字符串,通常以 const char* 指针的形式传递。
(2)stream是指向输出流的指针,通常是文件指针。
3.fputs():用于将字符串写入文件。位于标准库的stdio.h 头文件中。
函数原型:int fputs(const char *str, FILE *stream);
返回值说明:
返回一个整数值,如果写入成功,则返回非负整数(通常是成功写入的字符数,具体取决于编译器),否则返回特殊值 EOF。
参数说明:
(1)str是要写入的字符串,通常以 const char* 指针的形式传递。
(2)stream是指向输出流的指针,通常是文件指针。
第 17 章 小小项目练习
1.主菜单和退出
#include <stdio.h>
// 定义结构体表示客户信息
typedef struct
{
int id; // 编号
char name[20]; // 姓名
enum
{
MALE = 'm',
FEMALE = 'f'
} gender; // 性别
int age; // 年龄
char phone[11]; // 电话
char email[40]; // 邮箱
} Customer;
// 定义数组存储客户信息 数组元素是 Customer 类型
Customer customers[100];
// 定义变了记录已经添加的客户的数量
int customer_count = 0;
int main()
{
// 定义变了控制是否循环
int loop = 1;
// 死循环启动
while (loop)
{
printf("\n---------------------客户信息管理系统---------------------");
printf("\n 1.添加客户");
printf("\n 2.删除客户");
printf("\n 3.修改客户");
printf("\n 4.客户列表");
printf("\n 5.退出");
printf("\n 请选择(1-5):");
// 定义变量 获取用户输入的操作选项
int chooise;
scanf("%d", &chooise);
// 判断用户操作
switch (chooise)
{
case 1:
printf("添加客户!");
break;
case 2:
printf("删除客户!");
break;
case 3:
printf("修改客户!");
break;
case 4:
printf("客户列表!");
break;
case 5:
// 让用户确认是否退出
char ch;
printf("请确认是否退出(Y或N):");
getchar();
scanf("%c", &ch);
// 判断
if (ch == 'Y' || ch == 'y')
{
printf("退出客户信息管理系统,再见!");
loop = 0;
}
break;
default:
printf("请输入正确的操作选项!");
break;
}
}
return 0;
}
2. 添加客户
#include <stdio.h>
// 定义结构体表示客户信息
typedef struct
{
int id; // 编号
char name[20]; // 姓名
enum
{
MALE = 'm',
FEMALE = 'f'
} gender; // 性别
int age; // 年龄
char phone[11]; // 电话
char email[40]; // 邮箱
} Customer;
// 定义数组存储客户信息 数组元素是 Customer 类型
Customer customers[100];
// 定义变了记录已经添加的客户的数量
int customer_count = 0;
// 定义函数 实现添加客户
void add()
{
printf("\n---------------------添加客户---------------------");
// 设置客户的编号
customers[customer_count].id = customer_count + 1;
// 输入客户的姓名并设置
printf("\n姓名:");
scanf("%s", customers[customer_count].name);
// 输入客户的性别并设置
printf("\n性别(m或f):");
getchar();
scanf("%c", (char *)&(customers[customer_count].gender));
// 输入客户的年龄并设置
printf("\n年龄:");
scanf("%d", &customers[customer_count].age);
// 输入客户的电话并设置
printf("\n电话:");
scanf("%s", customers[customer_count].phone);
// 输入客户的邮箱并设置
printf("\n邮箱:");
scanf("%s", customers[customer_count].email);
// 已添加的客户数量自增
customer_count ++;
printf("\n客户添加成功!");
}
int main()
{
// 定义变了控制是否循环
int loop = 1;
// 死循环启动
while (loop)
{
printf("\n---------------------客户信息管理系统---------------------");
printf("\n 1.添加客户");
printf("\n 2.删除客户");
printf("\n 3.修改客户");
printf("\n 4.客户列表");
printf("\n 5.退出");
printf("\n 请选择(1-5):");
// 定义变量 获取用户输入的操作选项
int chooise;
scanf("%d", &chooise);
// 判断用户操作
switch (chooise)
{
case 1:
add();
break;
case 2:
printf("删除客户!");
break;
case 3:
printf("修改客户!");
break;
case 4:
printf("客户列表!");
break;
case 5:
// 让用户确认是否退出
char ch;
printf("请确认是否退出(Y或N):");
getchar();
scanf("%c", &ch);
// 判断
if (ch == 'Y' || ch == 'y')
{
printf("退出客户信息管理系统,再见!");
loop = 0;
}
break;
default:
printf("请输入正确的操作选项!");
break;
}
}
return 0;
}
3.客户列表
#include <stdio.h>
// 定义结构体表示客户信息
typedef struct
{
int id; // 编号
char name[20]; // 姓名
enum
{
MALE = 'm',
FEMALE = 'f'
} gender; // 性别
int age; // 年龄
char phone[11]; // 电话
char email[40]; // 邮箱
} Customer;
// 定义数组存储客户信息 数组元素是 Customer 类型
Customer customers[100];
// 定义变了记录已经添加的客户的数量
int customer_count = 0;
// 定义函数 实现添加客户
void add()
{
printf("\n---------------------添加客户---------------------");
// 设置客户的编号
customers[customer_count].id = customer_count + 1;
// 输入客户的姓名并设置
printf("\n姓名:");
scanf("%s", customers[customer_count].name);
// 输入客户的性别并设置
printf("\n性别(m或f):");
getchar();
scanf("%c", (char *)&(customers[customer_count].gender));
// 输入客户的年龄并设置
printf("\n年龄:");
scanf("%d", &customers[customer_count].age);
// 输入客户的电话并设置
printf("\n电话:");
scanf("%s", customers[customer_count].phone);
// 输入客户的邮箱并设置
printf("\n邮箱:");
scanf("%s", customers[customer_count].email);
// 已添加的客户数量自增
customer_count ++;
printf("\n客户添加成功!");
}
// 定义函数 显示客户列表
void list()
{
printf("\n---------------------客户列表---------------------");
// 如果没有客户信息
if (customer_count <= 0)
{
printf("\n当前还没有客户信息,快去添加吧!");
return;
}
// 输出表头
printf("\n编号\t姓名\t性别\t年龄\t电话\t邮箱");
// 遍历数组显示客户信息
for (int i = 0; i < customer_count; i ++)
{
printf("\n%d\t%s\t%c\t%d\t%s\t%s", customers[i].id, customers[i].name, customers[i].gender, customers[i].age, customers[i].phone, customers[i].email);
}
}
int main()
{
// 定义变了控制是否循环
int loop = 1;
// 死循环启动
while (loop)
{
printf("\n---------------------客户信息管理系统---------------------");
printf("\n 1.添加客户");
printf("\n 2.删除客户");
printf("\n 3.修改客户");
printf("\n 4.客户列表");
printf("\n 5.退出");
printf("\n 请选择(1-5):");
// 定义变量 获取用户输入的操作选项
int chooise;
scanf("%d", &chooise);
// 判断用户操作
switch (chooise)
{
case 1:
add();
break;
case 2:
printf("删除客户!");
break;
case 3:
printf("修改客户!");
break;
case 4:
list();
break;
case 5:
// 让用户确认是否退出
char ch;
printf("请确认是否退出(Y或N):");
getchar();
scanf("%c", &ch);
// 判断
if (ch == 'Y' || ch == 'y')
{
printf("退出客户信息管理系统,再见!");
loop = 0;
}
break;
default:
printf("请输入正确的操作选项!");
break;
}
}
return 0;
}
4. 删除客户
#include <stdio.h>
#include <stdbool.h>
// 定义结构体表示客户信息
typedef struct
{
int id; // 编号
char name[20]; // 姓名
enum
{
MALE = 'm',
FEMALE = 'f'
} gender; // 性别
int age; // 年龄
char phone[11]; // 电话
char email[40]; // 邮箱
} Customer;
// 定义数组存储客户信息 数组元素是 Customer 类型
Customer customers[100];
// 定义变了记录已经添加的客户的数量
int customer_count = 0;
// 定义函数 实现添加客户
void add()
{
printf("\n---------------------添加客户---------------------");
// 设置客户的编号
customers[customer_count].id = customer_count + 1;
// 输入客户的姓名并设置
printf("\n姓名:");
scanf("%s", customers[customer_count].name);
// 输入客户的性别并设置
printf("\n性别(m或f):");
getchar();
scanf("%c", (char *)&(customers[customer_count].gender));
// 输入客户的年龄并设置
printf("\n年龄:");
scanf("%d", &customers[customer_count].age);
// 输入客户的电话并设置
printf("\n电话:");
scanf("%s", customers[customer_count].phone);
// 输入客户的邮箱并设置
printf("\n邮箱:");
scanf("%s", customers[customer_count].email);
// 已添加的客户数量自增
customer_count ++;
printf("\n客户添加成功!");
}
// 定义函数 显示客户列表
void list()
{
printf("\n---------------------客户列表---------------------");
// 如果没有客户信息
if (customer_count <= 0)
{
printf("\n当前还没有客户信息,快去添加吧!");
return;
}
// 输出表头
printf("\n编号\t姓名\t性别\t年龄\t电话\t邮箱");
// 遍历数组显示客户信息
for (int i = 0; i < customer_count; i ++)
{
printf("\n%d\t%s\t%c\t%d\t%s\t%s", customers[i].id, customers[i].name, customers[i].gender, customers[i].age, customers[i].phone, customers[i].email);
}
}
// 定义函数 执行删除操作,参数是要删除的客户的编号, 返回1表示删除成功,返回0表示删除失败
bool delete(int id)
{
// 判断编号是否在合理范围内
if (id < 0 || id > customer_count)
{
return false;
}
// 根据编号计算下标
int index = id - 1;
// 执行删除 从被删除的客户开始,向后遍历
for (int i = index; i < customer_count - 1; i ++)
{
// 将后面元素的值赋值给当前元素
customers[i] = customers[i+1];
// 修改编号
customers[i].id --;
}
// 已添加客户个数自减
customer_count --;
return true;
}
// 定义函数 删除界面
void deleteView()
{
// 获取用户输入的要删除客户编号
int deleted_id;
printf("\n请输入要删除客户的编号(-1表示退出):");
scanf("%d", &deleted_id);
// 判断是否退出
if (deleted_id == -1)
{
printf("\n退出删除操作!");
return;
}
// 确认是否删除
char ch;
printf("\n确认是否删除(Y或N):");
getchar();
scanf("%c", &ch);
// 判断是否退出 需要退出的情况
if (ch != 'Y' && ch != 'y')
{
printf("\n退出删除操作!");
return;
}
// 开始执行删除
if (delete(deleted_id))
{
printf("\n删除成功!");
}
else
{
printf("\n删除失败!客户不存在!");
}
}
int main()
{
// 定义变了控制是否循环
int loop = 1;
// 死循环启动
while (loop)
{
printf("\n---------------------客户信息管理系统---------------------");
printf("\n 1.添加客户");
printf("\n 2.删除客户");
printf("\n 3.修改客户");
printf("\n 4.客户列表");
printf("\n 5.退出");
printf("\n 请选择(1-5):");
// 定义变量 获取用户输入的操作选项
int chooise;
scanf("%d", &chooise);
// 判断用户操作
switch (chooise)
{
case 1:
add();
break;
case 2:
deleteView();
break;
case 3:
printf("修改客户!");
break;
case 4:
list();
break;
case 5:
// 让用户确认是否退出
char ch;
printf("请确认是否退出(Y或N):");
getchar();
scanf("%c", &ch);
// 判断
if (ch == 'Y' || ch == 'y')
{
printf("退出客户信息管理系统,再见!");
loop = 0;
}
break;
default:
printf("请输入正确的操作选项!");
break;
}
}
return 0;
}
5. 修改客户
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· .NET10 - 预览版1新功能体验(一)