Eu realmente não posso odiar um adolescente perseguindo seus sonhos
Índice
1. Precauções para leitura do código-fonte
2. Função de leitura de arquivos e regras de leitura e gravação de arquivos
Olá a todos, meu nome é Ji Ning.
O artigo anterior mostrou como usar a linguagem C para realizar a versão dinâmica do catálogo de endereços. Este artigo apresentará como usar a linguagem C para gravar as informações do catálogo de endereços em um arquivo e salvá-lo na memória. Na próxima vez você carrega o programa do catálogo de endereços, você pode ler diretamente a versão anterior.
1. Precauções para leitura do código-fonte
- O código-fonte é dividido em três arquivos, um arquivo de cabeçalho .h, dois arquivos de arquivo-fonte .c e os três arquivos precisam ser criados no mesmo caminho
- Cada vez que um ponteiro é passado, a validade do ponteiro deve ser verificada; cada memória aberta dinamicamente deve ser liberada a tempo após o uso, e o ponteiro mantido será definido como um ponteiro nulo após a liberação
- Lembre-se de fechar o arquivo depois de ler e gravar o arquivo
//contact.c
#define _CRT_SECURE_NO_WARNINGS
#include "contact.h"
int Memory_allocation(Contact* Cp)
{
assert(Cp);
if (Cp->sz == Cp->SpaceMax)//开辟内存
{
Options* Sp = (Options*)realloc(Cp->date, ((One_Add + Cp->SpaceMax) * sizeof(Options)));
if (Sp == NULL)
{
perror("realloc");
return 1;
}
else
{
Cp->date = Sp;
Cp->SpaceMax += One_Add;
printf("增容成功\n");
return 0;
}
}
else
return 0;
}
int FindName(Contact* Cp, char s[])
{
//找到就返回i
//找不到就返回-1
assert(Cp);
int i = 0;
for (i = 0; i < Cp->sz; i++)
{
if (strcmp(s, Cp->date[i].Name) == 0)
{
return i;
}
}
return -1;
}
void InputContact(Contact* Cp)
{
assert(Cp);
FILE* pf = fopen("data.txt", "rb");
if (pf == NULL)
{
return;
}
else
{
Options tmp = { 0 };
while(fread(&tmp, sizeof(Options), 1, pf))
{
if (1== Memory_allocation(Cp))
return;
Cp->date[Cp->sz] = tmp;
Cp->sz++;
}
}
fclose(pf);
pf = NULL;
}
void InitContact(Contact* Cp)//初始化通讯录
{
assert(Cp);
Cp->date=(Options*)malloc(sizeof(Options) * Start_Capacity);
if (Cp == NULL)
{
perror("malloc");
return;
}
Cp->sz = 0;
Cp->SpaceMax = Max_Space;
InputContact(Cp);//录入数据
//静态版
/*memeset(Cp->date, 0, sizeof(Options));*/
}
void AddContact(Contact* Cp)
{
assert(Cp);
int z=Memory_allocation(Cp);
if (z == 1)
{
printf("增容失败\n");
return;
}
//静态版——不需要开辟内存
/*if (Cp->sz == 100)
{
printf("通讯录已满\n");
return;
}*/
else
{
printf("请输入姓名:\n");
scanf("%s", Cp->date[Cp->sz].Name);
printf("请输入年龄:\n");
scanf("%d", &(Cp->date[Cp->sz].Age));
printf("请输入性别:\n");
scanf("%s", Cp->date[Cp->sz].Sex);
printf("请输入电话:\n");
scanf("%s", Cp->date[Cp->sz].Tele);
printf("请输入地址:\n");
scanf("%s", Cp->date[Cp->sz].Addr);
Cp->sz += 1;
}
}
void ShowContact(Contact* Cp)
{
assert(Cp);
int i = 0;
printf("%10s\t%4s\t%5s\t%15s\t%30s\n","姓名","年龄","性别","电话","地址");
for (i = 0; i < Cp->sz; i++)
{
printf("%10s\t%4d\t%5s\t%15s\t%30s\n", Cp->date[i].Name,
Cp->date[i].Age,
Cp->date[i].Sex,
Cp->date[i].Tele,
Cp->date[i].Addr);
}
}
void DelContact(Contact* Cp)
{
assert(Cp);
printf("请输入要删除的名字:\n");
char s[Con_Name] = "0";
scanf("%s", s);
//找名字函数
int i= FindName(Cp,s);
int j = 0;
for (j = i; j < Cp->sz; j++)
{
memmove(&Cp->date[j], &Cp->date[j + 1], sizeof(Cp->date[0]));
}
Cp->sz--;
}
void RevContact(Contact* Cp)
{
assert(Cp);
printf("请输入你要修改的名字:\n");
char s[Con_Name] = "0";
scanf("%s", s);
int i = FindName(Cp, s);//先得找到
printf("请输入姓名:\n");
scanf("%s", Cp->date[i].Name);
printf("请输入年龄:\n");
scanf("%d", &(Cp->date[i].Age));
printf("请输入性别:\n");
scanf("%s", Cp->date[i].Sex);
printf("请输入电话:\n");
scanf("%s", Cp->date[i].Tele);
printf("请输入地址:\n");
scanf("%s", Cp->date[i].Addr);
}
void SearchContact(Contact* Cp)
{
assert(Cp);
printf("请输入你要查找的姓名:\n");
char s[Con_Name] = "0";
scanf("%s", s);
int i = FindName(Cp, s);
printf("%10s\t%4d\t%5s\t%15s\t%30s\n", Cp->date[i].Name,
Cp->date[i].Age,
Cp->date[i].Sex,
Cp->date[i].Tele,
Cp->date[i].Addr);
}
int Comper1(const void* p1, const void* p2)
{
return ((Options*)p1)->Age - (((Options*)p2)->Age);
}
int Comper2(const void* p1, const void* p2)
{
return strcmp(((Options*)p1)->Name,(((Options*)p2)->Name));
}
void SortContact(Contact* Cp)
{
assert(Cp);
printf("请输入你要进行排序的选项:姓名/年龄\n");
char s[Con_Name] = "0";
scanf("%s", s);
if (strcmp(s, "年龄") == 0)
qsort(&(Cp->data[0]), Cp->sz, sizeof(Cp->data[0]), Comper1);
else
qsort(&(Cp->data[0]), Cp->sz, sizeof(Cp->data[0]), Comper2);
printf("排序后的通讯录:\n");
ShowContact(Cp);
}
void Destory_Contact(Contact* Cp)
{
assert(Cp);
free(Cp->date);
Cp -> date = NULL;
}
void StoreContact(Contact* Cp)
{
assert(Cp);
//打开文件
FILE* pf = fopen("data.txt", "wb");
int i = 0;
for (i = 0; i < Cp->sz; i++)
{
//以二进制的形式写入文件
fwrite(Cp->date+i, sizeof(Options), 1, pf);
}
//关闭文件
fclose(pf);
pf = NULL;
}
//test.c
#define _CRT_SECURE_NO_WARNINGS
#include "contact.h"
//动态版通讯录
void menu()
{
printf("***************************************************\n");
printf("*********** 1.添加联系人 ***********\n");
printf("*********** 2.删除指定联系人 ***********\n");
printf("*********** 3.修改指定联系人 ***********\n");
printf("*********** 4.查找指定联系人 ***********\n");
printf("*********** 5.显示联系人信息 ***********\n");
printf("*********** 6.对联系人进行排序 ***********\n");
printf("*********** 0.退出通讯录 ***********\n");
printf("***************************************************\n");
}
//实现一个通讯录
int main()
{
Contact Con;
InitContact(&Con);//对通讯录进行初始化
int input = 0;
int a = 0;
do
{
menu();
scanf("%d", &input);
//switch...case语句
switch (input)
{
case ADD:
AddContact(&Con);
break;
case DEL://删除
DelContact(&Con);
break;
case REV://修改
RevContact(&Con);
break;
case SEARCH://查找
SearchContact(&Con);
break;
case SHOW:
//打印通讯录
ShowContact(&Con);
break;
case SORT://排序
SortContact(&Con);
break;
case EXIT:
StoreContact(&Con);
Destory_Contact(&Con);
printf("退出通讯录\n");
break;
default:
printf("输入错误,请重新输入:\n");
break;
}
} while (input);
return 0;
}
//contact.h
#pragma once
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<assert.h>
#define Con_Name 10
#define Con_Sex 5
#define Con_Tele 12
#define Con_ADDr 30
#define Max_Space 3
#define One_Add 2
#define Start_Capacity 3
//定义通讯录结构体,并且重命名为Options
typedef struct Options
{
char Name[Con_Name];
int Age;
char Sex[Con_Sex];
char Tele[Con_Tele];
char Addr[Con_ADDr];
}Options;
typedef struct Contact
{
//静态版 Options date[100]; 初始化空间为100
Options *date;
int sz;//记录通讯录中的人数
int SpaceMax;//记录通讯录中的最大空间
}Contact;
//枚举类型
enum Chara
{
EXIT,
ADD,
DEL,
REV,
SEARCH,
SHOW,
SORT,
};
//声明添加函数
//初始化通讯录
void InitContact(Contact* Cp);
void AddContact(Contact* Cp);
void ShowContact(Contact* Cp);
void DelContact(Contact* Cp);
void RevContact(Contact* Cp);
void SearchContact(Contact* Cp);
void SortContact(Contact* Cp);
void Destory_Contact(Contact* Cp);
void StoreContact(Contact* Cp);
void InputContact(Contact* Cp);
2. Função de leitura de arquivos e regras de leitura e gravação de arquivos
O que é um documento?
Arquivos de programa, incluindo arquivos de programa de origem (sufixo .c), arquivos de objeto (sufixo de ambiente Windows .obj), programas executáveis (sufixo de ambiente Windows .exe); arquivos de dados, o conteúdo do arquivo não é necessariamente um programa, mas os dados lido e gravado quando o programa está em execução, como o arquivo do qual o programa precisa ler os dados ou o arquivo que gera o conteúdo. Este artigo é sobre arquivos de dados
Passos para operar arquivos em linguagem C:
1. Abra o arquivo
2. Ler/gravar arquivos
3. Feche o arquivo
O programa lê o arquivo significa ler as informações do arquivo nos dados do programa, e o programa grava o arquivo significa salvar os dados do programa no arquivo
1. Abra o arquivo
Ler arquivo - EIFE* pf = fopen("date.txt","r");
Gravar arquivo - EIFE* pf = fopen("date.txt","w");
Ler arquivo binário - EIFE* pf = fopen("date.txt","rb");
Gravar arquivo binário - EIFE* pf = fopen("date.txt","wb");
Quando o programa não consegue ler o arquivo, um ponteiro nulo será retornado; quando o programa não consegue escrever o arquivo, um novo arquivo será criado
O primeiro parâmetro da função fopen é o caminho do arquivo. O caminho do arquivo é dividido em caminho relativo e caminho absoluto. O caminho absoluto é o diretório do arquivo onde o arquivo começa a partir do nome do disco, como C:\Users\16656 \Desktop; e o caminho relativo é o diretório atual. O arquivo sob o arquivo; pf é o ponteiro do tipo de arquivo, conhecido como ponteiro de arquivo
Outros regulamentos:
.\\Debug - Arquivo de depuração no diretório atual
..\\Debug——Arquivo de depuração no diretório superior
2. Ler e gravar arquivos
ler/escrever dados de texto
função de entrada de texto fscanf fcanf( pf ," %d %f ", &(sa) , &(ss) );
função de saída de texto fprintf fcanf( pf ," %d %f ", sa , ss);
Ler texto de um arquivo em um programa ou escrever texto de um programa em um arquivo, pf é um ponteiro para o arquivo de destino
ler/escrever dados binários
fread função de entrada binária fread( &s ,sizeof (struct S) , 1 , pf);
função de saída binária fwrite fwrite( &s ,sizeof (struct S) , 1 , pf);
&s: os dados apontados devem ser lidos/gravados no arquivo
sizeof ( struct S ): o tamanho da mensagem a ser escrita/lida
1: o número de mensagens a serem lidas/escritas
pf: mantém um ponteiro para o arquivo
Ler e escrever caracteres/strings
fputc(' a ', pf ); grava caractere no arquivo
fputs(" Manghuangji", pf ) ; escreve a string no arquivo
fgetc(' a ', pf ) ; lê os caracteres do arquivo no programa
fputs(ch,3,pf) ; lê a string do arquivo no programa
Como o código a seguir
int main()
{
FILE* pf = fopen("data.txt", "r");
char ch[10] = "0";
fgets(ch,3,pf);
printf("%s", ch);
return 0;
}
3. Feche o arquivo
A função fclose para fechar o arquivo corresponde à função fopen
fclose(pf); pode fechar o arquivo e ao mesmo tempo precisar definir o ponteiro do arquivo para vazio
O blogueiro já escreve há muito tempo, se você puder dar ao blogueiro um combo triplo grátis para incentivá-lo, então acho que suas calças tailandesas são realmente picantes! ! !