通过文件IO来进行写入文件,读取文件等操作
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#define TRUE 1
#define FALSE 0
#define MAX_ID_LEN 10
#define MAX_NAME_LEN 30
#define FILE_NAME "data"
typedef int BOOL;
typedef struct _DATE{
int year;
int month;
int day;
}DATE_T;
typedef struct _STUDENT{
char id[MAX_ID_LEN];
char name[MAX_NAME_LEN];
DATE_T birthday;
int height;
struct _STUDENT * next;
}STUDENT_T;
BOOL toDate(DATE_T * date,char *szBuf)
{
char * cha=(char*)szBuf;
if(sscanf(cha,"%d-%d-%d",&(date->year),&(date->month),&(date->day))!=-1) {
return TRUE;
}
else
{
return FALSE;
}
}
void insert(STUDENT_T ** head,STUDENT_T *data)
{
//二级指针,要解引用,&head是实参,&head+1会加上结构体占用的字节数
//
while(*head)
{
if(strcmp(data->id,(*head)->id)>0)
{
//如果头节点的下一个存在
//优先级要注意,*head->next会先做head->next
if((*head)->next && strcmp(data->id,(*head)->next->id)<0)
{
data->next=(*head)->next;
(*head)->next=data;
break;
}
else if((*head)->next && strcmp(data->id,(*head)->next->id)>=0)
{
*head=(*head)->next;
}
else
{
(*head)->next=data;
break;
}
}
else
{
//temp指针没有分配新的内存,所以不需要释放,函数调用完会把局部变量删除
//二级指针怎么改变一级指针的指向
STUDENT_T *temp=NULL;
temp=data;
data=*head;
*head=temp;
(*head)->next=data;
break;
}
}
}
void save(STUDENT_T *head)
{
FILE *fp=NULL;
char str[100];
sprintf(str,"%s%s%s%s",getenv("HOME"),"/linux/cproject/",FILE_NAME,".txt");
printf("save str:%s\n",str);
fp=fopen(str,"a+");
if(fp==NULL)
{
exit(-1);
}
while(head)
{
//也可以用*head.成员
fputs("id:\t",fp);
fputs(head->id,fp);
fputc('\0',fp);
fputc('\n',fp);
fputs("name:\t",fp);
fputs(head->name,fp);
fputc('\0',fp);
fputc('\n',fp);
//这里要用.运算符,因为STUDENT_T中定义的不是Date
fprintf(fp,"%d",(head->birthday).year);
fputs("-",fp);
fprintf(fp,"%d",(head->birthday).month);
fputs("-",fp);
fprintf(fp,"%d",(head->birthday).day);
fputc('\0',fp);
fputc('\n',fp);
fprintf(fp,"%d",head->height);
fputc('\0',fp);
fputc('\n',fp);
head=head->next;
}
fclose(fp);
}
void load(STUDENT_T **head)
{
//load是通过文件流来读取学生信息的
FILE * fp=NULL;
char str1[100];
sprintf(str1,"%s%s%s%s",getenv("HOME"),"/linux/cproject/",FILE_NAME,".txt");
fp=fopen(str1,"r");
printf("load str1:%s\n",str1);
if(fp==NULL)
{
printf("file not exists!");
exit(-1);
}
char str[50];
while((fgets(str,50,fp))!=NULL)
{
fputs(str,stdout);
fputs("\n",stdout);
}
fclose(fp);
}
void output(STUDENT_T * head)
{
//output是读取内存中学生链表的信息,而不是从文件流中读取
while(head)
{
printf("id:\t%s \n name:\t%s \n birthday:\t%d-%d-%d \n height:\t %d \n",
head->id,head->name,(head->birthday).year,(head->birthday).month,(head->birthday).day,
head->height);
head=head->next;
}
}
void release(STUDENT_T * head)
{
//释放占用的内存
while(head->next->next)
{
STUDENT_T * temp=NULL;
temp=head->next;
//指针指向的内存被释放之后,指针变量中的值不变,也就是说指针指向的内存区域不变,虽然这块内存可能被释放了
free(head);
//所以要重新给head指针赋值
head=temp;
temp=temp->next;
}
//从子代开始释放,这里只剩下两个结构体了
free(head->next);
free(head);
}
STUDENT_T * create()
{
STUDENT_T *head=NULL,*p=NULL;
char szBuf[1024];
while(1)
{
p=(STUDENT_T *)malloc(sizeof(STUDENT_T));
if(!p)
{
printf("Memory overflow!\n");
break;
}
printf("Please input id (0 for exit): ");
scanf("%s",p->id);
if(strcmp(p->id,"0")==0)
{
break;
}
printf("Please input name: ");
scanf("%s",p->name);
do
{
printf("Please input date(format of yyyy-mm-dd): ");
scanf("%s",szBuf);
//结构体当参数传递时,传的是值而不是地址
if(toDate(&p->birthday,szBuf))
{
break;
}
else
{
printf("Invalid date format\n");
}
}while(1);
printf("Please input height (unit of cm): ");
//只有数组名或者指针(字符串)才是地址,才能用->
scanf("%d",&p->height);
//一开始执行这里
if (!head)
{
head=p;
}
else
{
//传的是指针变量的地址,这个指针是指向STUDENT_T结构体的,所以用的时候要先解引用
insert(&head,p);
}
}
return head;
}
int main()
{
STUDENT_T *head=create();
if(!head)
{
printf("Create list failed!\n");
return -1;
}
printf("The student info created: \n");
output(head);
save(head);
//release(head);
load(&head);
printf("The student info loaded: \n");
output(head);
release(head);
return 0;
}