通讯录的加载和保存

通讯录可以实现增加/删除/修改数据等功能,数据是存放在内存中,当程序退出的时候,通讯录中的数据自然就不存在了,如果下次运行通讯录程序的时候,数据又得重新录入,所以很不方便。

使用文件我们可以将数据直接存放在电脑的硬盘上,做到了数据的持久化。这样,通讯录就可以把信息记录下来,只有我们自己选择删除数据的时候,数据才不复存在。

通讯录中的加载和保存功能使用了文件的打开和关闭已保存通讯录信息,主要包含的函数有fopen()和fclose().

功能一:通讯录的加载

void LoadContact(struct Contact* ps)
{
	struct PeoInfo tmp = { 0 };
	FILE* psRead = fopen("Contact.txt", "rb");//以二进制只读的方式打开文件

	if (!psRead)//若打开失败,即psRead为空指针
	{
		printf("LoadContact::%s\n", strerror(errno));
		return;
	}

	while (fread(&tmp, sizeof(struct PeoInfo), 1, psRead))//fread读取成功返回一个非0值,将文件中的数据先读入tmp中
	{
		CheckCapacity(ps);//判断是否需要增容
		ps->data[ps->size] = tmp;
		ps->size++;//联系人个数递增
	}

	fclose(psRead);//关闭文件
	psRead = NULL;//指针置空
}

功能二:通讯录的保存

void SaveContact(struct Contact* ps)
{
	FILE* pfWrite = fopen("Contact.txt", "wb");//以二进制只写的方式打开文件

	if (!pfWrite)//若打开失败
	{
		printf("SaveContact::%s\n", strerror(errno));//将errno错误编码所对应的错误信息输出出来
		return;
	}
	for (int i = 0; i < ps->size; i++)
	{
		fwrite(&(ps->data[i]), sizeof(struct PeoInfo), 1, pfWrite);//依次将信息写入
	}

	fclose(pfWrite);//关闭文件
	pfWrite = NULL;//指针置空
	printf("保存成功!\n");
}

1. fopen()
 

让我们编译并运行下面的程序,创建一个文件file.txt,其中包含以下内容:

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

int main () {
   FILE * fp;

   fp = fopen ("file.txt", "w+");
   fprintf(fp, "%s %s %s %d", "We", "are", "in", 2012);
   
   fclose(fp);
   
   return(0);
}

运行以上程序,创建一个含有以下内容的 file.txt 文件:

We are in 2012

接下来,用以下程序再次运行以上的文件:

#include <stdio.h>

int main () {
   FILE *fp;
   int c;
  
   fp = fopen("file.txt","r");
   while(1) {
      c = fgetc(fp);
      if( feof(fp) ) { 
         break ;
      }
      printf("%c", c);
   }
   fclose(fp);
   
   return(0);
}

再次运行会出现同样的内容:

We are in 2012

C库函数FILE *fopen(const char *filename, const char *mode)使用给定模式通过filename打开指向的文件名。

打开文件名在参数filename中指定的文件,并将其与一个流关联,该流可在未来操作中由返回的file指针识别。

流上允许的操作以及如何执行这些操作由mode形参定义。

默认情况下,如果已知返回的流不指向交互设备,则返回的流是完全缓冲的(参见setbuf)。

返回的指针可以通过调用fclose或freopen来解除与文件的关联。正常程序终止时,所有打开的文件都会自动关闭。

判断文件是否打开成功

打开文件出错时,fopen() 将返回一个空指针,也就是 NULL,我们可以利用这一点来判断文件是否打开成功,请看下面的代码:

FILE *fp;
if( (fp=fopen("D:\\demo.txt","rb")) == NULL ){
printf("Fail to open file!\n");
exit(0); //退出程序(结束程序)
}

我们通过判断 fopen() 的返回值是否和 NULL 相等来判断是否打开失败:如果 fopen() 的返回值为 NULL,那么 fp 的值也为  NULL,此时 if 的判断条件成立,表示文件打开失败。

2. fclose()

fclose是C语言标准库中的一个函数,功能是关闭一个流。未写的缓冲区数据将被刷新到操作系统中。任何未读的缓冲数据将被丢弃。无论操作是否成功,流都不再与文件相关联,如果使用了自动分配,则由setbuf或setvbuf分配的缓冲区(如果有的话)也会被解除关联并释放。如果在fclose返回后使用指针流的值,则该行为未定义。

函数原型:int fclose (FILE *stream); 如果流成功关闭,fclose 返回 0,否则返回EOF(-1)。

判断文件是否打开成功

打开文件出错时,fopen() 将返回一个空指针,也就是 NULL,我们可以利用这一点来判断文件是否打开成功:

FILE *fp;
if((fp=fopen("D:\\homework.txt","rb")) == NULL)
{
    printf("Fail to open file!\n");
    exit(0); //退出程序(结束程序)
}

如果文件打开失败,可以用strerror函数将errno错误编码所对应的错误信息输出出来, 方便找到出错的位置。strerror函数返回一个指向系统错误代码errnum的文本描述的指针。Errnum通常从errno变量中获取,但该函数接受任何int类型的值。返回的字符串不能被程序修改,但可以被随后调用strerror函数覆盖。可能会返回指向静态只读字符串字面量的不同指针,或者可能会反复返回相同的指针,指向strerror放置字符串的静态缓冲区。

猜你喜欢

转载自blog.csdn.net/m0_72000264/article/details/128697408