C++复习

目录 

一、删除文件,文件改名函数

二、察看文件大小

1.不打开文件

2.打开文件察看文件大小

 

三、linux和windows下文件的区别

四、刷新缓冲区

五、函数调用模型(调用惯例)

​编辑

六、宏函数的特点

七、函数调用的变量 

 八、内存存放方向

九、指针步长的两个作用

十、malloc和calloc

十一、sscanf函数

十二、配置文件读写案例

十三、文件的加密和解密 


 

 

一、删除文件,文件改名函数


	int ret = rename("copy.txt" , "copy2.avi");  //旧名 ,  新名
	int ret = remove("paste.txt");

两者都是成功返回0,失败返回-1;

 

二、察看文件大小

1.不打开文件

下图是linux下的结构体,windows下可能稍有不同。

8bdbb84c03bb4c1cb49362bb1b496e4f.png

 

3775af96661f4690b1f3a1d5665f76e0.png

2.打开文件察看文件大小

 

`ftell` 是一个标准库函数,用于获取文件流指针的当前位置(即指针相对于文件开头的偏移量)。

具体用法如下


long ftell(FILE *stream);

`ftell` 函数接受一个文件流指针 `stream` 作为参数,并返回一个 `long` 类型的值,表示当前指针位置相对于文件开头的偏移量。

请注意,`ftell` 函数返回的值是相对于文件开头的偏移量,以字节为单位。如果发生错误,`ftell` 函数将返回一个特殊的值 `EOF`。

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>


int main()
{
	FILE *fp = fopen("abc.c" , "r");
	
	fseek(fp , 0 , SEEK_END);
	int len = ftell(fp);
	printf("文件大小:[%d]\n",len);   //60
	 
	fclose(fp);

    return 0 ;
}


三、linux和windows下文件的区别

aacd9b40a7d94f5dbc093ded39e44aca.png

 

 

 

 

四、刷新缓冲区

就是指把缓冲区的数据放到输入设备或者输出设备里。

65da441f63f5461b9d26796b2134011a.png

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>

 
int main()
{
	FILE *fp = fopen("abc.c" , "w+");
	if(fp == NULL){
		perror("open error");
		return;
	}
	char ch = 0;

	while(1){
		scanf("%c" , &ch);
		
		fflush(fp);
		if(ch == ':'){
			break;
		}
		fputc( ch , fp);
	}
	
	fclose(fp);

    return 0 ;
}

 016aa64d652a44d7b475e6f64b13ea95.png

 

 

五、函数调用模型(调用惯例)

主调函数与被调函数之间统一的约定,成为调用惯例。

573f3deb20f54d69aedf2d18cec68184.png

 

六、宏函数的特点

d131f6b98937442183a985d663f63076.png

 

七、函数调用的变量 

4047ad1db11046bbbef6b0606e1dd8b1.png

 

 八、内存存放方向

小端对齐

#include <stdio.h>

void test01(){
	int a = 0x11223344;
	char *p = (char *)&a;
	
	printf("%x\n" , *p);		//44  低位字节数据  低地址
	printf("%x\n" , *(p+1));	//33  高位字节数据  高地址
}
 
int main(){
	test01();
} 

 3ada8ad026fd4cd8a42cebfb5bc63826.png

 

 

九、指针步长的两个作用

 

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stddef.h>	//offserof 的 头文件 

//指针步长 代表 解引用后,解出的字节数量 
void test01(){
	char buf[1024] = {0};
	int a = 1000;
	
	memcpy(buf+1 , &a , sizeof(int)); //dst arc size
	
	char *p = buf;
	printf("%d\n" , *(int *)(p+1)); //1000
}

//指针步长 代表 指针+1后跳跃的字节数 
void test02(){
	char *p = NULL;
	printf("%d\n" , p);		//0
	printf("%d\n" , p+1);	//1
	
	double *p2 = NULL;
	printf("%d\n" , p2);	//0
	printf("%d\n" , p2+1);	//8
}

//步长练习 , 自定义数据类型练习 
struct Person{
	char a;	//0~3
	int b;	//4~7
	char buf[64];	//8~71
	int d;	//72~75
}; 

void test03(){
	struct Person p = {'a' , 10 , "hello world" , 20};
	
	printf("d属性的偏移量:%d\n" , offsetof(struct Person , d)); //72
	//返回成员变量d在结构体Person起始地址的偏移量。
	//offsetof宏用于处理底层的内存操作,如在结构体中访问特定位置的数据。
	//返回前面三个成员变量所占用的字节数之和,表示成员变量d相对于结构体起始地址的偏移量。
	
	printf("d属性的值为:%d\n" , *(int *)((char *)&p+72));  //20
}

int main(){
	test03();	
} 

 

十、malloc和calloc

b08a9d5b644b412499518c4db4f4db13.png

 

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

int *p = NULL;

void test01(){
	p = (int *)calloc(10 , sizeof(int));
	p[0] = 1;
	p[1] = 2;
} 

int main(){
	test01();
	for(int i=0; i<4; i++){
		printf("p[%d] == [%d]\n" , i , p[i]);
	}
	
	return 0;
} 

p[0] == [1]
p[1] == [2]
p[2] == [0]
p[3] == [0]

 

f961888f28cd4dfe94e2045e8c1d40f7.png

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

int *p = NULL;

void test01(){
	p = (int *)calloc(10 , sizeof(int));
	p[0] = 1;
	p[1] = 2;
	
//	for(int i=0; i<4; i++){
//		printf("p[%d] == [%d]\n" , i , p[i]);
//	}

	printf("%d\n",p);
} 

void test02(){
	p = (int*)realloc(p , sizeof(int)*20);
	
	for(int i=0; i<20; i++){
		printf("p[%d] == [%d]\n" , i , p[i]);
	}
	printf("%d\n",p);
} 

int main(){
	test01();
	test02();
	
	return 0;
} 

7738336
p[0] == [1]
p[1] == [2]
p[2] == [0]
p[3] == [0]
p[4] == [0]
p[5] == [0]
p[6] == [0]
p[7] == [0]
p[8] == [0]
p[9] == [0]
p[10] == [-1191182151]
p[11] == [28457]
p[12] == [7733584]
p[13] == [0]
p[14] == [7763376]
p[15] == [0]
p[16] == [1634887535]
p[17] == [1766203501]
p[18] == [544433516]
p[19] == [909670440]
7738336 

 

f95cfe71678f4f57847eb956161ae7bd.png

 

 0d9e85c4979f4a5c91527f0aaa4ac771.png

 

十一、sscanf函数

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

void test01(){
	char *str = "12345abcde";
	char buf[1024] = {0};
	memset(buf , 0 , sizeof(buf));
	sscanf(str , "%*d%s" ,buf);		//忽略数字 
//	printf("%s\n",buf);		//abcde 
	
//	str = "abcde 12345";		//遇到空格或者\t都代表忽略结束。
	str = "abcde12345"; 
	memset(buf , 0 , sizeof(buf));
	sscanf(str , "%*[a-z]%s" ,buf);		//把a-z都忽略 
	printf("%s\n",buf);	
	
	str = "abcdea12345"; 
	memset(buf , 0 , sizeof(buf));
	sscanf(str , "%6s" ,buf);	//取前6个字符 
	printf("%s\n",buf);		//abcdea
	
	sscanf(str , "%[a-c]" ,buf);	//取a-c
	printf("%s\n",buf);		//abc
	
	
	str = "1234aB5e"; 
	memset(buf , 0 , sizeof(buf));
	sscanf(str , "%[0-9]" ,buf);	//取数字 
	printf("%s\n",buf);		//1234
	
	sscanf(str , "%*d%[aBc]" ,buf);	//取a或B或c 
	printf("%s\n",buf);		//aB
	
	sscanf(str , "%[^5]" ,buf);	//取非5
	printf("%s\n",buf);		//1234aB 
	
	sscanf(str , "%[^b-z]" ,buf);	//取非a-z
	printf("%s\n",buf);		//1234aB5
	
	 
}

void test02(){
	char str[100] = "127.0.0.1";
	int n1,n2,n3,n4;
	sscanf(str , "%d.%d.%d.%d" , &n1 , &n2 , &n3 , &n4);
	printf("[%d][%d][%d][%d]",n1,n2,n3,n4); //[127][0][0][1]
	
}

void test03(){
	char str[100] = "anasd#holo@123";
	char buf[1024];
	sscanf(str , "%*[^#]#%[^@]" , buf);  //holo
	printf("%s\n" , buf);
	
	strcpy(str , "helloworld@holo.cn") ;
	char buf1[1024] , buf2[1024];
	sscanf(str , "%[^@]%*@%s" , buf1 , buf2);
	printf("[%s]\n[%s]" , buf1 , buf2);  //[helloworld]  [holo.cn]
 
}

int main(){
	test03();
	return 0;
} 

十二、配置文件读写案例

config.txt

#英雄ID 注释
heroId:1
#英雄姓名
heroName:亚瑟
#英雄攻击力
heroAtk:1000
#英雄防御力
heroDef:1000
#英雄简介
heroInfo:前排坦克


 config.c

这段代码是一个简单的配置文件解析程序。它读取指定文件中的文本内容,解析出配置项的键值对,并提供根据键获取值的功能。

下面是代码的主要功能解释:

  1. 定义了一个结构体 ConfigInfo,用于存储配置项的键值对。
  2. isVaildLines 函数用于判断一行文本是否是有效配置项。如果该行中包含 : 字符,则认为是有效配置项,返回 1;否则返回 0。
  3. getFileLines 函数用于获取指定文件中的有效配置项的行数。它打开文件,逐行读取文本内容,并调用 isVaildLines 函数判断每一行是否是有效配置项。
  4. parseFile 函数用于解析文件内容,提取有效配置项的键值对。它首先根据行数动态分配存储配置项的内存空间,然后打开文件,逐行读取文本内容,使用 strchr 函数找到键值分隔符 :,并使用 strncpy 函数将键和值分别复制到对应的结构体成员中。
  5. getInfoByKey 函数用于根据键获取对应的值。它遍历配置项数组,逐个比较键是否匹配,如果找到匹配的键,则返回对应的值;如果没有找到匹配的键,则返回 NULL。
  6. freeConfigInfo 函数用于释放配置项数组占用的内存。它接收一个 ConfigInfo 结构体数组的指针,并使用 free 函数释放内存,并将指针置为 NULL。
  7. 在 main 函数中,首先获取配置文件的有效行数,然后调用 parseFile 函数解析文件内容,将解析结果存储在 configInfo 结构体数组中。接着通过调用 getInfoByKey 函数,根据键获取对应的值,并打印出来。最后调用 freeConfigInfo 函数释放内存。

这段代码适用于读取配置文件,提取配置项的键值对,并根据键获取对应的值。

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <stdlib.h>
#include <Windows.h>

using namespace std;

struct ConfigInfo{
	char key[32];
	char value[32];
};

int isVaildLines(char *str){
	if(strchr(str,':') == NULL){
		return 0;
	}else{
		return 1;
	}
}

//获取文件的有效行数 
int getFileLines(char * filePath){
	FILE *fp = fopen(filePath , "r");
	if(fp == NULL){
		perror("fopen error");
		return -1;
	}	
	int lines = 0;
    char buf[1024] = {0};
	while(fgets(buf , 1024 , fp) != NULL){
		if(isVaildLines(buf) == 1){
			lines++;
		}		
		memset(buf , 0 , sizeof(buf));
	}
	
	fclose(fp);
	return lines;
}	


//解析文件
void parseFile(char *filePath , int lines , struct ConfigInfo ** configInfo){
	struct ConfigInfo * info = (struct ConfigInfo * )malloc(sizeof(struct ConfigInfo) * lines);
	
	if(info == NULL){
		return;
	}
	
	FILE *fp = fopen(filePath , "r");
	if(fp == NULL){
		perror("fopen error");
		return;	
	}
	
	char buf[1024] = {0};
//	int Vaild = 0;
	int index = 0;
	while(fgets(buf , 1024 , fp) != NULL){
		if(isVaildLines(buf) == 1){
//			lines++;
			
			memset(info[index].key , 0 , sizeof(info[index].key) );
			memset(info[index].value , 0 , sizeof(info[index].value) );
			
			char *pos = strchr(buf , ':');
			
		/*
			sscanf(buf , "%[^:]%*:%s" , info[index].key , info[index].value);*/
			
			strncpy(info[index].key , buf , pos - buf);
			strncpy(info[index].value , pos+1 , strlen(pos+1)-1);
//			strcpy(info[index].value , pos+1);
			
			index++;
		}
			memset(buf , 0 , sizeof(buf));
	}
	*configInfo = info;
} 

char * getInfoByKey(char * key , struct ConfigInfo * configInfo , int lines){
	for(int i=0; i<lines; i++){
		if(strcmp(key , configInfo[i].key) == 0){
			return configInfo[i].value;
		}
	}
	return NULL;
}


void freeConfigInfo(struct ConfigInfo *configInfo){
	if(configInfo != NULL){
		free(configInfo);
		configInfo = NULL;
	}
}

int main(){
	char *filePath = (char *)"./config.txt";
	
	int lines = getFileLines(filePath);
	printf("有效行数为:[%d]\n",lines);
	
	
	struct ConfigInfo * configInfo = NULL;
	parseFile(filePath , lines , &configInfo);
	
	printf("heroId = [%s]\n" , getInfoByKey("heroId" , configInfo , lines));
	printf("heroName = [%s]\n" , getInfoByKey("heroName" , configInfo , lines));
	printf("heroAtk = [%s]\n" , getInfoByKey("heroAtk" , configInfo , lines));
	printf("heroDef = [%s]\n" , getInfoByKey("heroDef" , configInfo , lines));
	printf("heroInfo = [%s]\n" , getInfoByKey("heroInfo" , configInfo , lines));
	
	
	//释放
	freeConfigInfo(configInfo); 
	configInfo = NULL;
	return 0;
}

有效行数为:[5]
heroId = [1]
heroName = [亚瑟]
heroAtk = [1000]
heroDef = [1000]
heroInfo = [前排坦克]

 

十三、文件的加密和解密 

 

这段代码实现了文件的加密和解密操作。

codeFile 函数用于对源文件进行加密,并将加密后的内容写入目标文件。具体步骤如下:

  1. 使用 srand(time(0)) 设置随机数种子,以确保每次运行生成不同的随机数序列。
  2. 打开源文件和目标文件,如果文件打开失败则输出错误信息并返回。
  3. 使用 fgetc 函数从源文件中逐个字符读取,将字符转换为 short 类型的整数。
  4. 将读取的 short 类型整数左移 4 位,并将最高位设置为 1(即二进制的 1000000000000000)。
  5. 通过 rand() % 16 生成一个范围在 0 到 15 之间的随机数,并加到 short 类型整数上。
  6. 使用 fprintf 函数将加密后的整数转换为字符串并写入目标文件。
  7. 关闭源文件和目标文件。

decodeFile 函数用于对加密文件进行解密,并将解密后的内容写入目标文件。具体步骤如下:

  1. 打开加密文件和目标文件,如果文件打开失败则输出错误信息并返回。
  2. 使用 fscanf 函数从加密文件中按照 %hd 格式读取一个 short 类型的整数。
  3. 将读取的 short 类型整数左移 1 位,然后右移 5 位,将高位的加密标记位移除。
  4. 将解密后的 short 类型整数转换为 char 类型,并使用 fputc 函数将其写入目标文件。
  5. 循环执行步骤 2-4 直到加密文件的末尾。
  6. 关闭加密文件和目标文件。

需要注意的是,这段代码使用简单的位操作进行加密和解密,并不是强大的加密算法。它只是给出了一个简单的示例来演示文件加密和解密的基本原理。在实际应用中,需要使用更加复杂和安全的加密算法来保护敏感数据的安全性。


void codeFile(char *sourceFilePath,char *destFilePath){
	srand(time(0));
	FILE *fp_r = fopen(sourceFilePath , "r");
	FILE *fp_w = fopen(destFilePath , "w");
	
	if(fp_r == NULL || fp_w == NULL){
		perror("fopen error");
		return;
	}
	char ch;
	while((ch = fgetc(fp_r)) != EOF){
		short temp = (short)ch;
		temp = temp << 4;
		temp = temp | 0x8000;
		temp += rand() % 16;	//0~15
//		printf("%d\n",temp);
		fprintf(fp_w , "%hd" , temp);
	}
	
	
	fclose(fp_w);
	fclose(fp_r);
} 

void decodeFile(char *sourceFilePath , char *destFilePath){
	FILE *fp_r = fopen(sourceFilePath , "r");
	FILE *fp_w = fopen(destFilePath , "w");
	
	if(fp_r == NULL || fp_w == NULL){
		perror("fopen error");
		return;
	}
	
	short temp;
	char ch;
	while((!feof(fp_r))){   //用short读 
		fscanf(fp_r , "%hd" , &temp);
		
		temp <<= 1;
		temp >>= 5;
		ch = (char)temp;
		fputc(ch , fp_w);
	}
	
	fclose(fp_r);
	fclose(fp_w);
}

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值