C语言 | 第十七章 | 家庭收支软件-2 读写文件

news2024/10/20 21:03:02

P 161 项目-CRM(3)-主菜单 2023/3/23

一、显示主菜单

功能说明:用户打开软件,可以看到主菜单,输入5退出软件

思路分析:在customerManage.c中,编写一个函数mainMenu,显示菜单, 在main函数中调,用代码实现。

#include<stdio.h>

// 定义结构体数据类型 
struct Customer{
	int id; // 编号
	int age;  // 年龄
	char name[10]; // 名字
	char gender;  // f 表示女,m表示男
	char phone[16]; //  电话号码
	char email[20]; // 邮箱
};

int loop = 1;  // 控制是否退出主菜单
char key;

// 显示一个Customer变量的信息
// 这里我们接收的是结构体指针,目的是提高效率
void getCustomerInfo(struct Customer * customer){
	printf("\n%d\t%s\t%s\t%d\t%c\t%s\t%s",(* customer).id,(* customer).gender,(* customer).name,(* customer).age,(* customer).phone,(* customer).email);
}

// 显示主菜单
void mainMenu(){
	do {
		printf("\n-----------------客户信息管理软件-----------------");
		printf("\n		1 添 加 客 户");
		printf("\n		2 修 改 客 户");
		printf("\n		3 删 除 客 户");
		printf("\n		4 客 户 列 表");
		printf("\n		5 退	   出");
		printf("\n请选择(1-5):");
		scanf("%c",&key);
		getchar();  // 过滤回车

		switch(key){
		case '1':
			printf("添加客户");
			break;
		case '2':
			printf("修改客户");
			break;
		case '3':
			printf("删除客户");
			break;
		case '4':
			printf("客户列表");
			break;
		case '5':
			printf("退出");
			loop = 0;
			break;
		default:
			printf("\n你的输入有误,请重新输入");
			break;
		}
	}while(loop);
	printf("\n你退出了客户管理系统");
	getchar();
}

void main(){
mainMenu(); // 调用函数,显示菜单
}

P 162 项目-CRM(4)-显示客户 2023/3/24

一、显示客户

思路分析:

  1. 因为我们需要将多个客户保存起来,因此我们需要使用结构体数组-Customer 结构体数组。
  2. 编写一个函数listCutomers来显示客户信息。
  3. 在主菜单中调用listCustomers
#include<stdio.h>
#include<string.h>

// 定义结构体数据类型 
struct Customer{
	int id; // 编号
	int age;  // 年龄
	char name[10]; // 名字
	char gender;  // f 表示女,m表示男
	char phone[16]; //  电话号码
	char email[20]; // 邮箱
};

int loop = 1;  // 控制是否退出主菜单
char key;
int customerNum = 1;  // 表示当前有多少个客户

// 定义客户结构体数组;数组显示多组数据
struct Customer customers[100];

// 显示一个Customer变量的信息
// 这里我们接收的是结构体指针,目的是提高效率
void getCustomerInfo(struct Customer * customer){
	printf("\n%d\t%s\t%c\t%d\t%s\t%s",(* customer).id,(* customer).name,(* customer).gender,(* customer).age,(* customer).phone,(* customer).email);
}

// 显示客户信息列表
void listCustomer(){
	int i = 0;
	printf(" ---------------------------客户列表---------------------------");
	printf("\n编号\t姓名\t性别\t年龄\t电话\t邮箱");
	for(i = 0; i < customerNum; i++){  // 表示客户的编号,循环打印客户信息
		getCustomerInfo(&customers[i]);
	}
}

// 显示主菜单
void mainMenu(){
	do {
		printf("\n\n\n-----------------客户信息管理软件-----------------");
		printf("\n		1 添 加 客 户");
		printf("\n		2 修 改 客 户");
		printf("\n		3 删 除 客 户");
		printf("\n		4 客 户 列 表");
		printf("\n		5 退	   出");
		printf("\n请选择(1-5):");
		scanf("%c",&key);
		getchar();  // 过滤回车

		switch(key){
		case '1':
			printf("添加客户");
			break;
		case '2':
			printf("修改客户");
			break;
		case '3':
			printf("删除客户");
			break;
		case '4':
			listCustomer();
			break;
		case '5':
			printf("退出");
			loop = 0;
			break;
		default:
			printf("\n你的输入有误,请重新输入");
			break;
		}
	}while(loop);
	printf("\n你退出了客户管理系统");
	getchar();
}

void main(){
	// 为了测试显示客户信息,我们可以先初始化一个客户,后面通过界面进行添加
	customers[0].id = 1;
	customers[0].age = 10;
	// 邮箱不可以直接像上面一样赋值
	// 原因:此时数组是个指针,指针指向元素首地址,这样的话赋值相当于修改地址,不可以
	// 需要用到拷贝的方法:如下
	strcpy(customers[0].email,"yy@sohu.com");
	customers[0].gender = 'f';
	strcpy(customers[0].name,"zs");
	strcpy(customers[0].phone,"110");

	mainMenu(); // 调用函数,显示菜单
}

P 163 项目-CRM(5)-添加客户 2023/3/24

一、添加客户

功能说明:添加客户

思路分析:

  1. 编写一个add函数,在该函数中完成添加客户的功能。
  2. 在mainMenu调用即可
// 添加客户
void add(){
	customers[customerNum].id = customerNum + 1;  // 编号按照自增规则
	// 因为这里下标为0表示的是第一个人,下标为2表示的是第二个人,所以要这么写
	printf("\n---------------------添加客户---------------------");
	printf("\n姓名:");  //  一定要过滤回车,要不然就会被下面拿到回车
	scanf("%s",customers[customerNum].name);
	getchar();
	printf("\n性别:");
	scanf("%c",&customers[customerNum].gender);	
	getchar(); 
	printf("\n年龄:");
	scanf("%d",&customers[customerNum].age);
	getchar();
	printf("\n电话:");
	scanf("%s",customers[customerNum].phone);
	getchar();
	printf("\n邮箱:");
	scanf("%s",customers[customerNum].email);
	getchar();
	printf("---------------------添加完成---------------------");
	customerNum++;   // 这里必须,自增;否则会将上一个信息覆盖掉
}

	case '4':
	listCustomer();

P 164 项目-CRM(6)-删除客户 2023/3/24

一、删除客户

功能说明:

image-20230324135416344

思路分析:

  1. 先编写一个函数findindex,根据用户输入的id去查找,该id是否存在customer结构体数组中,如果存在,就返回该id 对应的index,因为id和index不是对应关系;如果id存在则返回对应的index,否则返回-1。
  2. 编写一个函数del,该函数根据接收的index来判断是否可以删除;如果接收到的index是-1,就不删除,否则就删除该index对应的客户。
  3. 编写delVIew函数,让用户可以输入要删除的id,并且mainMenu函数中调用。
#include<stdio.h>
#include<string.h>

// 定义结构体数据类型 
struct Customer{
	int id; // 编号
	int age;  // 年龄
	char name[10]; // 名字
	char gender;  // f 表示女,m表示男
	char phone[16]; //  电话号码
	char email[20]; // 邮箱
};

int loop = 1;  // 控制是否退出主菜单
char key;
int customerNum = 1;  // 表示当前有多少个客户

// 定义客户结构体数组;数组显示多组数据
struct Customer customers[100];

// 显示一个Customer变量的信息
// 这里我们接收的是结构体指针,目的是提高效率
void getCustomerInfo(struct Customer * customer){
	printf("\n%d\t%s\t%c\t%d\t%s\t%s",(* customer).id,(* customer).name,(* customer).gender,(* customer).age,(* customer).phone,(* customer).email);
}

// 添加客户
void add(){
	customers[customerNum].id = customerNum + 1;  // 编号按照自增规则
	// 因为这里下标为0表示的是第一个人,下标为2表示的是第二个人,所以要这么写
	printf("\n---------------------添加客户---------------------");
	printf("\n姓名:");  //  一定要过滤回车,要不然就会被下面拿到回车
	scanf("%s",customers[customerNum].name);
	getchar();
	printf("\n性别:");
	scanf("%c",&customers[customerNum].gender);	
	getchar(); 
	printf("\n年龄:");
	scanf("%d",&customers[customerNum].age);
	getchar();
	printf("\n电话:");
	scanf("%s",customers[customerNum].phone);
	getchar();
	printf("\n邮箱:");
	scanf("%s",customers[customerNum].email);
	getchar();
	printf("---------------------添加完成---------------------");
	customerNum++;   // 这里必须,自增;否则会将上一个信息覆盖掉
}

// 根据输入的id,返回index,如果没有就返回-1。
int findIndex(int id){
	int index = -1;
	int i;
	for(i = 0; i < customerNum; i++){
		if(customers[i].id == id){ // 等于,就相当于找到了
			index = i;
		}
	}
	return index;
}

// 说明:
// 1.返回int,如果1就说明删除成功了
// 2.返回0,表示删除失败
// 3.接受的是要删除的客户id
int del(int id){  // 形参是要删除的id
	int index = findIndex(id);
	int i;
	if(index == -1){ // 说明该id没有对应的客户
		return 0;   // 表示删除失败
	}else{
		// 说明有对应的客户,就要删除,删除的本质就是将编号为id的这个客户移除
		// 1.从index + 1位置开始,整体前移
		for(i = index + 1; i < customerNum; i++){
			customers[i-1] = customers[i];	// 这里就是通过整体前移
			customers[i-1].id--;
			// 假如有5个客户要移除3,则经过函数findIndex得index=2,
		}
		// 2. customerNum - 1
		customerNum--;
		return 1;  // 1 表示删除成功
	}
}

// 显示删除客户的界面,然后调用
void delView(){
	int id = 0;
	char choice = ' ';
	printf("\n---------------------删除客户---------------------");
	printf("\n请选择待删除客户编号(-1退出):");
	scanf("%d",&id);
	getchar();
	if(id == -1){
		printf("\n删除未完成---------------------");
		return;
	}
	printf("\n确认是否删除(Y/N):");
	scanf("%c",&choice);
	getchar();
	if(choice == 'Y' || 'y'){
		if(del(id) == 0){
			printf("\n---------------------删除失败,因为id不存在---------------------");
		}else{
			printf("\n---------------------删除成功!---------------------");
		}
	}
}



// 显示客户信息列表
void listCustomer(){
	int i = 0;
	printf(" ---------------------------客户列表---------------------------");
	printf("\n编号\t姓名\t性别\t年龄\t电话\t邮箱");
	for(i = 0; i < customerNum; i++){  // 表示客户的编号,循环打印客户信息
		getCustomerInfo(&customers[i]);
	}
}

// 显示主菜单
void mainMenu(){
	do {
		printf("\n\n\n-----------------客户信息管理软件-----------------");
		printf("\n		1 添 加 客 户");
		printf("\n		2 修 改 客 户");
		printf("\n		3 删 除 客 户");
		printf("\n		4 客 户 列 表");
		printf("\n		5 退	   出");
		printf("\n请选择(1-5):");
		scanf("%c",&key);
		getchar();  // 过滤回车

		switch(key){
		case '1':
			add();
			break;
		case '2':
			printf("修改客户");
			break;
		case '3':
			delView();
			break;
		case '4':
			listCustomer();
			break;
		case '5':
			printf("退出");
			loop = 0;
			break;
		default:
			printf("\n你的输入有误,请重新输入");
			break;
		}
	}while(loop);
	printf("\n你退出了客户管理系统");
	getchar();
}

void main(){
	// 为了测试显示客户信息,我们可以先初始化一个客户,后面通过界面进行添加
	customers[0].id = 1;
	customers[0].age = 10;
	// 邮箱不可以直接像上面一样赋值
	// 原因:此时数组是个指针,指针指向元素首地址,这样的话赋值相当于修改地址,不可以
	// 需要用到拷贝的方法:如下
	strcpy(customers[0].email,"yy@sohu.com");
	customers[0].gender = 'f';
	strcpy(customers[0].name,"zs");
	strcpy(customers[0].phone,"110");

	mainMenu(); // 调用函数,显示菜单
}

二、简单分布图

image-20230324184828335

P 165 项目-CRM(7)-功能完善 2023/3/24

一、完善退出确认功能

功能说明:要求用户在退出时提示 " 确认是否退出(Y/N):",用户必须输入Y/N, 否则循环提示。

思路分析:

  1. 使用do-while循环,提示用户输入Y/N,户必须输入Y/N, 否则循环提示。
  2. 需要在增加一个全局变量choice,表示用户的选择。
char choice = ' ' ;  // 表示退出选择Y/N
  	  case '5':
			do{
				printf("确认是否退出(Y/N):");
				scanf("%c",&choice);
				getchar();
			}while(choice != 'Y'&& choice != 'N');   // 如果输入的不是Y,并且不是N
			// 退出while循环后一定输出的是Y或者N
			if(choice== 'Y' || choice== 'y' ){
				loop = 0;
			} // 如果输入的是N,不做处理,继续显示菜单
			break;
		default:
			printf("\n你的输入有误,请重新输入");
			break;
		}
	}while(loop);
	printf("\n你退出了客户管理系统");

二、完成修改客户的功能

思路分析:修改客户时,需要先查找该用户,如果用户不存在,就需要提示并结束修改,如果找到用户,就显示该用户信息,然后输入新的信息,id不能修改!

#include<stdio.h>
#include<string.h>

// 定义结构体数据类型 
struct Customer{
	int id; // 编号
	int age;  // 年龄
	char name[10]; // 名字
	char gender;  // f 表示女,m表示男
	char phone[16]; //  电话号码
	char email[20]; // 邮箱
};

int loop = 1;  // 控制是否退出主菜单
char key;
int customerNum = 1;  // 表示当前有多少个客户
char choice = ' ' ;  // 表示退出选择Y/N

// 定义客户结构体数组;数组显示多组数据
struct Customer customers[100];

// 显示一个Customer变量的信息
// 这里我们接收的是结构体指针,目的是提高效率
void getCustomerInfo(struct Customer * customer){
	printf("\n%d\t%s\t%c\t%d\t%s\t%s",(* customer).id,(* customer).name,(* customer).gender,(* customer).age,(* customer).phone,(* customer).email);
}

// 添加客户
void add(){
	customers[customerNum].id = customerNum + 1;  // 编号按照自增规则
	// 因为这里下标为0表示的是第一个人,下标为2表示的是第二个人,所以要这么写
	printf("\n---------------------添加客户---------------------");
	printf("\n姓名:");  //  一定要过滤回车,要不然就会被下面拿到回车
	scanf("%s",customers[customerNum].name);
	getchar();
	printf("\n性别:");
	scanf("%c",&customers[customerNum].gender);	
	getchar(); 
	printf("\n年龄:");
	scanf("%d",&customers[customerNum].age);
	getchar();
	printf("\n电话:");
	scanf("%s",customers[customerNum].phone);
	getchar();
	printf("\n邮箱:");
	scanf("%s",customers[customerNum].email);
	getchar();
	printf("---------------------添加完成---------------------");
	customerNum++;   // 这里必须,自增;否则会将上一个信息覆盖掉
}

// 根据输入的id,返回index,如果没有就返回-1。
int findIndex(int id){
	int index = -1;
	int i;
	for(i = 0; i < customerNum; i++){
		if(customers[i].id == id){ // 等于,就相当于找到了
			index = i;
		}
	}
	return index;
}

// 说明:
// 1.返回int,如果1就说明删除成功了
// 2.返回0,表示删除失败
// 3.接受的是要删除的客户id
int del(int id){  // 形参是要删除的id
	int index = findIndex(id);
	int i;
	if(index == -1){ // 说明该id没有对应的客户
		return 0;   // 表示删除失败
	}else{
		// 说明有对应的客户,就要删除,删除的本质就是将编号为id的这个客户移除
		// 1.从index + 1位置开始,整体前移
		for(i = index + 1; i < customerNum; i++){
			customers[i-1] = customers[i];	// 这里就是通过整体前移
			customers[i-1].id--;
			// 假如有5个客户要移除3,则经过函数findIndex得index=2,
		}
		// 2. customerNum - 1
		customerNum--;
		return 1;  // 1 表示删除成功
	}
}

// 显示删除客户的界面,然后调用
void delView(){
	int id = 0;
	char choice = ' ';
	printf("\n---------------------删除客户---------------------");
	printf("\n请选择待删除客户编号(-1退出):");
	scanf("%d",&id);
	getchar();
	if(id == -1){
		printf("\n删除未完成---------------------");
		return;
	}
	printf("\n确认是否删除(Y/N):");
	scanf("%c",&choice);
	getchar();
	if(choice == 'Y' || 'y'){
		if(del(id) == 0){
			printf("\n---------------------删除失败,因为id不存在---------------------");
		}else{
			printf("\n---------------------删除成功!---------------------");
		}
	}
}

// 显示修改客户函数
int update(int id){
	char key= ' ' ;
	int index = findIndex(id);
	if(index == -1){ // 说明该id没有对应的客户
		return -1;   // 表示修改失败
	}else{
		printf("\n1.姓名、2.姓别、3.年龄、4.电话、5.邮箱");
		printf("\n请选择需要修改信息的编号:");
		scanf("%c",&key);
		switch(key){
			// 这里会返回下标
		case '1':
			printf("\n姓名(原:%s):",customers[index].name);
			scanf("%s",customers[index].name);
			getchar();
			break;
		case '2':
			printf("\n姓别(原:%c):",customers[index].gender);
			scanf("%c",&customers[index].gender);
			getchar();
			break;
		case '3':
			printf("\n年龄(原:%d):",customers[index].age);
			scanf("%d",&customers[index].age);
			getchar();
			break;
		case '4':
			printf("\n电话(原:%s):",customers[index].phone);
			scanf("%s",customers[index].phone);
			getchar();
			break;
		case '5':
			printf("\n邮箱(原:%s):",customers[index].email);
			scanf("%s",customers[index].email);
			getchar();
			break;
		default:
			printf("\n你输入的有误");
			break;
		}
	}
}

// 修改客户界面
void updateView(){
	int num = 0;
	int back = 0;
	printf("\n请选择待修改客户编号(-1退出):");
	scanf("%d",&num);
	getchar();
	if(num == -1){
		return ;
	}else{
		back = update(num);
		if(back == -1 ){
			printf("\n---------------------修改失败,客户id不存在---------------------");
		}else{
			printf("\n---------------------修改成功---------------------");
		}
	}
}

// 显示客户信息列表
void listCustomer(){
	int i = 0;
	printf(" ---------------------------客户列表---------------------------");
	printf("\n编号\t姓名\t性别\t年龄\t电话\t邮箱");
	for(i = 0; i < customerNum; i++){  // 表示客户的编号,循环打印客户信息
		getCustomerInfo(&customers[i]);
	}
}

// 显示主菜单
void mainMenu(){
	do {
		printf("\n\n\n-----------------客户信息管理软件-----------------");
		printf("\n		1 添 加 客 户");
		printf("\n		2 修 改 客 户");
		printf("\n		3 删 除 客 户");
		printf("\n		4 客 户 列 表");
		printf("\n		5 退	   出");
		printf("\n请选择(1-5):");
		scanf("%c",&key);
		getchar();  // 过滤回车

		switch(key){
		case '1':
			add();
			break;
		case '2':
			updateView();
			break;
		case '3':
			delView();
			break;
		case '4':
			listCustomer();
			break;
		case '5':
			do{
				printf("确认是否退出(Y/N):");
				scanf("%c",&choice);
				getchar();
			}while(choice != 'Y'&& choice != 'N');   // 如果输入的不是Y,并且不是N
			// 退出while循环后一定输出的是Y或者N
			if(choice== 'Y' || choice== 'y' ){
				loop = 0;
			} // 如果输入的是N,不做处理,继续显示菜单
			break;
		default:
			printf("\n你的输入有误,请重新输入");
			break;
		}
	}while(loop);
	printf("\n你退出了客户管理系统");
	getchar();
}

void main(){
	// 为了测试显示客户信息,我们可以先初始化一个客户,后面通过界面进行添加
	customers[0].id = 1;
	customers[0].age = 10;
	// 邮箱不可以直接像上面一样赋值
	// 原因:此时数组是个指针,指针指向元素首地址,这样的话赋值相当于修改地址,不可以
	// 需要用到拷贝的方法:如下
	strcpy(customers[0].email,"yy@sohu.com");
	customers[0].gender = 'f';
	strcpy(customers[0].name,"zs");
	strcpy(customers[0].phone,"110");

	mainMenu(); // 调用函数,显示菜单
}

P 166 文件基本介绍 2023/3/24

一、基本介绍

介绍:文件,对我们并不陌生,文件是数据源(保存数据的地方)的一种,比如大家经常使用的word文档,txt文件,excel文件…都是文件。文件最主要的作用就是保存数据,它既可以保存一张图片,也可以保持视频,声音…

二、流

文件在程序中是以流的形式来操作的。

image-20230324203337130

**流:数据在数据源(文件)程序(内存)**之间经历的路径
**输入流:**数据从数据源(文件)到程序(内存)的路径
**输出流:**数据从程序(内存)到数据源(文件)的路径

image-20230324204310529

P167 C标准文件(输入输出) 2023/3/24

一、输入输出

  1. 当我们提到输入时,这意味着要向程序写入一些数据。输入可以是以文件的形式或从命令行中进行。C 语言提供了一系列内置的函数来读取给定的输入,并根据需要写入到程序中。
  2. 当我们提到输出时,这意味着要在屏幕上、打印机上或任意文件中显示一些数据。C 语言提供了一系列内置的函数来输出数据到计算机屏幕上和保存数据到文本文件或二进制文件(图片、声音、视频)中。

二、标准文件

  1. C 语言把所有的设备都当作文件。所以设备(比如显示器)被处理的方式与文件相同。以下三个文件会在程序执行时自动打开,以便访问键盘和屏幕。

image-20230325130759830

  1. 文件指针是访问文件的方式,我们会讲解如何从屏幕读取值以及如何把结果输出到屏幕上。

  2. C 语言中的 I/O (输入/输出) 通常使用 printf() 和 scanf() 两个函数。scanf() 函数用于从标准输入(键盘)读取并格式化, printf() 函数发送格式化输出到标准输出(屏幕)。

  3. 案例演示:

#include <stdio.h> // 执行 printf() 函数需要该库
int main()
{
printf("hello"); //显示引号中的内容
return 0;
}

P 168 文件读写三组函数 2023/3/25

一、getchar() & putchar() 函数

  1. int getchar(void) 函数从屏幕读取下一个可用的字符,并把它返回为一个整数。这个函数在同一个时间内只会读取一个单一的字符。您可以在循环内使用这个方法,以便从屏幕上读取多个字符。
  2. int putchar(int c) 函数把字符输出到屏幕上,并返回相同的字符。这个函数在同一个时间内只会输出一个单一的字符。您可以在循环内使用这个方法,以便在屏幕上输出多个字符。
  3. 应用实例:程序会读取一个单一的字符:
#include <stdio.h>
int main( )
{
	int c;
	printf( "Enter a value :");
	c = getchar( );  // 读取一个char,返回一个int

	printf( "\nYou entered: ");
	putchar( c );  // 可以在屏幕上显示
	printf( "\n");
	getchar();   // 过滤回车
	getchar();  // 暂停
	return 0;
}

image-20230325132457821

二、gets() & puts() 函数

  1. char *gets(char *s) 函数从 stdin 读取一行到 s 所指向的缓冲区,直到一个终止符或 EOF
  • gets函数类似于scanf函数,用于读取标准输入。
    • 前面我们已经知道scanf函数在读取字符串时遇到空格就认为读取结束,所以当输入的字符串存在空格时,我们需要使用gets函数进行读取。
  • gets函数从STDIN(标准输入)读取字符并把它们加载到str(字符串)中,直到遇到换行符(\n)。
    • 我们输入"how are you",共11个字符,可以看到gets会读取空格,同时可以看到我们并未给数组进行初始化赋值,但是最后有’\0’,这是因为gets遇到\n后,不会存储\n,而是将其翻译为空字符’\0’
  1. int puts(const char *s) 函数把字符串 s 和一个尾随的换行符写入到 stdout。
  • 函数puts把str(字符串)写入STDOU(标准输出)。
    • puts会将数组c中存储的"how are you"字符串打印到屏幕上,同时打印换行,相对于printf函数,puts只能用于输出字符串,同时多打印一个换行符,等价于printf(%s\n",c)
  1. 应用实例: 程序读取一整行直到该行结束。
#include <stdio.h>
int main( )
{
	char str[100];  // 字符数组
	printf( "输入字符串:");
	gets( str );

	printf( "\n你刚才输入的字符串是: ");
	puts( str );  //  把刚刚接收到的字符串返回回来显示一遍
	getchar();
	return 0;
}

image-20230325134723184

三、scanf() 和 printf() 函数

  1. int scanf(const char *format, ...) 函数从标准输入流 stdin 读取输入,并根据提供的 format 来浏览输入。
  2. int printf(const char *format, ...) 函数把输出写入到标准输出流 stdout ,并根据提供的格式产生输出。
  3. format 可以是一个简单的常量字符串,但是您可以分别指定 %s、%d、%c、%f 等来输出或读取字符串、整数、字符或浮点数。还有许多其他可用的格式选项,可以根据需要使用。如需了解完整的细节,可以查看这些函数的参考手册。现在让我们通过下面这个简单的实例来加深理解。
  4. 应用实例:您输入一个文本并按下回车键时,程序读取输入, 但是要求格式要匹配。
#include <stdio.h>
int main( ) {
	char str[100];
	int i;
	printf( "Enter a value :");
	scanf("%s %d", str, &i);
	printf( "\nYou entered: %s %d ", str, i);
	printf("\n");
	getchar();
	getchar();
	return 0;
}

P 169 fopen和fclose及模式 2023/3/25

一、C文件读写

  1. 讲解了 C 语言处理的标准输入和输出设备。我们将介绍 如何创建、打开、关闭文本文件或二进制文件。
  2. 一个文件,无论它是文本文件还是二进制文件,都是代表了一系列的字节。C 语言不仅提供了访问顶层的函数,也提供了底层(OS)调用来处理存储设备上的文件。本章将讲解文件管理的重要调用:

二、打开文件 fopen

  1. 使用 fopen( ) 函数来创建一个新的文件或者打开一个已有的文件,这个调用会初始化类型 FILE 的一个对象,类型 FILE 包含了所有用来控制流的必要的信息。下面是这个函数

    调用的原型:FILE *fopen( const char * filename, const char * mode );就是打开文件相应的指针。

    • 说明:在这里,filename 是字符串,用来命名文件,访问模式 mode 的值可以是下列值中的一个。
    • 如果处理的是二进制文件(图片,视频…),则需使用下面的访问模式:"rb", "wb", "ab", "rb+", "r+b", "wb+", "w+b", "ab+", "a+b"
模式描述
r打开一个已有的文本文件,允许读取文件。
w打开一个文本文件,允许写入文件。如果文件不存在,则会创建一个新文件。
在这里,您的程序会从文件的开头写入内容。如果文件存在,则该会被截断为
零长度,重新写入!!!。
a打开一个文本文件,以追加模式写入文件。如果文件不存在,则会创建一个新
文件。在这里,您的程序会在已有的文件内容中追加内容。
r+打开一个文本文件,允许读写文件。(文件会被截取为0长度)
w+打开一个文本文件,允许读写文件。如果文件已存在,则文件会被截断为零长
度,如果文件不存在,则会创建一个新文件。
a+打开一个文本文件,允许读写文件。如果文件不存在,则会创建一个新文件。
读取会从文件的开头开始,写入则只能是追加模式。

三、关闭文件 fclose

关闭文件,使用 fclose( ) 函数。函数的原型如下:int fclose( FILE *fp );

  1. 如果成功关闭文件,fclose( ) 函数返回零,如果关闭文件时发生错误,函数返回 EOF。这个函数实际上,会清空缓冲区中的数据,关闭文件,并释放用于该文件的所有内存。EOF 是一个定义在头文件 stdio.h 中的常量。
  2. C 标准库提供了各种函数来按字符或者以固定长度字符串的形式读写文件。
  3. 使用完文件后(读,写),一定要将该文件关闭。

P 170 写文件和注意事项 2023/3/25

一、写入文件 fputs

下面是把字符写入到流中的函数:int fputc( int c, FILE \*fp );

  • 说明:函数 fputc() 把参数 c 的字符值写入到 fp 所指向的输出流中。如果写入成功,它会返回写入的字符,如果发生错误,则会返回 EOF。您可以使用下面的函数来把一个以 null 结尾的字符串写入到流中:int fputs( const char *s, FILE *fp );
#include<stdio.h>
void main(){
	// 创建文件指针
	FILE *fp = NULL;

	// 打开改文件
	fp = fopen("e:/ctest.txt","r+"); // w+模式是,文件会被阶段为0长度
	// 将内容写入到文件中
	fprintf(fp,"你好 北京~~\n");
	fputs("你好 上海~~\n",fp);

	// 关闭文件!!! 如果不关闭文件,将不会保存到我们的文件中
	fclose(fp);
	printf("创建,写入信息完成"); 
	getchar();
}

image-20230325152214248

P 171 读文件和注意事项 2023/3/25

一、读取文件 fgets

下面是从文件读取单个字符的函数:int fgetc( FILE * fp );

  • 说明:fgetc() 函数从 fp 所指向的输入文件中读取一个字符。返回值是读取的字符,如果发生错误则返回 EOF
  • 下面的函数从流中读取一个字符串:char *fgets( char *buf, int n, FILE *fp );
    1. 说明:函数 fgets() 从 fp 所指向的输入流中读取 n - 1 个字符。它会把读取的字符串复制到缓冲区 buf,并在最后追加一个 null 字符来终止字符串。如果这个函数在读取最后一个字符之前就遇到一个换行符 ‘\n’ 或文件的末尾 EOF,则只会返回读取到的字符,包括换行符。
    2. 也可以使用 int fscanf(FILE *fp, const char *format, …) 函数来从文件中读取字符串,但是在遇到第一个空格字符时,它会停止读取
#include<stdio.h>
void main(){

		// 创建一个文件指针
	FILE *fp = NULL;
	// 定义一个缓冲区
	char buff[1024];
	// 打开文件
	fp = fopen("e:/ctest100.txt","r");
	
	// 方法1:
	//fscanf(fp,"%s",buff);  //  将fp所指向的文件里面读一行到buff里面去
	 输出
	//printf("%s\n",buff);
	
	// 方法2:读取整个文件
	while(fgets(buff,1024,fp)!=NULL){  // 一行读取1024
		// 读取整个文件,使用while循环,读取到空的基结束
		printf("%s",buff);
	}
	fclose(fp);  // 关闭文件
	getchar();
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2219567.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

计算机组成原理(笔记7高速缓冲存储器Cache,计算机组成原理的重难点全、直接、组相连)

为什么要设立高速缓冲存储器 &#xff08;Cache&#xff09;&#xff1f; Cache是介于CPU和主存之间的小容量存储器&#xff0c;存取速度比主存快。它能高速地向CPU提供指令和数据&#xff0c;加快程序的执行速度。它是为了解决CPU和主存之间速度不匹配而采用的一项重要技术。…

unity静态批处理

unity静态批处理 静态批处理要求和兼容性渲染管线兼容性 使用静态批处理在构建时进行静态批处理在构建时执行静态批处理的步骤&#xff1a; 在运行时进行静态批处理性能影响 静态批处理 静态批处理是一种绘制调用批处理方法&#xff0c;它将不移动的网格组合在一起&#xff0c…

【HarmonyOS NEXT】权限申请及应用设置页跳转

关键词&#xff1a;鸿蒙、程序访问控制、定位、应用详情页、startability、want 在app开发过程中&#xff0c;常进行系统权限的申请以提供设备访问或个性化功能&#xff08;如扫一扫、城市定位、剪贴板等&#xff09;&#xff0c;从而保障应用功能的完整性&#xff0c;那么本期…

mov 转 mp4

1. 下载 ffmpeg 下载链接 Tags GyanD/codexffmpeg GitHub 下载 windos 精简版 解压 &#xff08;里面的mov文件和mp4文件是我后面自己加的&#xff09; 2. 转换 转换命令 ffmpeg -i 5.mov -c:v libx264 -c:a aac 5.mp4 其中 5.mov 是源文件路径 5.mp4是目标路径 使用lib…

计算机毕业设计 零食批发商仓库管理系统的设计与实现 Java+SpringBoot+Vue 前后端分离 文档报告 代码讲解 安装调试

&#x1f34a;作者&#xff1a;计算机编程-吉哥 &#x1f34a;简介&#xff1a;专业从事JavaWeb程序开发&#xff0c;微信小程序开发&#xff0c;定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事&#xff0c;生活就是快乐的。 &#x1f34a;心愿&#xff1a;点…

智发展 智飞跃 亚信安全与新华三深化战略合作

10月16日&#xff0c;亚信安全与新华三集团共同宣布&#xff0c;双方正式签署战略合作协议&#xff0c;双方将基于各自在硬件及软件安全领域的能力和优势&#xff0c;在产品、解决方案、市场拓展等多个领域深入合作&#xff0c;赋能千行百业数字化转型与变革。 亚信安全CEO马红…

跨域问题及常用的5种解决方案

1.什么是跨域问题&#xff1f; 跨域问题通常指的是在浏览器中由于同源策略的限制而产生的问题。同源策略&#xff08;Same-origin policy&#xff09;是浏览器的一种安全措施&#xff0c;它要求请求的域名、协议和端口必须与提供资源的网站相同。当一个网页尝试访问另一个来源…

【算法】C++中的二分查找

&#x1f4e2;博客主页&#xff1a;https://blog.csdn.net/2301_779549673 &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff01; &#x1f4e2;本文由 JohnKi 原创&#xff0c;首发于 CSDN&#x1f649; &#x1f4e2;未来很长&#…

wifi、热点密码破解 - python

乐子脚本&#xff0c;有点小慢&#xff0c;试过多线程&#xff0c;系统 wifi 连接太慢了&#xff0c;需要时间确认&#xff0c;多线程的话系统根本反应不过来。 也就可以试试破解别人的热点&#xff0c;一般都是 123456 这样的傻鸟口令 # coding:utf-8 import pywifi from pyw…

初识git · 基本操作

目录 前言&#xff1a; 基本操作 检查是否存在git 初始化仓库 认识三个区域 添加文件 查看.git文件 修改文件 版本回退 撤销操作 删除文件 我的博客即将同步至腾讯云开发者社区&#xff0c;邀请大家一同入驻&#xff1a;https://cloud.tencent.com/developer/suppor…

Qt-多线程

1. Qt 多线程概述 Qt 默认只有一个主线程&#xff0c;该线程既要处理窗口移动&#xff0c;又要处理各种运算。 当要处理的运算比较复杂时&#xff0c;窗口就无法移动&#xff0c;所以在处理程序时在很多情况下都需要使用多线程来完成。 示例&#xff1a;移动窗口和复杂循环 …

八股面试2(自用)

mysql存储引擎 存储引擎&#xff1a;定义数据的存储方式&#xff0c;以及数据读取的实现逻辑 在以前数据库5.5默认MyISAM引擎&#xff0c;之后默认InnoDB引擎 MyISAM引擎的数据和索引是分开存储的&#xff0c;InnoDb将索引和文件存储在同一个文件。 MyISAM不支持事务&#…

SPOOLing技术详解,结合实际场景让你了解什么是假脱机技术。

SPOOLing技术 ​ 在手工操作阶段&#xff0c;主机直接从I/O设备获取数据&#xff0c;但是由于设备速度很慢&#xff0c;主机速度很快。人机速度矛盾明显&#xff0c;主机需要浪费很多时间来等待设备。 什么是脱机技术&#xff0c;脱机技术可以解决什么问题&#xff1f; 所谓脱…

大数据测试:Charles修改响应数据

上一篇大数据测试&#xff1a;Fiddler修改响应数据-CSDN博客 &#xff0c;有同学反馈有没有Charles的方式修改响应数据&#xff0c;本篇就是Charles修改数据操作步骤&#xff0c;相比较fiddler&#xff0c;Charles相对简单&#xff0c;便捷&#xff0c;我很喜欢 1、背景&…

【笔记】【YOLOv10图像识别】自动识别图片、视频、摄像头、电脑桌面中的花朵学习踩坑

&#xff08;一&#xff09;启动 创建环境python3.9 打开此环境终端 &#xff08;后面的语句操作几乎都在这个终端执行&#xff09; 输入up主提供的语句&#xff1a;pip install -r requirements.txt 1.下载pytorch网络连接超时 pytorch网址&#xff1a; Start Locally | P…

java -jar 命令自动重启 Java 项目

一、java -jar 方式运行项目 重启Java项目通常意味着你需要先停止当前运行的Java进程&#xff0c;然后再次启动它。下面是在CentOS上执行这些步骤的一种常见方法&#xff1a; 停止Java进程 找到Java进程的PID&#xff1a; 使用ps命令配合grep来查找运行中的Java进程的PID&#…

【Java SE 】封装 的特性 和 static 详解

&#x1f525;博客主页&#x1f525;&#xff1a;【 坊钰_CSDN博客 】 欢迎各位点赞&#x1f44d;评论✍收藏⭐ 目录 1. 封装的概念 1.1 一个例子 2. 访问权限控制符 3. 包的概念 3.1 import 导入 3.2 常见的包 4. static 静态成员 4.1 static 使用情况 4.2 static 修…

> Invalid revision: 3.22.1-g37088a8-dirty

Android项目使用cmake 3.22.1&#xff0c;编译时报错&#xff1a; > Invalid revision: 3.22.1-g37088a8-dirty解决方法一&#xff1a; 升级Gradle版本和AGP的版本&#xff1b; 建议使用AS推荐的版本&#xff1a; 目前可运行的版本配置&#xff1a; AS&#xff1a;Jel…

champ模型部署指南

一、介绍 champ是由阿里巴巴、复旦大学和南京大学的研究人员共同提出的一种基于3D的将人物图片转换为视频动画的模型&#xff0c;该方法结合了3D参数化模型(特别是SMPL模型)和潜在扩散模型&#xff0c;能够精确地捕捉和再现人体的3D形状和动态&#xff0c;同时保持动画的时间一…

读书读到NOBEL

最近在读陈逸鹤的《程序员的自我修养》这本书&#xff0c;里面有这么一段话&#xff1a; “远古时代的人们只能创造出用于猎捕的长矛&#xff0c;而今天借助来自各行各业人 们的智慧&#xff0c;我们可以制造出高铁、大型飞机&#xff0c;并探索宇宙。但要更进一步解决人类所面…