额……链表读文件的过程中我DEBUG发现地址总是有偏移(不对)

Lamuna 2017-04-19 04:10:14
程序内容比较多,我就捡我这个问题相关的部分来发代码吧:

数据结构非常简单:

typedef struct Node{
int num;
struct Node *next;
}


有一个文本文件,里面装满了随机数,用空格或者什么的分隔每一个数,这个我不管怎么分,总之每次fscanf的都是一个int值就对了。
我最开始的append是每次都遍历一次链表,好把文件中新增的结构放在表的最后。思路是这样的:



对应的代码如下:

/*追加节点*/
int append(NODE *HEAD,int num) {
if (!HEAD || num < 0) {
return 0;
}

/*设置cur = HEAD*/
NODE *cur = HEAD;

/*cur一直遍历到最后*/
while (cur->next) {
cur = cur->next;
}

/*设置一个temp保存数据*/
NODE *temp = create_empty();
set_num(temp,num);

/*将cur的next指向temp*/
cur->next = temp;

return 1;
}


其实问题就已经解决了
但是我发现如果读取超过100万个内容的时候就开始成几何级的费时间了(其实超过10万个数就已经超过2秒了)。

于是我就想到每次直接在链表尾部增加不久好了么?于是就有了这个思路:


测试用的文件里面只有两个数,分别是7875和17912

满怀信心的F5,结果发现只输出17912……可是应该从head开始的话应该先有7875才对。

实现的代码还有相应做测试的main函数就一并都发来了:


void file_append(NODE *node,int num) {
if (!node) {
return;
}
printf("\nbefore_node addr:0x%p\n",&node);
NODE *temp = create_empty();
temp->num = num;
node->next = temp;
/*这样应该保证每次node都是最后一个节点?*/
node = node->next;
printf("\n temp addr:0x%p\n node addr:0x%p\n", &temp,&node);
}

int file_input(NODE *HEAD,const char *filename) {
if (!HEAD) {
return 0;
}

NODE *tail = HEAD;
while (tail->next) {
tail = tail->next;
}
/*这样一来,tail最终指向了最后一个节点*/

FILE *fp = fopen(filename, "r");
if (!fp) {
return 0;
}
while (!feof(fp)) {
int temp;
fscanf(fp, "%d", &temp);
printf("\n===============%d=================\n",temp);
file_append(tail, temp);
printf("\nnode(tail) addr:0x%p\n", &tail);
printf("\n====================================\n");
}
fclose(fp);

return 1;
}


int main(int argc,char *argv[]) {

if (argc < 2) {
printf("请指明文件名\n");
getchar();
return 1;
}

NODE *head = create_empty();

clock_t start, end;

start = clock();
if(!file_input(head, argv[1])){
printf("文件不存在!\n");
getchar();
return 2;
}
end = clock();

printf("文件加载完毕!共耗时%d毫秒。\n",end - start);
print_chaintab(head);

getchar();

remove_all_nodes(head);
free(head);
return 0;
}


运行结果如下:




结果发现每次node地址虽然变了,但都不是temp生成出来的……请问这是怎么回事?我的代码到底哪里出现了错误?是逻辑错误?还是我单纯的不会写?
...全文
215 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
自信男孩 2017-04-20
  • 打赏
  • 举报
回复
引用 5 楼 Lamuna 的回复:
[quote=引用 4 楼 cfjtaishan 的回复:] 每次都返回头指针,注意改一下函数的类型
改函数类型?返回头指针……是这个意思么?

NODE *file_append(NODE **node,int num){
    /*............*/
    return (*node);
}
这样改么?请问这样改的意义是什么? …………………… 迭代么?[/quote] 不是这样,当然这样做也是可以,类似strcpy一样;可以通过返回值也可以通过传入传出参数实现返回。 这是两种方式来获取链表的头节点:一种是传二重指针进去,第二种就是传一重指针,但是返回值返回头节点地址;当然,还有第三种,就是两个都做,不过没必要。
Lamuna 2017-04-20
  • 打赏
  • 举报
回复
另外,这个程序内存也是个问题
我生成了一个5.39M的文件,我分别在main的读取前,读取后和内存清理前设置了getchar()来观察内存变化:

int main(int argc,char *argv[]) {

if (argc < 2) {
printf("请指明文件名\n");
getchar();
return 1;
}

printf("开始读取文件……");
getchar();

NODE *head = create_empty();

clock_t start, end;

start = clock();
if(!file_input(head, argv[1])){
printf("文件不存在!\n");
getchar();
return 2;
}
end = clock();

printf("文件加载完毕!共耗时%d毫秒。\n",end - start);
/*print_chaintab(head);*/

getchar();

remove_all_nodes(head);
free(head);

printf("记录清除完毕……");
getchar();

return 0;
}


运行时只占用572K


读取完所有记录居然有将近54M的占用


我清除链表的部分是这样写的:


/*删除指定节点*/
int delete_node(NODE *node) {
if (!node) {
return 0;
}
memset(node, 0, sizeof(node));
free(node);
return 1;
}

/*清空链表所有节点*/
int remove_all_nodes(NODE *HEAD) {
if (!HEAD) {
return 0;
}
NODE *cur = HEAD;
NODE *temp = NULL;
while (cur) {
temp = cur->next;
cur->next = cur->next->next;
delete_node(temp);
cur = cur->next;
}
return 1;
}



按说这部分内存应该释放了才对?……可事实是内存占用依旧是这么多……


请问
1、为什么内存占用了50多M?这相当于是文件大小的10倍多了
2、到底我的清除链表有没有完成任务?这些内存是否已经被清除掉了?
3、为什么清除后的程序没有恢复到500多K?如何让它恢复成初始大小?
Lamuna 2017-04-20
  • 打赏
  • 举报
回复
引用 4 楼 cfjtaishan 的回复:
每次都返回头指针,注意改一下函数的类型
改函数类型?返回头指针……是这个意思么?

NODE *file_append(NODE **node,int num){
    /*............*/
    return (*node);
}
这样改么?请问这样改的意义是什么? …………………… 迭代么?
Lamuna 2017-04-20
  • 打赏
  • 举报
回复
strcpy.... char *strcpy(char *dest, const char *src) { char *tmp = dest; while ((*dest++ = *src++) != '\0') ; return tmp; } 额……返回一个char *,同时*dest在操作的时候也被修改了……这个意思?
自信男孩 2017-04-19
  • 打赏
  • 举报
回复
引用 3 楼 Lamuna 的回复:
[quote=引用 2 楼 zhao4zhong1 的回复:]
void file_append(NODE **node,int num) {
    if (!*node) {
        return;
    }
    printf("\nbefore_node addr:0x%p\n",*node);
    NODE *temp = create_empty();
    temp->num = num;
    (*node)->next = temp;
    /*这样应该保证每次node都是最后一个节点?*/
    (*node) = temp;
    printf("\n temp addr:0x%p\n node addr:0x%p\n", *node);
}
//...
        file_append(&tail, temp);
额……也就是说……如果……我想将一个指针作为函数的参数,在函数执行后应用参数的变化,就在实现函数时声明一个指向该指针的指针而不是获取该指针的地址么? [/quote] 每次都返回头指针,注意改一下函数的类型
Lamuna 2017-04-19
  • 打赏
  • 举报
回复
引用 2 楼 zhao4zhong1 的回复:
void file_append(NODE **node,int num) {
    if (!*node) {
        return;
    }
    printf("\nbefore_node addr:0x%p\n",*node);
    NODE *temp = create_empty();
    temp->num = num;
    (*node)->next = temp;
    /*这样应该保证每次node都是最后一个节点?*/
    (*node) = temp;
    printf("\n temp addr:0x%p\n node addr:0x%p\n", *node);
}
//...
        file_append(&tail, temp);
额……也就是说……如果……我想将一个指针作为函数的参数,在函数执行后应用参数的变化,就在实现函数时声明一个指向该指针的指针而不是获取该指针的地址么?
赵4老师 2017-04-19
  • 打赏
  • 举报
回复
void file_append(NODE **node,int num) {
    if (!*node) {
        return;
    }
    printf("\nbefore_node addr:0x%p\n",*node);
    NODE *temp = create_empty();
    temp->num = num;
    (*node)->next = temp;
    /*这样应该保证每次node都是最后一个节点?*/
    (*node) = temp;
    printf("\n temp addr:0x%p\n node addr:0x%p\n", *node);
}
//...
        file_append(&tail, temp);
赵4老师 2017-04-19
  • 打赏
  • 举报
回复
http://edu.csdn.net/course/detail/2344 C语言指针与汇编内存地址-一.代码要素

69,382

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧