【问题标题】:Create an address book using a linked list使用链表创建地址簿
【发布时间】:2014-05-14 21:22:41
【问题描述】:

我昨天打开了一个帖子,询问我应该如何进行。这是我到目前为止所得到的(对不起语言,该程序将使用阿尔巴尼亚语,但我相信你明白了)。

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

void regjistrim();
void kerkim();
void modifikim();
void fshirje();
void rradhitje();
void display();
void load();

#define EMRI 50
#define MBIEMRI 50
#define ID 20
#define TEL 20
#define EMAIL 25

typedef struct node
{
    char emri[EMRI];
    char mbiemri[MBIEMRI];
    char id[ID];
    char tel[TEL];
    char email[EMAIL];
    struct node* next;
} node;

FILE* addressbook;
node* mynode;
node* curr;

int main(void)
{
    char input[2];
    int choice;

    load();

    printf("----------------ADDRESS BOOK----------------");
    printf("\n\n\t1 - Regjistrimi i ri\n");
    printf("\n\t2 - Kerkim\n");
    printf("\n\t3 - Modifikim\n");
    printf("\n\t4 - Fshirje\n");
    printf("\n\t5 - Rradhitje\n");
    printf("\n\t6 - Afishim i address book\n");
    printf("\n\t0 - Exit\n");

    fgets(input, 4, stdin);
    sscanf(input, "%d", &choice);

    while (choice < 0 || choice > 6)
    {
        printf("\nShtypni nje numer nga 0 - 6: \n");
        fgets(input, 4, stdin);
        sscanf(input, "%d", &choice);
    }

    switch (choice)
    {
        case 1:
            regjistrim();
            break;
        case 2:
            kerkim();
            break;
        case 3:
            modifikim();
            break;
        case 4:
            fshirje();
            break;
        case 5:
            rradhitje();
            break;
        case 6:
            display();
            break;
        case 0:
            exit(0);
            break;
    }

    return 0;
}

void load()
{
    addressbook = fopen("Addressbook.txt", "r");

    if (addressbook == NULL)
        printf("Could not open file.");

    node* mynode = malloc(sizeof(node));

    while (fscanf(addressbook, "%s %s %s %s %s", mynode->emri, mynode->mbiemri, mynode->id, mynode->tel, mynode->email) != EOF)
    {
        node* mynode = malloc(sizeof(node));
        mynode = mynode->next;
    }
    mynode = curr;
}


//Regjistron nje qytetar ne addressbook
void regjistrim()
{
    char input[2];
    char answer;

    do
    {
        node* newnode = malloc(sizeof(node));

        curr->next = newnode;

        addressbook = fopen("Addressbook.txt", "a+");

        printf("\nShtypni emrin: ");
        fgets(newnode->emri, EMRI, stdin);

        printf("\nShtypni mbiemrin: ");
        fgets(newnode->mbiemri, MBIEMRI, stdin);

        printf("\nShtypni ID-in: ");
        fgets(newnode->id, ID, stdin);

        printf("\nShtypni nr. telefoni: ");
        fgets(newnode->tel, TEL, stdin);

        printf("\nShtypni email-in: ");
        fgets(newnode->email, EMAIL, stdin);

        fprintf(addressbook, "Emri: %sMbiemri: %sID: %sNr. telefoni: %sEmail: %s\n", newnode->emri, newnode->mbiemri, newnode->id, newnode->tel, newnode->email);

        fclose(addressbook);

        printf("\nShtypni y/Y neqoftese doni te regjistroni person tjeter: ");
        fgets(input, 50, stdin);
        sscanf(input, "%c", &answer);

        curr = newnode;
    }
    while(answer == 'y' || answer == 'Y');
}

void kerkim()
{
    //TODO
}

void modifikim()
{
    //TODO
}

void fshirje()
{
    //TODO
}

void rradhitje()
{
    //TODO
}

void display()
{
    //TODO
}

目前我遇到了段错误:while (fscanf(addressbook, "%s %s %s %s %s", mynode-&gt;emri, mynode-&gt;mbiemri, mynode-&gt;id, mynode-&gt;tel, mynode-&gt;email) != EOF)

我主要关心load() 函数,它会在用户执行任何操作之前将任何条目加载到链接列表中(如果有的话)。

提前谢谢你。

【问题讨论】:

  • 你试过用调试器单步调试吗?如果你看到一个段错误,你有一个空引用。找到它,弄清楚它发生的原因,然后你就可以上路了。
  • 全局变量mynodecurr是什么意思?你打算用它们做什么?
  • (1)并且你在两者的本地范围内使用了相同的名称。
  • (2)fprintf(addressbook, "Emri: %sMbiemri: %sID: %sNr. telefoni: %sEmail: %s\n"...fscanf(addressbook, "%s %s %s %s %s"...:文件格式不同。
  • 您可能想尝试验证您打开的文件是否有效,并在失败时使用perror()fprintf(stderr, ...) 报告错误,然后是exit(EXIT_FAILURE)。现在你的错误报告没有被刷新到标准输出,因为没有换行符,你盲目地进入一个使用 NULL 文件指针的 while 循环,因此由于调用未定义的行为而导致错误。此外,load() 中的前向链接读取循环完全不正确。如果您想在阅读时转发链接,请使用指针指向指针。

标签: c linked-list segmentation-fault


【解决方案1】:

我建议您查看现有的链表实现。添加用于插入节点、附加节点、删除节点以及诸如此类的辅助函数。一旦你有一个列表本身的工作实现,你将更容易编写利用链表数据结构的代码。

考虑更改您的node 结构以包含指向实际数据的指针和指向下一个节点的指针(而不是实际在struct 本身中包含数据)。更好地练习这种方式。您甚至可以通过将 void 指针用作“通用”指针来扩展您的链表实现以支持任何数据类型。

链表的分段错误通常表明您在代码中的某处取消引用 NULL 指针(但并非总是如此!)。确保您没有引用已删除的节点或尚未分配的节点。

如果您对当前的实现感到满意,请使用gdb 单步执行代码并在程序出现段错误的位置设置断点。您应该不会很难找到错误所在。

【讨论】:

    【解决方案2】:

    如果您想创建一个链接列表,请尝试这样做 替换此代码

    node* mynode = malloc(sizeof(node));
    
        while (fscanf(addressbook, "%s %s %s %s %s", mynode->emri, mynode->mbiemri, mynode->id, mynode->tel, mynode->email) == 5)
        {
            node* mynode = malloc(sizeof(node));
            mynode = mynode->next;
        }
        mynode = curr;
    

    有了这个

    node* mynodeLocal = malloc(sizeof(node));
        node *secondLastNode;
        while (fscanf(addressbook, "%s %s %s %s %s", mynodeLocal->emri, mynodeLocal->mbiemri, mynodeLocal->id, mynodeLocal->tel, mynodeLocal->email) != EOF)
        {
         secondLastNode = mynodeLocal;
            mynodeLocal->next = malloc(sizeof(node));
            mynodeLocal = mynodeLocal->next;
            mynodeLocal->next = NULL;
    
        }
        secondeLastNode->next = NULL;
        mynode = curr;//Change this line according to your requirement.
    

    【讨论】:

    • 我在使用 fscanf() 时仍然遇到段错误。
    • 尝试将 !=EOF 替换为 ==5
    • 循环打印一些东西,通过这样做你可以检查 fscanf() 是否正在读取。例如,您可以尝试打印 mynodeLocal->emri.
    • 看来问题是无法创建文件。当文件已经被创建时,加载函数被正确执行。我不知道发生了什么事。该文件在函数void regjistrim() 中正确创建,该函数在地址簿中注册了一个人。
    • 带负载功能的问题解决了吗?现在你有 regjisrim() 的问题吗?
    猜你喜欢
    • 1970-01-01
    • 2013-09-17
    • 2012-01-26
    • 1970-01-01
    • 1970-01-01
    • 2020-05-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多