C提高5 高级结构体 文件操作

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C提高5 高级结构体 文件操作相关的知识,希望对你有一定的参考价值。


1,昨天的作业题经典C语言题型

1将全局区二维字符拷贝到堆中

2将栈区二维字符拷贝到堆中

3合并栈区与全局区的二维字符数组

4把数组排序

5打印堆区的二维数组

6释放堆空间

[email protected]:~/high$ cat main.c 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/**********	释放二级指针方式1,只释放堆中内存	********/
void free_two_level_pointer01(char **p,int num)
{
	if(p == NULL) return ;
	int i =0;
	for(i = 0;i<num;i++)
	{
		if(p[i] != NULL)
		{
			free(p[i]);
			p[i] = NULL;
		}
	}
	free(p);
}

/**********	释放二级指针方式2,只释放堆中内存,同时修改实参的值	********/
void free_two_level_pointer02(char ***p,int count)
{
	int num = 0;
	if(p == NULL) return ;
	int i;
	for(i = 0;i<count;i++)//先释放几个子串的空间
	{
		if(*(p) + i != NULL)
		{
			printf("%d 正在释放 %p \n",++num,*( *(p) + i)  );
			free(*( *(p) + i));
			*( *(p) + i) = NULL;
		}
	}
	if(*p != NULL)//再释放存放子串数目的空间
	{
		printf("%d 正在释放 %p \n",++num, *(p)  );
		free(*p);
		*p = NULL;
	}
	return ;
}


int sort(char **myp1,int len1,char (*myp2)[30],int len2,char ***myp3,int *len3)
{
	if(myp1 == NULL) return -1;
	if(myp2 == NULL) return -2;
	if(myp3 == NULL) return -3;
	int i =0;
	int j =0;
	char **p3 = NULL;
	p3 = (char **)malloc((len1 + len2) * sizeof(char *));//注意这里面装的是指针
	if(p3 == NULL)
	{
		return -4;
	}
	//把全局区的字符拷贝到堆区
	for(i =0;i<len1;i++)
	{
		int tmp_len = strlen(myp1[i]) +1;
		p3[i] = (char *)malloc(tmp_len * sizeof(char));
		if(p3 == NULL)
		{
               		return -4;
        	}
		strcpy(p3[i],myp1[i]);
	}

	//把栈区的字符拷贝到堆区
	for(j =0;j<len2;j++,i++)
	{
		int tmp_len = strlen(myp2[i]) +1;
		p3[i] = (char *)malloc(tmp_len * sizeof(char));
		if(p3 == NULL)
		{
               		return -4;
        	}
		strcpy(p3[i],myp2[j]);
	}

	//把结果传回去
	*len3 = len1 + len2;

	//排序  指针
	for(i = 0;i<len1 + len2;i++)
	{
		for(j = i+1;j<len1 + len2;j++)
		{
			if( strcmp(p3[i],p3[j]) >  0 )
			{
				char *tmp_p = p3[i];
				p3[i] = p3[j];
				p3[j] = tmp_p;
			}	
		}
	}
	//把结果传回去
	*myp3 = p3;
	return 0;
}


int main()
{
	int ret = 0;
	int i = 0;
	
	char *p1[] = {"aaaa","cccc","bbbb"};
	int len1 = sizeof(p1)/sizeof(char *);
	char p2[3][30] = {"1111","3333","2222"};
	int len2 = sizeof(p2)/sizeof(p2[0]);
	char **p3 = NULL;
	int len3 = 0;
	ret = sort(p1,len1,p2,len2,&p3,&len3);
	if(ret != 0)
	{
		printf("ERROR CODE:%d in main.c:sort(p1,len1,p2,len2,&p3,&len3 )\n",ret);
		return ret;
	}
	
	for(i = 0;i<len3;i++)
	{
		printf("%s\n",p3[i]);
	}

	free_two_level_pointer02(&p3,len3);

	

	return 0;
}


[email protected]:~/high$ 
编译运行
[email protected]:~/high$ gcc -Wall main.c  && ./a.out 
1111
2222
3333
aaaa
bbbb
cccc
1 正在释放 0x20410b0 
2 正在释放 0x20410f0 
3 正在释放 0x20410d0 
4 正在释放 0x2041050 
5 正在释放 0x2041090 
6 正在释放 0x2041070 
7 正在释放 0x2041010 
[email protected]:~/high$


这是老师的答案

[email protected]:~/high$ cat teacher.c 
#include <stdlib.h>
#include <string.h>
#include <stdio.h>


int sort(char **myp1 /*in*/, int num1, char (*myp2)[30], int num2, char ***myp3, int *num3)
{
	int i = 0, j = 0, k= 0;
	int  tmplen = 0;
	char **p3 = NULL;
	char *tmpP = NULL;
	p3 = (char **)malloc( (num1 + num2) * sizeof(char *)  ); //里面装的是指针
	if (p3 == NULL) 
	{
		return -1;
	}
	//根据

	for (i=0; i<num1; i++)
	{
		tmplen= strlen(myp1[i]) + 1;
		p3[i] = (char *)malloc( tmplen * sizeof(char)) ;
		if (p3[i] == NULL)
		{
			return -2;
		}
		strcpy(p3[i], myp1[i]);
	}


	for (j=0; j<num2; j++, i++)
	{
		tmplen = strlen(myp2[j]) + 1;
		p3[i] = (char *)malloc (tmplen * sizeof(char));
		if (p3[i] == NULL)
		{
			return -3;
		}
		strcpy(p3[i], myp2[j]);
	}

	tmplen = num1 + num2;
	//*num3 = num1 + num2;

	//排序
	for (i=0; i<tmplen; i++)
	{
		for (j=i+1; j<tmplen; j++)
		{
			if ( strcmp(p3[i], p3[j]) > 0 )
			{
				tmpP = p3[i];
				p3[i] = p3[j];
				p3[j] = tmpP;
			}
		}
	}

	//间接赋值
	*num3 = tmplen;
	*myp3 = p3;
	return 0;
}


void sortFree01(char **p, int len)
{
	int i = 0;
	if (p == NULL)
	{
		return ;
	}

	for (i=0; i<len ; i++)
	{
		free(p[i]);
	}
	free(p);
}

void sortFree02(char ***myp, int len) //把二级指针指向二维内存释放掉,,同时间接的修改了实参的值
{
	int i = 0;
	char **p = NULL;
	if (myp == NULL)
	{
		return ;
	}

	p  = *myp; //还原成二级指针
	if (p == NULL)
	{
		return ;
	}

	for (i=0; i<len ; i++)
	{
		free(p[i]);
	}
	free(p);
	//myp 是实参的地址
	*myp = NULL; //间接赋值是指针存在的最大意义
}

int  main()
{
	int ret = 0;
	char *p1[] = {"aa", "ccccccc", "bbbbbb"};
	char buf2[10][30] = {"111111", "3333333", "222222"};
	char **p3 = NULL;
	int len1, len2, len3, i = 0;

	len1 = sizeof(p1)/sizeof(*p1);
	len2 = 3;

	ret = sort(p1, len1, buf2, len2, &p3, &len3);
	if (ret != 0)
	{
		printf("func sort() err:%d \n", ret);
		return ret;
	}

	for (i=0; i<len3; i++)
	{
		printf("%s\n", p3[i]);
	}

	printf("hello...\n");
	return ret;
}
[email protected]:~/high$ 
编译
[email protected]:~/high$ gcc teacher.c  && ./a.out 
111111
222222
3333333
aa
bbbbbb
ccccccc
hello...
[email protected]:~/high$




结构体浅拷贝

[email protected]:~/high$ cat main.c 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct teacher
{
	char name[60];
	int age;
	char *alias_name;
};

int main()
{
	struct teacher t1;
	struct teacher t2;

	strcpy(t1.name,"chunli");
	t1.age = 22;
	t1.alias_name = (char *)malloc(100);
	strcpy(t1.alias_name,"chunli_alias");
	printf("%s \n",t1.name);
	printf("%d \n",t1.age);
	printf("%s \n",t1.alias_name);

	//t2 = t1;		//这两个拷贝方式的效果一样
	//编译器的 = 操作只会把指针变量的值 拷贝过去
	//但不会把指针指向的内存空间拷贝过去
	memcpy(&t2,&t1,sizeof(struct teacher));

	printf("%s \n",t2.name);
	printf("%d \n",t2.age);
	printf("%s \n",t2.alias_name);

	if(t1.alias_name != NULL)
	{
		free(t1.alias_name);
		t1.alias_name =NULL;
	}

	if(t2.alias_name != NULL)
	{
		free(t2.alias_name);//程序会在这里宕掉因为别人已经释放了那片区域
		t2.alias_name =NULL;
	}

	return 0;
}


[email protected]:~/high$ 

[email protected]:~/high$ 
[email protected]:~/high$ gcc -g main.c  && ./a.out 
chunli 
22 
chunli_alias 
chunli 
22 
chunli_alias 
*** Error in `./a.out‘: double free or corruption (fasttop): 0x00000000025a8010 ***
Aborted (core dumped)
[email protected]:~/high$




结构体深度拷贝

[email protected]:~/high$ cat main.c 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct teacher
{
	char name[60];
	int age;
	char *alias_name;
};

int main()
{
	struct teacher t1;
	struct teacher t2;

	strcpy(t1.name,"chunli");
	t1.age = 22;
	t1.alias_name = (char *)malloc(100);
	strcpy(t1.alias_name,"chunli_alias");
	printf("%s \n",t1.name);
	printf("%d \n",t1.age);
	printf("%s \n",t1.alias_name);

	//编译器的 = 操作只会把指针变量的值 拷贝过去
	//但不会把指针指向的内存空间拷贝过去
	//t2 = t1;		//这两个拷贝方式的效果一样
	memcpy(&t2,&t1,sizeof(struct teacher));
	t2.alias_name = (char*)malloc(100);	//为t2 打造内存空间
	strcpy(t2.alias_name,t1.alias_name);	//深度拷贝

	printf("%s \n",t2.name);
	printf("%d \n",t2.age);
	printf("%s \n",t2.alias_name);

	if(t1.alias_name != NULL)
	{
		free(t1.alias_name);
		t1.alias_name =NULL;
	}

	if(t2.alias_name != NULL)
	{
		free(t2.alias_name);//程序会在这里不会宕掉因为t2有自己的内存空间
		t2.alias_name =NULL;
	}

	return 0;
}


[email protected]:~/high$ gcc -g main.c  && ./a.out 
chunli 
22 
chunli_alias 
chunli 
22 
chunli_alias 
[email protected]:~/high$ 
[email protected]:~/high$ 
[email protected]:~/high$



结构体高级话题偏移量1

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

struct teacher
{
        char name[60];
        int age;
        char *alias_name;
};

int main()
{
        struct teacher t1;
        struct teacher *p1;
        p1 -1;
        p1 -2;
        p1 -3;
        p1 - p1;
        int offsize = (int)&(p1->age);
        printf("%d\n",offsize);

        return 0;
}
编译
[email protected]:~/high$ gcc -g main.c  && ./a.out 
main.c: In function ‘main’:
main.c:20:16: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
  int offsize = (int)&(p1->age);
                ^
1327912356




结构体高级话题偏移量2

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

struct teacher
{
        char name[60];
        int age;
        char *alias_name;
};

int main()
{
        struct teacher t1;
        struct teacher *p1;
        p1 -1;
        p1 -2;
        p1 -3;
        p1 - p1;
        //告诉编译器struct teacher *从0到age有多大
        int offsize = (int)&(((struct teacher *)0)->age);
        printf("%d\n",offsize);

        return 0;
}
编译
[email protected]:~/high$ gcc -g main.c  && ./a.out 
main.c: In function ‘main’:
main.c:21:16: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
  int offsize = (int)&(((struct teacher *)0)->age);
                ^
60




【文件操作】

// 把字符写入文件

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

int main()
{
        FILE *p = fopen("./hello","w"); 
        if(p == NULL)
        {
                printf("error in fopen\n");
        }

        char *str = "Hello World!\n";
        int i = 0;
        for(i = 0;i<strlen(str);i++)
        {
                fputc(str[i],p);
        }
        fclose(p);

        return 0;
}
编译
[email protected]:~/high$ gcc -g main.c  && ./a.out 
[email protected]:~/high$ cat hello 
Hello World!


// 读文件

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

int main()
{
        FILE *p = fopen("./hello","r+");
        if(p == NULL)
        {
                printf("error in fopen\n");
        }
        while(!feof(p))
        {
                char c = fgetc(p);
                printf("%c",c);
        }
        if(p != NULL)
        {
                fclose(p);
        }

        return 0;
}
[email protected]:~/high$ gcc -g main.c  && ./a.out 
Hello World!



// fputs写文件

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

int main()
{
        FILE *p = fopen("./hello","r+");
        if(p == NULL)
        {
                printf("error in fopen\n");
        }
        char *str = "Hello ...\n";
        fputs(str,p);
        if(p != NULL)
        {
                fclose(p);
        }

        return 0;
}
编译运行
[email protected]:~/high$ cat hello 
Hello ...
d!
可以看出残缺覆盖


fgets读文件

// fgets读文件
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
        FILE *p = fopen("./hello","r+");
        if(p == NULL)
        {
                printf("error in fopen\n");
        }
        char buf[1024];
        while(!feof(p))
        {
                fgets(buf,1024,p);
                printf("%s",buf);
        }
        if(p != NULL)
        {
                fclose(p);
        }

        return 0;
}
Linux下运行
[email protected]:~/high$ cat hello 
2222222222222222222222
ffffffffffffffffff
3333
[email protected]:~/high$ gcc -g main.c  && ./a.out 
2222222222222222222222
ffffffffffffffffff
3333
3333
不明白为什么会多一行
在win下面就是正常的
网上查了一下linux的feof函数有问题




把结构体写入文件

[email protected]:~/high$ cat main.c 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct teacher
{
	char name[64];
	int age;
}teacher;

int main()
{
	FILE *fp = NULL;
	char *filename = "./hello";
	teacher teacher_arr[3];
	int i = 0;
	for(i = 0;i<3;i++)		//初始化结构体
	{
		sprintf(teacher_arr[i].name,"%d,%d,%d",i,i+i,i*i);
		teacher_arr[i].age = i + 30;
	}

	fp = fopen(filename,"wb");	//打开文件
	if(fp == NULL)
	{
		return -1;
	}

	for(i = 0;i<3;i++)		//写入数据到文件
	{
		size_t write_num = fwrite(&teacher_arr[i],sizeof(teacher),1,fp);
		if(!write_num)
		{
			printf("磁盘满\n");
		}
	}

	if(fp != NULL)
	{
		fclose(fp);
	}
	
	return 0;
}


[email protected]:~/high$ gcc -g main.c  && ./a.out 
[email protected]:~/high$ cat hello 
0,0,0ɡ .1,2,1-..N=栀戀-..h愀嘂2,4,[email protected]僻戀-. [email protected]:~/high$ Xshell^C
[email protected]:~/high$ hexdump hello 
0000000 2c30 2c30 0030 0000 e1c8 569c 7ff4 0000
0000010 0000 0000 0000 0000 0000 0000 0000 0000
*
0000030 0000 0000 0000 0000 e520 569c 7ff4 0000
0000040 001e 0000 2c31 2c32 0031 0e2d 7ffe 0000
0000050 4e2e f63d 0000 0000 03a4 0040 0000 0000
0000060 ffff ffff 0000 0000 6268 0e2d 7ffe 0000
0000070 51f8 563f 7ff4 0000 b568 569c 7ff4 0000
0000080 e1c8 569c 001f 0000 2c32 2c34 0034 0000
0000090 0001 0000 0000 0000 083d 0040 0000 0000
00000a0 6170 0e2d 7ffe 0000 0000 0000 0000 0000
00000b0 07f0 0040 0000 0000 0570 0040 0000 0000
00000c0 6250 0e2d 7ffe 0000 0020 0000          
00000cc
[email protected]:~/high$



从二进制文件中读取结构体数据

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

typedef struct teacher
{
        char name[64];
        int age;
}teacher;

int main()
{
        FILE *fp = NULL;
        char *filename = "./hello";
        teacher teacher_arr[3];
        int i = 0;

        fp = fopen(filename,"rb");      //打开文件
        if(fp == NULL)  return -1;

        for(i = 0;i<3;i++)              //写入数据到文件
        {
                size_t write_num = fread(&teacher_arr[i],sizeof(teacher),1,fp);
        }
        if(fp != NULL)  fclose(fp);
        for(i = 0;i<3;i++)              //初始化结构体
        {
                printf("%s ->",teacher_arr[i].name);
                printf("%d \n",teacher_arr[i].age);
        }
        
        return 0;
}
编译
[email protected]:~/high$ gcc -g main.c  && ./a.out 
0,0,0 ->30 
1,2,1 ->31 
2,4,4 ->32 
[email protected]:~/high$


【C语言 文件项目】

1程序的配置文件

2配置文件信息以key value存放

3应用层 与 底层文件操作分开

4应用层查的时候输入key返回value

5应用层改的时候输入keyvalue。如果key存在就修改。如果key不存在则追加一条记录


我的代码文件

[email protected]:~/high$ ll
total 36K
-rw-rw-r-- 1 chunli chunli 2.6K Jun 21 15:50 cfg_op.c
-rw-rw-r-- 1 chunli chunli  340 Jun 21 12:35 cfg_op.h
-rw-rw-r-- 1 chunli chunli 1.4K Jun 21 15:49 main.c
-rw-r--r-- 1 chunli chunli   34 Jun 21 15:51 mycfg.ini


文件1

[email protected]:~/high$ cat cfg_op.h 
#ifndef __CFG_OP_H__
#define __CFG_OP_H__

	#ifdef __cplusplus
	extern "C"{
	#endif
		int GetCfgItem(char *pFileNmae/*in*/,char *pKey/*in*/,char*pValue/*in out*/,int *pValueLen/*out*/);
		int WriteCfgItem(char *pFilename/*in*/,char *pItemName /*in*/,char *pItemValue/*in*/,int itemCalueLen/*in*/ );
	#ifdef __cplusplus
	}
	#endif
	

#endif
[email protected]:~/high$



文件2

[email protected]:~/high$ cat cfg_op.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXline  1024

int GetCfgItem(char *pFileNmae/*in*/,char *pKey/*in*/,char*pValue/*in out*/,int *pValueLen/*out*/)
{
	int ret = 0;
	FILE *fp = NULL;
	fp = fopen(pFileNmae,"r+");
	if(fp == NULL) 
	{
		return -1;
		printf("open file %s error\n",pFileNmae);
	}
	char linebuf[MAXline];
	while(!feof(fp))
	{
		memset(linebuf,0,1024);
		char *find = NULL;
		fgets(linebuf,MAXline,fp);
		find = strstr(linebuf,pKey);	if(find == NULL){continue;}	//没找到key
		find = strstr(linebuf,"=");	if(find == NULL){continue;}	//也没有"="
		find = find + strlen("=");
		char *p_head = NULL;
		char *p_tail = NULL;
		while(1)
		{
			if(*find == ‘ ‘)	{find++;}
			else
			{
				p_head = find;
				if(*find == ‘\n‘)
				{
					ret = -1;
					goto End;
					printf("没有找到 %s 对应的value\n",pKey);
				}
				break;
			}
		}
		while(1)
		{
			if( (*find == ‘ ‘) || (*find == ‘\n‘) )
			{
				break;
			}
			else
			{
				*find++;
			}
		}
		p_tail = find;
		*pValueLen  = p_tail - p_head;
		memcpy(pValue,p_head,p_tail - p_head);
	}

End:
	fclose(fp);
	return ret;
}
int WriteCfgItem(char *pFilename/*in*/,char *pKey /*in*/,char *pValue/*in*/,int ValueLen/*in*/ )
{
	int ret = 0;
	int iTag = 0;
	int leng = 0;
	char linebuf[MAXline];
	FILE *fp = NULL;
	char *pTmp = NULL;
	char *pBegin = NULL;
	char *pEnd = NULL;
	char filebuf[1024 *8] = {0};
	if(pFilename == NULL) {return -1;}
	if(pKey == NULL) {return -2;}
	if(pValue == NULL) {return -3;}
	fp = fopen(pFilename,"r+");
	if(fp == NULL)	
	{
		printf("文件打开失败,正在创建\n");
		fp = fopen(pFilename,"w+t");
		if(fp == NULL)
		{
			ret = -4;
			printf("文件创建也失败了\n");
			goto End;
		}
	}
	fseek(fp,0L,SEEK_END);
	leng = ftell(fp);
	fseek(fp,0L,SEEK_SET);
	if(leng > 1024 * 8)
	{
		ret = -5;
		printf("文件太大了\n");
		goto End;
		
	}
	while(!feof(fp))
	{
		memset(linebuf,MAXline,sizeof(linebuf));
		pTmp = fgets(linebuf,MAXline,fp);
		if(pTmp == NULL)
		{
			break;
		}
		pTmp = strstr(linebuf,pKey);
		if(pTmp == NULL)
		{
			strcat(filebuf,linebuf);
			continue;
		}
		else
		{
			sprintf(linebuf,"%s = %s\n",pKey,pValue);
			strcat(filebuf,linebuf);
			iTag = 1;
		}
	}

		if(iTag == 0)
		{
			fprintf(fp,"%s = %s\n",pKey,pValue);
		}
		else
		{
			if(fp == NULL)
			{
				fclose(fp);
				fp = NULL;
			}
			fp = fopen(pFilename,"w+t");
			if(fp == NULL)
			{
				ret = -5;
				printf("ERROR Create file!\n");
				goto End;
			}
			fputs(filebuf,fp);
			//fwrtite(filebuf,sizeof(char),strlen(filebuf),fp);
		}

End:
	if(fp != NULL)
	{
		fclose(fp);
		fp = NULL;
	}
	return ret;
}

[email protected]:~/high$



文件3

[email protected]:~/high$ cat main.c 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "cfg_op.h"

char *filename = "mycfg.ini";

void printf_menu()
{
	printf("\t\t*********************************\n");
	printf("\t\t[1]读配置文件\n");
	printf("\t\t[2]写配置文件\n");
	printf("\t\t[0]退出\n");
	printf("\t\t*********************************\n");
}

int TGetCfg()
{
	char name[1024] = {0};
	char valude[1024] = {0};
	int vlen = 0;
	printf("进入读文件模式\n");
	printf("请输入key ");
	scanf("%s",name);
	int ret =  GetCfgItem(filename,name,valude,&vlen);
	if(ret != 0)
	{
		printf("ERROR in GetCfgItem \n");
		return ret;
	}
	printf("读取结果%s -> %s \n",name,valude);
	return ret;
}
int TWriteCfg()
{
	char name[1024] = {0};
	char valude[1024] = {0};
	printf("进入配置文件的修改或添加模式\n");
	printf("请输入key valude: ");
	scanf("%s %s",name,valude);
	int ret =  WriteCfgItem(filename,name,valude,strlen(valude));
	if(ret != 0)
	{
		printf("ERROR in WriteCfgItem \n");
		return ret;
	}
	printf("您的输入是:%s -> %s \n",name,valude);
	return ret;
}

int main()
{
	int choice_num;
	while(1)
	{
		printf_menu();
		scanf("%d",&choice_num);
		switch(choice_num)
		{
			case 0:
				exit(0);
			case 1:
				TGetCfg();
				break;
			case 2:
				TWriteCfg();
				break;
			default:
				exit(0);
		}
	}
	return 0;
}


[email protected]:~/high$



编译运行

[email protected]:~/high$ gcc -g -o run main.c  cfg_op.c  && ./run
		*********************************
		[1]读配置文件
		[2]写配置文件
		[0]退出
		*********************************
1
进入读文件模式
请输入key 1
读取结果1 -> 2 
		*********************************
		[1]读配置文件
		[2]写配置文件
		[0]退出
		*********************************
2
进入配置文件的修改或添加模式
请输入key valude: 1 haha   
您的输入是:1 -> haha 
		*********************************
		[1]读配置文件
		[2]写配置文件
		[0]退出
		*********************************
1
进入读文件模式
请输入key 1
读取结果1 -> haha 
		*********************************
		[1]读配置文件
		[2]写配置文件
		[0]退出
		*********************************
0
[email protected]:~/high$


上面这道题老师的代码VS环境编译

文件1cfg_op.h

#ifndef __CFG_OP_H__
#define __CFG_OP_H__


#ifdef  __cplusplus
extern "C" {
#endif

//获取配置项
int GetCfgItem(char *pFileName /*in*/, char *pKey /*in*/, char * pValue/*in out*/, int * pValueLen /*out*/);

//写配置项 
int WriteCfgItem(char *pFileName /*in*/, char *pItemName /*in*/, char *pItemValue/*in*/, int itemValueLen /*in*/);


#ifdef  __cplusplus
}
#endif



#endif





文件2

cfg_op.c

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

#define MaxLine 2048 

//获取配置项
int GetCfgItem(char *pFileName /*in*/, char *pKey /*in*/, char * pValue/*in out*/, int * pValueLen /*out*/)
{

	int		ret = 0;
	FILE	*fp = NULL;
	char	*pTmp = NULL, *pEnd = NULL, *pBegin = NULL;

	char lineBuf[MaxLine];

	fp = fopen(pFileName, "r");
	if (fp == NULL)
	{
		ret = -1;
		return ret;
	}

	while (!feof(fp))
	{
		memset(lineBuf, 0, sizeof(lineBuf));
		 //fgets(_Out_z_cap_(_MaxCount) char * _Buf, _In_ int _MaxCount, _Inout_ FILE * _File);
		fgets(lineBuf, MaxLine, fp);
		//printf("lineBuf:%s ",lineBuf );

		pTmp = strchr(lineBuf, ‘=‘); //
		if (pTmp == NULL) //没有=号
		{
			continue;
		}

		pTmp = strstr(lineBuf, pKey);
		if (pTmp == NULL) //判断key是不是在 //所在行 是不是有key
		{
			continue;
		}
		pTmp = pTmp + strlen(pKey); //mykey1 = myvalude11111111 ==> "= myvalude1111111"

		pTmp = strchr(pTmp, ‘=‘);
		if (pTmp == NULL) //判断key是不是在 //所在行 是不是有key
		{
			continue;
		}
		pTmp = pTmp + 1;
		//
		//printf("pTmp:%s ", pTmp);

		//获取value 起点
		while (1) 
		{
			if (*pTmp == ‘ ‘)
			{
				pTmp ++ ;
			} 
			else
			{
				pBegin = pTmp;
				if (*pBegin == ‘\n‘)
				{
					//没有配置value
					//printf("配置项:%s 没有配置value \n", pKey);
					goto End;
				}
				break;
			}
		}

		//获取valude结束点
		while (1) 
		{
			if ((*pTmp == ‘ ‘ || *pTmp == ‘\n‘))
			{
				break;
			}
			else 
			{
				pTmp ++;
			}
		}
		pEnd = pTmp;

		//赋值
		*pValueLen = pEnd-pBegin;
		memcpy(pValue, pBegin, pEnd-pBegin);
	}

End:
	if (fp == NULL)
	{
		fclose(fp);
	}
	return 0;

}

//写配置项 
//实现流程
//循环读每一行检查key配置项是否存在 若存在修改对应value值
//若不存在在文件末尾 添加 "key = value"
//难点如何修改文件流中的值
int WriteCfgItem(char *pFileName /*in*/, char *pKey /*in*/, char * pValue/*in*/, int ValueLen /*in*/)
{
	int		rv = 0, iTag = 0, length = 0;
	FILE	*fp = NULL;
	char	lineBuf[MaxLine];
	char	*pTmp = NULL, *pBegin = NULL, *pEnd = NULL;
	char	filebuf[1024*8] = {0};

	if (pFileName==NULL || pKey==NULL || pValue==NULL) 
	{
		rv = -1;
		printf("SetCfgItem() err. param err \n");
		goto End;
	}

	fp = fopen(pFileName, "r+");
	if (fp == NULL)
	{
		rv = -2;
		printf("fopen() err. \n");
		//goto End;
	}

	if (fp == NULL)
	{
		fp = fopen(pFileName, "w+t");
		if (fp == NULL)
		{
			rv = -3;
			printf("fopen() err. \n");
			goto End;
		}
	}

	fseek(fp, 0L, SEEK_END); //把文件指针从0位置开始移动到文件末尾
	//获取文件长度;
	length = ftell(fp);

	fseek(fp, 0L, SEEK_SET);

	if (length > 1024*8) 
	{
		rv = -3;
		printf("文件超过1024*8, nunsupport");
		goto End;
	}

	while (!feof(fp))
	{
		//读每一行
		memset(lineBuf, 0, sizeof(lineBuf));
		pTmp = fgets(lineBuf, MaxLine, fp);
		if (pTmp == NULL) 
		{
			break;
		}

		//key关键字是否在本行
		pTmp = strstr(lineBuf, pKey);
		if (pTmp == NULL) //key关键字不在本行 copy到filebuf中
		{
			strcat(filebuf, lineBuf);
			continue;
		}
		else  //key关键在在本行中替换旧的行再copy到filebuf中 
		{
			sprintf(lineBuf, "%s = %s\n", pKey, pValue);  
			strcat(filebuf, lineBuf);
			//若存在key
			iTag = 1; 
		}
	}

	//若key关键字不存在 追加
	if (iTag == 0) 
	{
		fprintf(fp, "%s = %s\n", pKey, pValue);
	}
	else //若key关键字存在则重新创建文件
	{
		if (fp != NULL) 
		{ 
			fclose(fp); 
			fp = NULL; //避免野指针
		}

		fp = fopen(pFileName, "w+t"); 
		if (fp == NULL)
		{
			rv = -4;
			printf("fopen() err. \n");
			goto End;
		}
		fputs(filebuf, fp);
		//fwrite(filebuf, sizeof(char), strlen(filebuf), fp);
	}

End:
	if (fp != NULL)
	{
		fclose(fp); 
	}
	return rv;
}




文件3

#define  _CRT_SECURE_NO_WARNINGS 
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "cfg_op.h"

#define CFGNAME "c:/mycfg.ini"
void mymenu()
{
	printf("=============================\n");
	printf("1 测试写配置文件\n");
	printf("2 测试读配置文件\n");
	printf("0 退出\n");
	printf("=============================\n");
}

//获取配置项
int TGetCfg()
{
	int		ret = 0;
	//读配置项 
	char	name[1024] = {0};
	char	valude[1024] = {0};
	int		vlen = 0;

	printf("\n请键入key:");
	scanf("%s", name);

	ret = GetCfgItem(CFGNAME /*in*/, name /*in*/, valude/*in*/, &vlen);
	if (ret != 0)
	{
		printf("func WriteCfgItem err:%d \n", ret);
		return ret;
	}
	printf("valude:%s \n", valude);

}

//写配置项 
int TWriteCfg()
{
	int		ret = 0;
	//写配置项 
	char name[1024] = {0};
	char valude[1024] = {0};


	printf("\n请键入key:");
	scanf("%s", name);

	printf("\n请键入valude:");
	scanf("%s", valude);

	ret = WriteCfgItem(CFGNAME /*in*/, name /*in*/, valude/*in*/,strlen(valude) /*in*/);
	if (ret != 0)
	{
		printf("func WriteCfgItem err:%d \n", ret);
		return ret;
	}
	printf("你的输入是%s = %s \n", name , valude);
	return ret;
}

void main()
{

	int choice;

	for (;;)
	{
		//显示一个菜单
		mymenu();
		scanf("%d", &choice);
		switch (choice)
		{
			
		case 1:   //写配置项
			TWriteCfg();
			break;
		case 2: 
			TGetCfg(); //读配置项
			break;
		case 0: 
			exit(0);
		default:;
			exit(0);
		}

	}
	printf("hello...\n");
	system("pause");
	return ;
}



文件专业加密:

VS编译OK

GCC编译不正常。

技术分享


4个文件:

文件1:des.h

/*********************************************************
 *  des.h
 *  用户使用des算法头文件
 *	
 *********************************************************/
#ifndef _OPENDESS_H_
#define _OPENDESS_H_

#ifdef __cplusplus
extern "C" {
#endif

//ab\0defg

//用户使用的函数
int DesEnc(
		unsigned char *pInData,
		int            nInDataLen,
		unsigned char *pOutData,
		int           *pOutDataLen);

//用户使用函数des解密
int DesDec(
	   unsigned char *pInData,
	   int            nInDataLen,
	   unsigned char *pOutData,
	   int           *pOutDataLen);

#ifdef __cplusplus
}
#endif

#endif


文件2,des.c

/******************************************************
 *
 *  des.c
 *  common des......
 *
 ******************************************************/

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

/*********************************************************
  data type definition for Des;
**********************************************************/
#define EN0	0
#define DE1	1

#define DES_KEYBYTES	128
#define DES_KEYLONGS	32
#define DES_BLOCKLEN	8

typedef struct {
	unsigned char ek[DES_KEYBYTES];
	int	ekLen;
	unsigned char dk[DES_KEYBYTES];
	int	dkLen;
	unsigned char CbcCtx[DES_BLOCKLEN];
} DES_CTX;

typedef struct {
	unsigned char ek1[DES_KEYBYTES];
	int	ek1Len;
	unsigned char dk1[DES_KEYBYTES];
	int	dk1Len;
	unsigned char ek2[DES_KEYBYTES];
	int	ek2Len;
	unsigned char dk2[DES_KEYBYTES];
	int	dk2Len;
	unsigned char CbcCtx[DES_BLOCKLEN];
	//int	IsFirstBlock;
} DES3_CTX;


static unsigned char pc1[56] = {
	56, 48, 40, 32, 24, 16,  8,  0, 57, 49, 41, 33, 25, 17,
	 9,  1, 58, 50, 42, 34, 26, 18, 10,  2, 59, 51, 43, 35,
	62, 54, 46, 38, 30, 22, 14,  6, 61, 53, 45, 37, 29, 21,
	13,  5, 60, 52, 44, 36, 28, 20, 12,  4, 27, 19, 11,  3 };

static unsigned char pc2[48] = {
	13, 16, 10, 23,  0,  4,		 2, 27, 14,  5, 20,  9,
	22, 18, 11,  3, 25,  7, 	15,  6, 26, 19, 12,  1,
	40, 51, 30, 36, 46, 54,		29, 39, 50, 44, 32, 47,
	43, 48, 38, 55, 33, 52, 	45, 41, 49, 35, 28, 31 };

static unsigned short bytebit[8] = {0200,0100,040,020,010,04,02,01 };
static unsigned char totrot[16] = {1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28};
static unsigned long bigbyte[24] = {
	0x800000L,	0x400000L,	0x200000L,	0x100000L,
	0x80000L,	0x40000L,	0x20000L,	0x10000L,
	0x8000L,	0x4000L,	0x2000L,	0x1000L,
	0x800L,		0x400L,		0x200L,		0x100L,
	0x80L,		0x40L,		0x20L,		0x10L,
	0x8L,		0x4L,		0x2L,		0x1L	};

//insert digits
static unsigned long SP1[64] ={
       0x01010400l,0x00000000l,0x00010000l,0x01010404l,
       0x01010004l,0x00010404l,0x00000004l,0x00010000l,
       0x00000400l,0x01010400l,0x01010404l,0x00000400l,
       0x01000404l,0x01010004l,0x01000000l,0x00000004l,
       0x00000404l,0x01000400l,0x01000400l,0x00010400l,
       0x00010400l,0x01010000l,0x01010000l,0x01000404l,
       0x00010004l,0x01000004l,0x01000004l,0x00010004l,
       0x00000000l,0x00000404l,0x00010404l,0x01000000l,
       0x00010000l,0x01010404l,0x00000004l,0x01010000l,
       0x01010400l,0x01000000l,0x01000000l,0x00000400l,
       0x01010004l,0x00010000l,0x00010400l,0x01000004l,
       0x00000400l,0x00000004l,0x01000404l,0x00010404l,
       0x01010404l,0x00010004l,0x01010000l,0x01000404l,
       0x01000004l,0x00000404l,0x00010404l,0x01010400l,
       0x00000404l,0x01000400l,0x01000400l,0x00000000l,
       0x00010004l,0x00010400l,0x00000000l,0x01010004l };
       
       
static unsigned long SP2[64]={
       0x80108020l,0x80008000l,0x00008000l,0x00108020l,
       0x00100000l,0x00000020l,0x80100020l,0x80008020l,
       0x80000020l,0x80108020l,0x80108000l,0x80000000l,
       0x80008000l,0x00100000l,0x00000020l,0x80100020l,
       0x00108000l,0x00100020l,0x80008020l,0x00000000l,
       0x80000000l,0x00008000l,0x00108020l,0x80100000l,
       0x00100020l,0x80000020l,0x00000000l,0x00108000l,
       0x00008020l,0x80108000l,0x80100000l,0x00008020l,
       0x00000000l,0x00108020l,0x80100020l,0x00100000l,
       0x80008020l,0x80100000l,0x80108000l,0x00008000l,
       0x80100000l,0x80008000l,0x00000020l,0x80108020l,
       0x00108020l,0x00000020l,0x00008000l,0x80000000l,
       0x00008020l,0x80108000l,0x00100000l,0x80000020l,
       0x00100020l,0x80008020l,0x80000020l,0x00100020l,
       0x00108000l,0x00000000l,0x80008000l,0x00008020l,
       0x80000000l,0x80100020l,0x80108020l,0x00108000l };
       
       
static unsigned long SP3[64]={ 
       0x00000208l,0x08020200l,0x00000000l,0x08020008l,
       0x08000200l,0x00000000l,0x00020208l,0x08000200l,
       0x00020008l,0x08000008l,0x08000008l,0x00020000l,
       0x08020208l,0x00020008l,0x08020000l,0x00000208l,
       0x08000000l,0x00000008l,0x08020200l,0x00000200l,
       0x00020200l,0x08020000l,0x08020008l,0x00020208l,
       0x08000208l,0x00020200l,0x00020000l,0x08000208l,
       0x00000008l,0x08020208l,0x00000200l,0x08000000l,
       0x08020200l,0x08000000l,0x00020008l,0x00000208l,
       0x00020000l,0x08020200l,0x08000200l,0x00000000l,
       0x00000200l,0x00020008l,0x08020208l,0x08000200l,
       0x08000008l,0x00000200l,0x00000000l,0x08020008l,
       0x08000208l,0x00020000l,0x08000000l,0x08020208l,
       0x00000008l,0x00020208l,0x00020200l,0x08000008l,
       0x08020000l,0x08000208l,0x00000208l,0x08020000l,
       0x00020208l,0x00000008l,0x08020008l,0x00020200l };
       
       
static unsigned long SP4[64]={             
       0x00802001l,0x00002081l,0x00002081l,0x00000080l,
       0x00802080l,0x00800081l,0x00800001l,0x00002001l,
       0x00000000l,0x00802000l,0x00802000l,0x00802081l,
       0x00000081l,0x00000000l,0x00800080l,0x00800001l,
       0x00000001l,0x00002000l,0x00800000l,0x00802001l,
       0x00000080l,0x00800000l,0x00002001l,0x00002080l,
       0x00800081l,0x00000001l,0x00002080l,0x00800080l,
       0x00002000l,0x00802080l,0x00802081l,0x00000081l,
       0x00800080l,0x00800001l,0x00802000l,0x00802081l,
       0x00000081l,0x00000000l,0x00000000l,0x00802000l,
       0x00002080l,0x00800080l,0x00800081l,0x00000001l,
       0x00802001l,0x00002081l,0x00002081l,0x00000080l,
       0x00802081l,0x00000081l,0x00000001l,0x00002000l,
       0x00800001l,0x00002001l,0x00802080l,0x00800081l,
       0x00002001l,0x00002080l,0x00800000l,0x00802001l,
       0x00000080l,0x00800000l,0x00002000l,0x00802080l };
       
       
static unsigned long SP5[64]={   
       0x00000100l,0x02080100l,0x02080000l,0x42000100l,
       0x00080000l,0x00000100l,0x40000000l,0x02080000l,
       0x40080100l,0x00080000l,0x02000100l,0x40080100l,
       0x42000100l,0x42080000l,0x00080100l,0x40000000l,
       0x02000000l,0x40080000l,0x40080000l,0x00000000l,
       0x40000100l,0x42080100l,0x42080100l,0x02000100l,
       0x42080000l,0x40000100l,0x00000000l,0x42000000l,
       0x02080100l,0x02000000l,0x42000000l,0x00080100l,
       0x00080000l,0x42000100l,0x00000100l,0x02000000l,
       0x40000000l,0x02080000l,0x42000100l,0x40080100l,
       0x02000100l,0x40000000l,0x42080000l,0x02080100l,
       0x40080100l,0x00000100l,0x20000000l,0x42080000l,
       0x42080100l,0x00080100l,0x42000000l,0x42080100l,
       0x02080000l,0x02000100l,0x40000100l,0x00080000l,
       0x00080100l,0x02000100l,0x40000100l,0x00080000l,
       0x00000000l,0x40080000l,0x02080100l,0x40000100l };
       
       
static unsigned long SP6[64]={ 
       0x20000010l,0x20400000l,0x00004000l,0x20404010l,
       0x20400000l,0x00000010l,0x20404010l,0x00400000l,
       0x20004000l,0x00404010l,0x00400000l,0x20000010l,
       0x00400010l,0x20004000l,0x20000000l,0x00004010l,
       0x00000000l,0x00400010l,0x20004010l,0x00004000l,
       0x00404000l,0x20004010l,0x00000010l,0x20400010l,
       0x20400010l,0x00000000l,0x00404010l,0x20404000l,
       0x00004010l,0x00404000l,0x20404000l,0x20000000l,
       0x20004000l,0x00000010l,0x20400010l,0x00404000l,
       0x20404010l,0x00400000l,0x00004010l,0x20000010l,
       0x00400000l,0x20004000l,0x20000000l,0x00004010l,
       0x20000010l,0x20404010l,0x00404000l,0x20400000l,
       0x00404010l,0x20404000l,0x00000000l,0x20400010l,
       0x00000010l,0x00004000l,0x20400000l,0x00404010l,
       0x00004000l,0x00400010l,0x20004010l,0x00000000l,
       0x20404000l,0x20000000l,0x00400010l,0x20004010l };  
            
static unsigned long SP7[64] = {
	0x00200000L, 0x04200002L, 0x04000802L, 0x00000000L,
	0x00000800L, 0x04000802L, 0x00200802L, 0x04200800L,
	0x04200802L, 0x00200000L, 0x00000000L, 0x04000002L,
	0x00000002L, 0x04000000L, 0x04200002L, 0x00000802L,
	0x04000800L, 0x00200802L, 0x00200002L, 0x04000800L,
	0x04000002L, 0x04200000L, 0x04200800L, 0x00200002L,
	0x04200000L, 0x00000800L, 0x00000802L, 0x04200802L,
	0x00200800L, 0x00000002L, 0x04000000L, 0x00200800L,
	0x04000000L, 0x00200800L, 0x00200000L, 0x04000802L,
	0x04000802L, 0x04200002L, 0x04200002L, 0x00000002L,
	0x00200002L, 0x04000000L, 0x04000800L, 0x00200000L,
	0x04200800L, 0x00000802L, 0x00200802L, 0x04200800L,
	0x00000802L, 0x04000002L, 0x04200802L, 0x04200000L,
	0x00200800L, 0x00000000L, 0x00000002L, 0x04200802L,
	0x00000000L, 0x00200802L, 0x04200000L, 0x00000800L,
	0x04000002L, 0x04000800L, 0x00000800L, 0x00200002L };
	
static unsigned long SP8[64] = {
	0x10001040L, 0x00001000L, 0x00040000L, 0x10041040L,
	0x10000000L, 0x10001040L, 0x00000040L, 0x10000000L,
	0x00040040L, 0x10040000L, 0x10041040L, 0x00041000L,
	0x10041000L, 0x00041040L, 0x00001000L, 0x00000040L,
	0x10040000L, 0x10000040L, 0x10001000L, 0x00001040L,
	0x00041000L, 0x00040040L, 0x10040040L, 0x10041000L,
	0x00001040L, 0x00000000L, 0x00000000L, 0x10040040L,
	0x10000040L, 0x10001000L, 0x00041040L, 0x00040000L,
	0x00041040L, 0x00040000L, 0x10041000L, 0x00001000L,
	0x00000040L, 0x10040040L, 0x00001000L, 0x00041040L,
	0x10001000L, 0x00000040L, 0x10000040L, 0x10040000L,
	0x10040040L, 0x10000000L, 0x00040000L, 0x10001040L,
	0x00000000L, 0x10041040L, 0x00040040L, 0x10000040L,
	0x10040000L, 0x10001000L, 0x10001040L, 0x00000000L,
	0x10041040L, 0x00041000L, 0x00041000L, 0x00001040L,
	0x00001040L, 0x00040040L, 0x10000000L, 0x10041000L };

void deskey(unsigned char *key,short edf, unsigned long *kn);
void cookey(register unsigned long *raw1, unsigned long *dough);
//void cpkey(register unsigned long *into);
//void usekey(register unsigned long *from);
//void des(unsigned char *inblock,unsigned char *outblock);
void scrunch(register unsigned char *outof, register unsigned long *into);
void unscrun(register unsigned long *outof, register unsigned char *into);
void desfunc(register unsigned long *block,register unsigned long *keys);

/*****************  DES Function  *****************/
unsigned long OPENCOMM_DesExpandEncKey(
		unsigned char *pbDesKey,
		unsigned long  ulDesKeyLen,
		unsigned char *pbDesEncKey,
		unsigned long *ulDesEncKeyLen);

unsigned long OPENCOMM_DesExpandDecKey(
		unsigned char *pbDesKey,
		unsigned long  ulDesKeyLen,
		unsigned char *pbDesDecKey,
		unsigned long *ulDesDecKeyLen);

unsigned long OPENCOMM_DesEncRaw(
		unsigned char *pbDesEncKey,
		unsigned long  ulDesEncKeyLen,
		unsigned char *pbInData,
		unsigned long  ulInDataLen,
		unsigned char *pbOutData,
		unsigned long *ulOutDataLen);

unsigned long OPENCOMM_DesDecRaw(
		unsigned char *pbDesDecKey,
		unsigned long  ulDesDecKeyLen,
		unsigned char *pbInData,
		unsigned long  ulInDataLen,
		unsigned char *pbOutData,
		unsigned long *ulOutDataLen);


int myic_DESDecrypt(
		unsigned char *pDesKey,
		int            nDesKeyLen,
		unsigned char *pInData,
		int    

以上是关于C提高5 高级结构体 文件操作的主要内容,如果未能解决你的问题,请参考以下文章

C语言提高内容目录

图书管理系统(大一C语言大作业 包含主要结构体,文件操作, 如数据的修改 查询 删除等)

C语言进阶之旅(留下的足迹)

c博客06-结构体&文件

C语言结构体里的结构体怎么初始化

C语言进阶之旅(留下的足迹)