【问题标题】:Linked list in C, addiotion of big numbers. SEGMENTATION FAULTC中的链表,添加大数字。分段故障
【发布时间】:2015-05-25 12:27:29
【问题描述】:

我正在做一个项目,我应该用 C 语言编写一个程序,我可以在其中添加长达 500 位的数字。

我认为我已经接近一个工作程序,但是当我运行该程序时,我不断收到“分段错误”消息。

我已经用谷歌搜索了这个,但似乎你可以从很多不同的原因中得到这个错误,你只需要弄清楚是哪个......

我对 C 不太熟悉,所以我想你们可以帮助我吗?

到目前为止,这是我的代码:

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

// ----------------------------- STRUCTEN --------------------------

typedef struct node *nodeptr;

struct node{
    int data;
    nodeptr next;
};

// ----------------------------- MAIN -------------------------------

int main(){

    // Det krävs 3 listor. En för tal1, en för tal2 och en för svaret.

    nodeptr list1 = NULL;
    nodeptr list2 = NULL;
    nodeptr answer = NULL;

    // Allokerer minnet för listorna.

    list1 = malloc(sizeof(nodeptr));
    list2 = malloc(sizeof(nodeptr));
    answer = malloc(sizeof(nodeptr));

    creat_linked_list(list1, list2, answer);    // Skapar de länkade listorna.

    char first_number[1000];                    // Det första talet får max vara 1000 tecken.

    printf("Enter the first number: ");
    scanf("%s",first_number);

    char second_number[1000];

    printf("Enter the second number: ");
    scanf("%c",second_number);

    int l1 = fill_list(list1, first_number);
    int l2 = fill_list(list2, second_number);

    addition(list1, list2, answer);

return;
}

// ------------------------------ skapa den linkade listan -----------------------------

creat_linked_list (nodeptr list1, nodeptr list2, nodeptr answer){

    // Påbörjar listorna.

    list1 -> next = NULL;
    list2 -> next = NULL;
    answer -> next = NULL;

    list1 -> data = 0;
    list2 -> data = 0;
    answer -> data = 0;


}

// ------------------------------------ Fyller i listorna -----------------------------

int fill_list (nodeptr pointer, char number[]) {

    int x = 0;
    int lenght = strlen(number);

    while (x < lenght){

        int digit = (int)number[x] - (int)'0'; //'0' = 48, tas bort från number[x] för att det är ascii-kodat.
        nodeptr temp = NULL;
        temp = malloc(sizeof(nodeptr));
        temp -> next = pointer -> next;
        pointer -> next = temp;
        temp -> data = digit;
        x = x + 1;

    }
return lenght;
}

// --------------------------------------- Kod för addition av tal -------------------

addition(nodeptr list1, nodeptr list2, nodeptr answer){

    int digit1, digit2;
    int sum, carry;

    while(1){

        if ((list1 -> next != NULL)&&(list2 -> next != NULL)){

            list1 = list1 -> next;  //Tar ut plats i lista 1
            digit1 = list1 -> data; //Tar ut värdet på den platsen.

            list2 = list2 -> next;  // --- || --- 2
            digit2 = list2 -> data; // --- || ---
        }
        else{
            if((list1 -> next = NULL)&&(list2 ->next != NULL)) {

                digit1 = 0; // Eftersom att det inte finns fler siffror i tal 1

                list2 = list2 -> next;  // Samma som IF-satsen innan.
                digit2 = list2 -> data;
            }

            else{

                digit2 = 0; //// Eftersom att det inte finns fler siffror i tal 2

                list1 = list1 -> next;
                digit1 = list1 -> data;
            }
        }
        nodeptr temp = NULL;
        temp = malloc(sizeof(nodeptr));
        temp -> next = NULL;

        temp -> data = (digit1 + digit2 + carry)%10;
        answer -> next = temp;
        answer = answer -> next;

        if ((digit1 + digit2 + carry) > 9) {
            carry = 1;
        }
        else{
            carry = 0;
        }

        if((list1 -> next = NULL)&&(list2 ->next = NULL)) {
            break;
        }

    }

    if (carry){                     // Om det ligger kvar en carry efter att alla tal har blivit adderade
                                    // så går vi in här.
        nodeptr temp = NULL;
        temp = malloc(sizeof(nodeptr));

        answer -> next = temp;
        answer -> data = carry;     
        answer -> next = NULL;      // Markerar slutet av answer listan. 
    }
}

当我运行代码时,我会到达需要输入第一个数字的部分。之后代码崩溃,我得到分段错误。

请帮忙!

【问题讨论】:

  • 在调试器中运行以定位崩溃,编辑您的问题以仅包含相关代码,包括涉及的变量及其声明、初始化和值。
  • 只是一个提示:你知道sizeof(nodeptr)实际上是什么...(剧透:它将是4或8),现在将该值与sizeof(struct node)比较...这就是为什么你'得到一个段错误
  • 好的,我解决了。在加法函数中,在 if((list1 -> next = NULL)&&(list2 ->next = NULL)) 行中我忘记添加额外的“=”。它应该是 list2 -> next == NULL.

标签: c linked-list segmentation-fault


【解决方案1】:

很容易找到您的一个问题,以及最有可能导致崩溃的原因:

list1 = malloc(sizeof(nodeptr));
list2 = malloc(sizeof(nodeptr));
answer = malloc(sizeof(nodeptr));

那些malloc 调用只分配nodeptr 的大小,这是一个指向结构的指针,而不是结构本身。这将只有 4 或 8 个字节,而您的结构可能有 8 或 12 个字节大。

【讨论】:

  • 解决办法是尽可能写list1 = malloc(sizeof *list1);
【解决方案2】:

除了其他问题,你还有

printf("Enter the second number: ");
scanf("%c",second_number);
// -----^

您只读取 1 个字符并稍后使用 second_number 作为字符串。它不是以null结尾的,所以当用作字符串时会导致段错误。

【讨论】:

  • 好的,谢谢!我将 C 更改为 S,现在它可以让我在崩溃前输入第二个数字!
  • @EliasVanOotegem 这些是扩展精度(“bignum”)数字,有 1,000 个十进制数字。没有原生类型可以处理这个问题。
  • @unwind:错过了,应该仔细阅读问题
【解决方案3】:

int不支持500位,C int只能从-2^15+1+2^15-1

查看this question 以了解有关 C 变量范围的更多信息。

【讨论】:

  • “我可以在其中添加长达 500 位的数字。”你是在告诉我 C 支持 int 类型的 500 位长数字吗?他缺少 malloc 的维度,它可以在运行程序时减少分段错误,但每个大于 int 范围的数字都会导致执行时间出现新的分段错误。
  • "int 不支持 500 位数字"。 OP 正在尝试使用本土机制来做到这一点,而不使用“int”。此外,标准中没有任何内容支持这种说法。关于“int”范围的下一个主张也没有任何证据支持。
猜你喜欢
  • 2014-01-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-06
  • 1970-01-01
  • 2014-07-16
  • 1970-01-01
相关资源
最近更新 更多