请问C语言如何把链表存入文件,从文件读取到链表

Zip Zou 在校大学生  2014-12-18 06:29:06
Consumer* read_list()
{
FILE *fp;
if ((fp = fopen("CONSUMER.dat", "rb")) == NULL)
{
printf("无法读取 CONSUMER.dat\n");
return NULL;
}
int sign;
Consumer *s,*p,*head;

head= (Consumer*)malloc(SIZE_C);
if (head == NULL)
{
printf("读取失败!内存空间申请不足!\n");
return NULL;
}
fseek(fp, 0, SEEK_END);
if (ftell(fp) == 0)
{
return NULL;
}
p = head;
p->next = NULL;
while (feof(fp))
{
s = (Consumer*)malloc(SIZE_C);
fread(s, SIZE_C, 1, fp);
p->next = s;
p = s;
p->next = NULL;
}
fclose(fp);
return head;
}//读取文件到链表
int save_consumer(Consumer *p)
{
FILE *fp;
Consumer *head;
head = p;//p为已经构建好的链表
if ((fp = fopen("CONSUMER.dat", "ab+")) == NULL)
{
printf("无法打开 CONSUMER.dat!\n");
return -1;
}
while (p != NULL)
{

fwrite(p, SIZE_C, 1, fp);
p = p->next;
}
fclose(fp);
return 1;
}//储存链表到文件
...全文
23292 3 收藏 12
写回复
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
请问一下SIZE_C是什么意思呢?
回复
引用 10 楼 q3733353520 的回复:
[quote=引用 9 楼 zhao4zhong1 的回复:] [quote=引用 7 楼 q3733353520 的回复:] [quote=引用 6 楼 zhao4zhong1 的回复:] 推荐使用WinHex软件查看硬盘或文件或内存中的原始字节内容。 不要把 fopen("...","...");fscanf,fprintf,fgets,fgetc,fclose //读时把\r\n替换成\n,写时把\n替换成\r\n;读到\x1a就设置EOF;读写的内容当字符看待 和 fopen("...","...b");fseek,fread,fwrite,fgetc,fclose //不作以上替换,遇到\x1a仍继续读;读写的内容当字节看待 弄混了
linux 咋看呢[/quote]
#include <stdio.h>
#include <string.h>
FILE *f;
char buffer[4096];
int r,a;
void HexDump(char *buf,int len,int addr) {
    int i,j,k;
    char binstr[80];

    for (i=0;i<len;i++) {
        if (0==(i%16)) {
            sprintf(binstr,"%08x -",i+addr);
            sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);
        } else if (15==(i%16)) {
            sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);
            sprintf(binstr,"%s  ",binstr);
            for (j=i-15;j<=i;j++) {
                sprintf(binstr,"%s%c",binstr,('!'<buf[j]&&buf[j]<='~')?buf[j]:'.');
            }
            printf("%s\n",binstr);
        } else {
            sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);
        }
    }
    if (0!=(i%16)) {
        k=16-(i%16);
        for (j=0;j<k;j++) {
            sprintf(binstr,"%s   ",binstr);
        }
        sprintf(binstr,"%s  ",binstr);
        k=16-k;
        for (j=i-k;j<i;j++) {
            sprintf(binstr,"%s%c",binstr,('!'<buf[j]&&buf[j]<='~')?buf[j]:'.');
        }
        printf("%s\n",binstr);
    }
}
int main(int argc,char **argv) {
    if (argc<2) {
        fprintf(stderr,"Usage: %s filename.ext\n",argv[0]);
        return 2;
    }
    f=fopen(argv[1],"rb");
    if (NULL==f) {
        fprintf(stderr,"Can not open file [%s]!\n",argv[1]);
        return 1;
    }
    a=0;
    while (1) {
        r=fread(buffer,1,4096,f);
        HexDump(buffer,r,a);
        a+=r;
        if (r<4096) break;
    }
    fclose(f);
    return 0;
}
[/quote] 哦, 谢谢赵老师[/quote] 文件的其实 od 可以,内存还是用gdb调试好点
回复
引用 9 楼 zhao4zhong1 的回复:
[quote=引用 7 楼 q3733353520 的回复:] [quote=引用 6 楼 zhao4zhong1 的回复:] 推荐使用WinHex软件查看硬盘或文件或内存中的原始字节内容。 不要把 fopen("...","...");fscanf,fprintf,fgets,fgetc,fclose //读时把\r\n替换成\n,写时把\n替换成\r\n;读到\x1a就设置EOF;读写的内容当字符看待 和 fopen("...","...b");fseek,fread,fwrite,fgetc,fclose //不作以上替换,遇到\x1a仍继续读;读写的内容当字节看待 弄混了
linux 咋看呢[/quote]
#include <stdio.h>
#include <string.h>
FILE *f;
char buffer[4096];
int r,a;
void HexDump(char *buf,int len,int addr) {
    int i,j,k;
    char binstr[80];

    for (i=0;i<len;i++) {
        if (0==(i%16)) {
            sprintf(binstr,"%08x -",i+addr);
            sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);
        } else if (15==(i%16)) {
            sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);
            sprintf(binstr,"%s  ",binstr);
            for (j=i-15;j<=i;j++) {
                sprintf(binstr,"%s%c",binstr,('!'<buf[j]&&buf[j]<='~')?buf[j]:'.');
            }
            printf("%s\n",binstr);
        } else {
            sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);
        }
    }
    if (0!=(i%16)) {
        k=16-(i%16);
        for (j=0;j<k;j++) {
            sprintf(binstr,"%s   ",binstr);
        }
        sprintf(binstr,"%s  ",binstr);
        k=16-k;
        for (j=i-k;j<i;j++) {
            sprintf(binstr,"%s%c",binstr,('!'<buf[j]&&buf[j]<='~')?buf[j]:'.');
        }
        printf("%s\n",binstr);
    }
}
int main(int argc,char **argv) {
    if (argc<2) {
        fprintf(stderr,"Usage: %s filename.ext\n",argv[0]);
        return 2;
    }
    f=fopen(argv[1],"rb");
    if (NULL==f) {
        fprintf(stderr,"Can not open file [%s]!\n",argv[1]);
        return 1;
    }
    a=0;
    while (1) {
        r=fread(buffer,1,4096,f);
        HexDump(buffer,r,a);
        a+=r;
        if (r<4096) break;
    }
    fclose(f);
    return 0;
}
[/quote] 哦, 谢谢赵老师
回复
引用 6 楼 zhao4zhong1 的回复:
推荐使用WinHex软件查看硬盘或文件或内存中的原始字节内容。 不要把 fopen("...","...");fscanf,fprintf,fgets,fgetc,fclose //读时把\r\n替换成\n,写时把\n替换成\r\n;读到\x1a就设置EOF;读写的内容当字符看待 和 fopen("...","...b");fseek,fread,fwrite,fgetc,fclose //不作以上替换,遇到\x1a仍继续读;读写的内容当字节看待 弄混了
linux 咋看呢
回复
赵4老师 2014-12-20
引用 7 楼 q3733353520 的回复:
[quote=引用 6 楼 zhao4zhong1 的回复:] 推荐使用WinHex软件查看硬盘或文件或内存中的原始字节内容。 不要把 fopen("...","...");fscanf,fprintf,fgets,fgetc,fclose //读时把\r\n替换成\n,写时把\n替换成\r\n;读到\x1a就设置EOF;读写的内容当字符看待 和 fopen("...","...b");fseek,fread,fwrite,fgetc,fclose //不作以上替换,遇到\x1a仍继续读;读写的内容当字节看待 弄混了
linux 咋看呢[/quote]
#include <stdio.h>
#include <string.h>
FILE *f;
char buffer[4096];
int r,a;
void HexDump(char *buf,int len,int addr) {
    int i,j,k;
    char binstr[80];

    for (i=0;i<len;i++) {
        if (0==(i%16)) {
            sprintf(binstr,"%08x -",i+addr);
            sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);
        } else if (15==(i%16)) {
            sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);
            sprintf(binstr,"%s  ",binstr);
            for (j=i-15;j<=i;j++) {
                sprintf(binstr,"%s%c",binstr,('!'<buf[j]&&buf[j]<='~')?buf[j]:'.');
            }
            printf("%s\n",binstr);
        } else {
            sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);
        }
    }
    if (0!=(i%16)) {
        k=16-(i%16);
        for (j=0;j<k;j++) {
            sprintf(binstr,"%s   ",binstr);
        }
        sprintf(binstr,"%s  ",binstr);
        k=16-k;
        for (j=i-k;j<i;j++) {
            sprintf(binstr,"%s%c",binstr,('!'<buf[j]&&buf[j]<='~')?buf[j]:'.');
        }
        printf("%s\n",binstr);
    }
}
int main(int argc,char **argv) {
    if (argc<2) {
        fprintf(stderr,"Usage: %s filename.ext\n",argv[0]);
        return 2;
    }
    f=fopen(argv[1],"rb");
    if (NULL==f) {
        fprintf(stderr,"Can not open file [%s]!\n",argv[1]);
        return 1;
    }
    a=0;
    while (1) {
        r=fread(buffer,1,4096,f);
        HexDump(buffer,r,a);
        a+=r;
        if (r<4096) break;
    }
    fclose(f);
    return 0;
}
回复
w74839520 2014-12-20
好帖子。学习学习。
回复
xionggch 2014-12-19

Consumer* read_list()
{
	FILE *fp;
	if ((fp = fopen("CONSUMER.dat", "rb")) == NULL)
	{
		printf("无法读取 CONSUMER.dat\n");
		return NULL;
	}
	int sign;
	Consumer *s,*p,*head;
	
	head= (Consumer*)malloc(SIZE_C);
	if (head == NULL)
	{
		printf("读取失败!内存空间申请不足!\n");
		return NULL;
	}
	fseek(fp, 0, SEEK_END);
	if (ftell(fp) == 0)
	{
		return NULL;
	}
	p = head;
	p->next = NULL;
	while (feof(fp))
	{
		s = (Consumer*)malloc(SIZE_C);
		//fread(s, SIZE_C, 1, fp);
                fread(s, sizeof(char), SIZE_C, fp);
		p->next = s;
		p = s;
		p->next = NULL;
	}
	fclose(fp);
	return head;
}//读取文件到链表
int save_consumer(Consumer *p)
{
	FILE *fp;
	Consumer *head;
	head = p;//p为已经构建好的链表
	//if ((fp = fopen("CONSUMER.dat", "ab+")) == NULL)
        if ((fp = fopen("CONSUMER.dat", "wb")) == NULL)
	{
		printf("无法打开 CONSUMER.dat!\n");
		return -1;
	}
	while (p != NULL)
	{
		//fwrite(p, SIZE_C, 1, fp);
                fwrite(p, sizeof(char), SIZE_C, fp);
		p = p->next;
	}
	fclose(fp);
	return 1;
}//储存链表到文件
回复
Zip Zou 2014-12-19
3楼,你的分析是对的,就是feof函数的原因,所以我改成了fread的返回值去判断,在读文件时我再设置了文件指针的位置,用fseek,这样就可以实现了,我逐语句调试,发现feof做循环控制条件的话,循环执行3次,所以feof正如你分析的一样!
回复
赵4老师 2014-12-19
推荐使用WinHex软件查看硬盘或文件或内存中的原始字节内容。 不要把 fopen("...","...");fscanf,fprintf,fgets,fgetc,fclose //读时把\r\n替换成\n,写时把\n替换成\r\n;读到\x1a就设置EOF;读写的内容当字符看待 和 fopen("...","...b");fseek,fread,fwrite,fgetc,fclose //不作以上替换,遇到\x1a仍继续读;读写的内容当字节看待 弄混了
回复
a138762698828 2014-12-18
while (!feof(fp)) { s = (Consumer*)malloc(SIZE_C); fread(s, sizeof(SIZE_C), 1, fp); p->next = s; p = s; p->next = NULL; } 试下能不能运行, while(!feof(fp))是循环来控制文件内容的读取, 例如当前读取的内容不是文件尾部,则feof(fp)为0,去非运算后为1,那么就继续循环执行! 如果执行到文件尾部,则feof(fp)为1,取非为0,循环借宿,读取文件结束。
回复
li4c 2014-12-18
for reference only,我就只写文件到链表了,链表o大n文件用对应的fprintf就可以了
/*************************************************************************
    > File Name: test3.c
    > Author: jukay
    > Mail: hellojukay@163.com 
    > Created Time: 2014年12月18日 星期四 19时29分18秒
 ************************************************************************/

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

struct date
{
	char str[3];
	struct date *next;
};

//链表长度为len
struct date *create_link(int len)
{
	struct date *head;
	struct date *tmp;
	int i;
	head = malloc(sizeof(struct date));
	tmp = head;
	for(i = 1; i < len; ++i)
	{
		head ->next = malloc(sizeof(struct date));
		head = head ->next;
	}
	head ->next = NULL;
	return tmp;
}

//读文件到链表
void read_file_to_link(struct date *head,FILE *fp)
{
	if(head == NULL || fp == NULL)
	{
		fprintf(stderr,"null pointer");
		exit(EXIT_FAILURE);
	}
		do
		{
			fscanf(fp,"%3s",head ->str);
			head = head ->next;
		}while(head != NULL);
}

//显示链表中的内容
void print_link(struct date *head)
{
	if(head == NULL)
	{
		fprintf(stderr,"null pointer");
		exit(EXIT_FAILURE);
	}
	do
	{
		printf("%s",head ->str);
		head = head ->next;
	}while(head != NULL);
}

int main()
{
	FILE *fp;
	int len; //链表长度
	scanf("%d",&len);
	fp = fopen("a.txt","r");
	struct date *head;
	head = create_link(len);
	read_file_to_link(head,fp);
	print_link(head);

	exit(EXIT_SUCCESS);
}
回复
Zip Zou 2014-12-18
有知道的吗?
回复
发动态
发帖子
C语言
创建于2007-09-28

6.3w+

社区成员

C语言相关问题讨论
申请成为版主
社区公告
暂无公告