【问题标题】:weird number appears on output-C奇怪的数字出现在输出-C
【发布时间】:2016-06-10 12:18:06
【问题描述】:

我做了一个这样的简单列表:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
 struct node{
    int am;
    struct node *next;
};
typedef struct node node;
int main(){
int n;
    node *head=(node *)malloc(sizeof(node));
    node *cur=head;
    printf("Give me a number:\n");
    scanf(" %d",head->am);
    cur=head;
    while(1){
        printf("Give me a number\n");
        scanf(" %d",&n);
        if(n==0)
            break;
        cur->am=n;
        cur->next=(node *)malloc(sizeof(node));
        cur=cur->next;
        cur->next=null;
    }
    travel(head);
    printf("Total nodes available :%d\n",count(head));
    system("pause");
    return 0;
}

现在 travel 应该遍历列表中的每个节点,并显示每个节点中保存的整数。

void travel(node *h){
    if(h==NULL)
        return;
    printf("Received data from node: \t %d\n",h->am);
    travel(h->next);
} 

现在的问题是,当调用 travel 时,它不会从第一个节点打印整数。它还会打印另一个“从节点接收的数据:”,后跟一个奇怪的数字。 例如 如果我给出 1,2,3,4 作为输入,这些就是结果

Received data from node:         2
Received data from node:         3
Received data from node:         4
Received data from node:         4026432

有什么想法吗?

【问题讨论】:

  • 没有直接关系,但递归遍历列表是个糟糕的主意。
  • scanf(" %d",head-&gt;am); 使它成为scanf("%d",&amp;head-&gt;am);
  • 启用编译器警告或获得更好的编译器。
  • 为什么不呢?你能准确点吗....head-&gt;am 不是变量的地址。

标签: c list data-structures


【解决方案1】:

现在的问题是,当调用 travel 时,它不会打印 第一个节点的整数

这可以从main()函数的这一部分准确知道

printf("Give me a number:\n");
scanf(" %d",head->am); //this is wrong use of scanf("%d",&head->am);
cur=head;
while(1){
    printf("Give me a number\n");
    scanf(" %d",&n);
    if(n==0)
        break;
    cur->am=n;

正如我所提到的,您扫描错误,但这并不重要,因为稍后在 while 循环中的代码中,您会以这种方式替换它...

  • 您扫描号码并将其存储在head-&gt;am
  • 然后您将head 分配给cur,因此head-&gt;amcur-&gt;am 现在都相同...所以在while 循环中,当您第一次将n 分配给cur-&gt;am 时,它被分配给@ 987654331@。所以这就解释了为什么你永远无法打印第一个节点。

解决方案:

  • 克服它......在while循环中,在分配cur-&gt;am=n之前尝试做:

    cur->next=(node *)malloc(sizeof(node));
    cur=cur->next;
    //then... assign
    curr->am=n;
    

这样你就不会丢失第一个节点。


建议:

正如有人已经说过,使用循环遍历/遍历列表要容易得多(没关系......如果你想递归地这样做)

下面是你如何使用循环:

 void travel(node *h)
 {
    if(h==NULL)
        return; //list is empty,consider printing "list empty" :)
    while(h!=NULL)
    {
        printf("Received data from node: \t %d\n",h->am);
        h=h->next;
    }
} 

在不更改 travel() 函数的情况下将所有代码放在一起,建议如下:

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

struct node
{
    int am;
    struct node *next;
};

typedef struct node node;

void travel(node *h);

int main() //I have a habit of returning values from main() :)
{
    int n;
    node *head=(node *)malloc(sizeof(node));
    node *cur=head;
    printf("Give me a number:\n");
    scanf(" %d",&head->am);
    cur=head;
    while(1)
    {
        printf("Give me a number\n");
        scanf(" %d",&n);
        if(n==0)
            break;
        cur->next=(node *)malloc(sizeof(node));
        cur=cur->next;
        cur->am=n;                     //NOTE:here's the change!
        cur->next=NULL;
    }
    travel(head);
    return 0; //just to signify successful compilation
}

void travel(node *h)
{
    if(h==NULL)
        return;
    printf("Received data from node: \t %d\n",h->am);
    travel(h->next);
}

示例输入: 5 6 3 1 0

样本输出:

Give me a number:
5
Give me a number
6
Give me a number
3
Give me a number
1
Give me a number
0
Received data from node:     5
Received data from node:     6
Received data from node:     3
Received data from node:     1

【讨论】:

  • @cssGEEK 你只能递归使用旅行吗?
  • 很好... @cssGEEK 希望上面的代码对解决您的问题有帮助:)
  • 我也从 main 返回值,但这是我在这里写的例子,我没有这样做:)
【解决方案2】:

有(至少)这些问题:

  1. scanf(" %d",head-&gt;am) 行是错误的,因为 scanf() 需要一个内存位置的地址,即预期值,意思是 &amp;head-&gt;am
  2. 您的循环扫描一个数字并将其放入当前节点,并且仅在它创建一个新节点之后。因此,您输入的第一个数字将被覆盖(在解决第一个问题之后),并且创建的最后一个节点将包含随机数据,因为循环将在输入 0 之后终止,但 之前 将任何内容放在最后节点。

【讨论】:

    【解决方案3】:

    我是这样提议的:

    int main(void){
        int n;
        node anchor = {0, NULL};//dummy head
        node *head, *cur = &anchor;
    
        while(1){
            printf("Give me a number\n");
            scanf("%d", &n);
            if(n==0)
                break;
            cur->next = malloc(sizeof(node));
            cur = cur->next;
            cur->am = n;
            cur->next = NULL;
        }
        head = anchor.next;
    
        travel(head);
        printf("Total nodes available :%d\n", count(head));
        return 0;
    }
    

    【讨论】:

    • 必须检查来自malloc() 的返回值。
    • @s7amuser 这是一个玩具程序,因此实际上不需要错误检查,但答案应该包括“为简单起见省略错误检查”。
    • @MichaelWalz 当然,但由于这个程序在任何情况下都非常小和简单,添加适当的错误检查和(如作者所指出的)由经验丰富的程序员处理的内存将使 OP 和社区受益.
    【解决方案4】:

    你在第一次 scanf 时错过了 &:

    scanf(" %d", &head->am);
    

    但它可以在 while 内完成所有的 scanf:

    int main(){
        node *head=0;
        node *cur=0;
        node *prev=0;
        while(1){
            prev = cur;
            cur=(node *)malloc(sizeof(node));
            cur->next=NULL;
            printf("Give me a number\n");
            scanf("%d",&cur->am);
            if(cur->am==0)
                break;
            if(head == NULL) head = cur;
            if(prev != NULL) prev->next = cur; 
        }
        travel(head);
        printf("Total nodes available :%d\n",count(head));
        return 0;
    }
    

    我希望我在这个 SO 编辑器中写的时候没有犯任何错误..

    正如有人所说,您应该释放链接列表..但这超出了这里的范围..

    HTH

    【讨论】:

    • curNULL 时,您将把第一个数字读入&amp;cur-&gt;am,因此您的代码将立即出现段错误。此外,您必须检查来自malloc 的返回地址,以确保它不是NULL
    • 不起作用。除非你正确,否则减一。 node *head=0; 也应该是 node *head=null; 或更好的 node *head=NULL;
    • @MichaelWalz ok ok .. 我不是编译器:D
    • @otopolsky 如果你不是编译器,你应该在发布之前编译并运行你的答案
    • @MichaelWalz .. 我期待这个,编译.. 它的工作.. 我应该写伪代码
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-07-13
    • 2021-12-03
    • 2011-06-14
    • 1970-01-01
    • 2023-01-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多