0

当我尝试打印我的链接列表时,我遇到了段错误。谁能解释为什么?我知道一个段错误意味着我正在访问我不应该访问的内存。我假设这意味着我没有正确设置我的指针。任何帮助都会很棒。我的代码...

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


struct node
{
    int val;
    struct node *next;             
}*head;

typedef struct node item;

int main() {

    item *curr, *head;

    head = NULL;

    char word = 'y';
    //int num[10];
    //int i = 0;

    while (word == 'y'){
    printf("Would you like to enter an integer? (y/n) ");
    scanf("%s", &word);

        if(word == 'y'){
            int temp = 0;
            printf("Enter an integer: ");
            scanf("%d", &temp);
            curr = (item *)malloc(sizeof(item));
            curr->val = temp;
            if (head == NULL){
                head = curr;
                head->next = NULL;
            }
            else {
            curr->next  = head;
            head = curr;
            }
        }
    }

    curr = head;

    while(curr != NULL) {
        printf("%d\n", curr->val); //seg fault happens here
        curr = curr->next ;
    }
    return 0;
}
4

4 回答 4

4

这个:

scanf("%s", &word);

是缓冲区溢出,因为%s会读取一个字符串,但你只有一个字符。这会调用未定义的行为;即使您只输入一个字符,scanf()也会在该字符后添加 0 终止符以生成正确的字符串。

更改声明word

char word[32];

并使用明确的大小进行扫描,以防止scanf()写入缓冲区之外:

scanf("%30s", word);

还要检查所有 I/O 和内存分配调用的返回值,因为它们可能会失败。

最后,不要malloc()在 C中转换 , 的返回值。

于 2013-06-03T07:59:13.193 回答
0

你被 抓住了scanf。首先,您希望读取单个字符,其格式为%c-在跳过任何前导空格%s读取下一个非空白字符序列。使用会导致错误,因为它会覆盖内存。%s

但是,如果您将格式更改为%c您的代码仍然无法正常工作,并且scanf再次出现这种情况。大多数格式scanf会跳过前导空格,但在读取字符时会这样做。所以如果你运行你的代码,你会看到:

Would you like to enter an integer? (y/n) y
Enter an integer: 10
Would you like to enter an integer? (y/n) 10

第二次在intoscanf之后读取了换行符,那不是 a ,然后继续打印出您的列表 -最后的。10wordy10

要在字符前跳过空格,请在格式字符串中添加一个空格,因此该行变为:

scanf(" %c", &word);

这一更改将允许您的代码工作,但您确实应该进行更多检查。scanf将返回它成功找到的项目数,您应该检查以确保用户确实输入了数字等。例如,如果用户不小心输入y了两次会发生什么:

Would you like to enter an integer? (y/n) y
Enter an integer: y
Would you like to enter an integer? (y/n) Enter an integer: 

这里发生的事情是scanf("%d", &temp)失败的,返回0的,并且没有存储任何东西到temp. 但是,由于您没有检查结果,因此您的程序继续运行,然后第二个y被下一个消耗scanf(" %c", &word)

还要看看你的if (head == NULL)陈述 - 这根本不是必需的,你可以用两行替换整个if/ else......这留作练习。

高温高压

于 2013-06-03T19:08:57.067 回答
0

关于内存泄漏,我建议您使用以下代码修复它们:

while(curr != NULL) {
    item* temp = curr; // store the current pointer
    printf("%d\n", curr->val);
    curr = curr->next ;
    free(temp); //free the current one now that curr points to the next
}

这将释放head循环的每次迭代中已打印的内容。

其他问题已经由其他海报解决。

于 2013-06-03T08:02:17.437 回答
0

*head将指针初始化为

item *curr=NULL, *head = NULL;

没有这个,if将不会执行,您将访问head节点的一些随机内存。while打印链表的循环可能不会终止并继续访问无效内存。

if (head == NULL){ 
  ...
}
于 2013-06-03T08:02:50.807 回答