C链表问题

时间:2017-12-03 23:50:03

标签: c data-structures struct linked-list

我真的需要你对我的程序的帮助。我是C的新手,需要在我的项目中创建一个链表。

我在macOS上使用xcode。 我的代码在这里:

typedef struct person
{
    char name[500];
    char telnum[16];
    char wohnort[500];
    struct person *next;

}person;

person *head=NULL;
void einlesen()
{
    person *p;
    char name[30];
    char telnum[16];
    char wohnort[30];
    //char buff1[15], buff2[15];
    int cnt=0;

    FILE *fp=fopen("Data2.txt", "r");
    if(fp==NULL)
    {
        printf("File konnte nicht geoeffnet werden!\n");
        exit(1);
    }
    while(fscanf(fp," %29[A-z ]\t%s\t%s", &name, &telnum, &wohnort)!=EOF)
    {

        cnt++;


        printf("Datei gefunden!\nDaten:%s, %s, %s\n", name, telnum, wohnort);


        if(head == NULL){
            head = (person*)malloc(sizeof(person));
            strcpy(head->name, name);
            strcpy(head->telnum, telnum);
            strcpy(head->wohnort, wohnort);
            head->next = NULL;
        }
        else{
            p = head;
            while(p->next != NULL)
            {
                p = p->next;
            }

            p->next = (person*)malloc(sizeof(person));
            strcpy(p->next->name,name);
            strcpy(p->next->telnum,telnum);
            strcpy(p->next->wohnort,wohnort);
            p->next->next = NULL;
        }

    }
    printf("Die Daten von %d Personen wurden eingelesen!\n\n", cnt);
    fclose(fp);
}

void addieren()
{   char name[30];
    char telnum[16];
    char wohnort[30];
    person *p = head;

    printf("Bitte den Namen der hinzufuegenden Person eingeben:\n");
    scanf(" %29s", name);
    while(getchar() != '\n');
    printf("\nBitte die Telefunnumer der hinzufuegenden Person eingeben:\n");
    scanf(" %15s", telnum);
    while(getchar() != '\n');
    printf("\nBitte den Wohnort der hinzufuegenden Person eingeben:\n");
    scanf(" %29s", wohnort);
    while(getchar() != '\n');

    if(p==NULL) return;
    while(p->next)
    {
        p=p->next;
    }
    p->next = (person*)malloc(sizeof(person));
    strcpy(p->next->name, name);
    strcpy(p->next->telnum, telnum);
    strcpy(p->next->wohnort, wohnort);
    p->next->next=NULL;
}

我在我的主要功能中有这个:

int main()
{   
    person *p1=head;


    einlesen();
    addieren();
    while(p1 !=NULL)
    {
        printf("Namen: %s\n", p1->name);
        p1=p1->next;
    }

    return 0;

}

它已经从文件中读取了数据,我想为它添加一些新记录并将其打印到屏幕上。这将返回0,并且不会在屏幕上真正打印列表。

稍后我需要为我的程序添加更多功能,例如: -deletefromlist - 修改元素 - 链表中的搜索 - 保存到文件 - 和一个菜单

2 个答案:

答案 0 :(得分:0)

您正在addieren函数中创建一个新人,而不是接收您在main函数上创建的人。你需要接收它作为一个参数,类似的东西

int addieren(person **head) { ... }

在主要上你应该

addieren(&p1);

注意双指针,这样你就可以传递指针并在函数内修改它。你也可能应该返回一个int来确认操作是否成功

答案 1 :(得分:0)

我没有看到任何特别的问题,所以我首先指出一些错误,也许当你添加一个问题(以问号结尾)时,你可以ping我更新。

while(fscanf(fp," %29[A-z ]\t%s\t%s", &name, &telnum, &wohnort)!=EOF)

首先我要说的是,在第一次使用功能之前,我是一名阅读手册的人。事实上,作为程序员,我很确定它对我们的期望。当然,我们必须知道要寻找哪些手册,因为互联网是一个危险的地方,人们偶尔会撒谎。 OpenGroup手册很好。例如,如果您输入Google“Opengroup fscanf”,您会找到fscanf的手册,该手册将回答许多问题我确定...

手册指出所有空格都被视为相同,作为一个试图尽可能多地读取和丢弃空白的指令。因此,普通空间与格式说明符中的\t具有相同的含义(至少在您的上下文中)...所以如果你的问题是“为什么所有的空格都被处理相同的话”?然后答案是“因为这是手册所说的应该做的。”

您正在阅读的固定宽度字段可能无法翻译,在一个场景中,手册还描述了测试的第一个字符在哪里无法匹配标准([A-z ],这看起来非常可疑,而您通过阅读手册可能会意识到这不是你想要的。这将导致scanf的返回值(来自0),对于您的代码,它看起来像成功的读取。

这是一个惯用的指南:让我们首先计算您想要读入的对象的数量......在这里,它们是从您的代码中逐字复制的:&name, &telnum, &wohnort ...他们三个。

现在,取这个数字,三个,并将它与fscanf返回的数据进行比较......如果这两个数字匹配,那么你可以安全地使用所有三个参数(尽管如下所述,它们可能不一定包含您希望它们包含的值。)

您也不应在&nametelnum使用wohnort(地址)运算符。 char [10]数组上的address-of运算符将导致char (*)[10]表达式,其中 - 您肯定需要一个简单的vanilla char *表达式。因此,正确的做法是让Cs隐含“数组表达式到指针表达式”转换为你做这件事。

下面可能更接近你想要的。我对[A-z ]事情的建议是,列出要包含在这些括号中的每个字符,或者如果要列出要的每个字符,请使用[^...]排除。需要说明的是,C格式字符串中没有范围,以防你的问题是什么。 e.g:

while(fscanf(fp," %29[qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM ] %s %s", name, telnum, wohnort)==3)

请注意,它还没有完全存在。 32字节输入的29个字节有可能被读入该固定宽度字段,在流上留下三个字符。也许它们不是空格,在这种情况下,你的空白指令会默默地失败,剩下的三个字符将被视为telnum

如果只是在了解相应的手册之前,您应该尝试每次调用scanf时只读取一个项目。

任何集合都不应要求n调用malloc来存储n个对象。如果您设法完成此(无疑是自我分配)任务,我建议您将下一个优先级分配为每个呼叫malloc的多个节点,或者更好的是,您没有获得的便利要free()每个字符串fscanf 返回,您可以从相同的技术中受益;期望调用者分配列表,向您传递所需的所有存储,以及从列表中添加,删除等项目。所有的功能都是修改传入的对象。

while(getchar() != '\n');

以上您认识到EOF可能会发生......您认为getchar()会在发生这种情况时返回什么?不是'\n',这是肯定的,它会无限期地返回那个(不是''\ n')值,因此是一个无限循环。试图解决这个问题会使循环复杂化;你需要存储角色,例如:

int c;
while ((c = getchar()) != EOF && c != '\n');

更明确的替代方案实际上是使用fread,例如

char c;
while (fread(&c, 1, 1, stdin) && c != '\n');

尽管如此,更好的是,正在使用fscanf,根据手册的解释(有许多其他有用的功能供您阅读A.S.A.P.)。你认为在连续输入十到十五次之后你能记住这两行吗?

scanf("%*[^\n]");
getchar();

Man ...您的代码总是在使用之前检查malloc返回值。我们如何知道您的malloc来电未返回NULL,导致您未提出问题?