繁体   English   中英

C链表问题

[英]C linked list problems

我确实需要您的程序帮助。 我是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 -modify元素-在链接列表中搜索-保存到文件-以及菜单

您正在函数addieren中创建一个新人员,而不是接收您在主函数中创建的人员。 您需要将其作为参数接收,像这样

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

而且主要是你应该

addieren(&p1);

注意双指针,因此您可以传递指针并在函数内部对其进行修改。 另外,您可能应该返回一个int以确认操作是否成功

我看不到任何特定的问题,因此,我将从指出一些错误开始,也许当您添加了一个问题(以问号结尾)时,可以对我进行更新。

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

首先,我要说的是,我强烈建议在首次使用函数之前先阅读本手册。 实际上,我非常确定这是我们作为程序员的期望。 当然,我们必须学习要寻找的手册,因为互联网是一个危险的地方,人们偶尔会撒谎。 OpenGroup手册很好。 例如,如果您键入Google“ Opengroup fscanf”,则会找到fscanf的手册,该手册将回答我的许多问题,请确保...

该手册指出,所有空白都被视为相同的指令,它试图读取并丢弃尽可能多的空白。 因此,在格式说明符中(至少在您的上下文中),普通空格与\\t含义相同...因此,如果您的问题与“为什么所有空白都被相同对待?”类似, 那么答案是“因为这就是手册说的应该做的”。

您正在阅读的固定宽度字段可能无法翻译,在这种情况下,手册还描述了测试的第一个字符与标准不符的地方( [Az ] ,这看起来很可疑,您可能会意识到阅读手册,这不是您想要的)。 这将导致返回值(来自scanf )为0 ,对您的代码而言,这看起来像是一次成功的读取。

这是一条惯用的准则:让我们首先计算一下您想读入的对象的数量...在这里,从您的代码中逐字复制: &name, &telnum, &wohnort ...其中有三个。

现在,取该数字(三个),然后将其与fscanf返回的值进行比较...如果这两个数字匹配,则可以安全地使用所有三个参数(尽管正如我在下面所述,它们不一定包含您期望的值)包含装有)。

您也不应在此处使用& (address-of)运算符来输入nametelnumwohnort char [10]数组上的address-of运算符将导致char (*)[10]表达式,而-您最想确定的是纯香草char *表达式。 因此,正确的做法是让Cs隐式的“数组表达式到指针表达式”的转换为您完成。

以下可能更接近您想要的。 我对[Az ]的建议是,列出要括在方括号中的每个字符,如果要列出要排除的每个字符,请使用[^...] 需要明确的是,如果您要问的是C格式字符串,则没有范围 例如:

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 (还有许多其他有用的功能可供您阅读有关ASAP的信息)。 连续键入十或十五次后,您是否还记得这两行?

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

......您的代码应始终在使用它们之前检查malloc返回值。 我们怎么知道您的malloc调用没有返回NULL ,从而导致您没有问过一个问题?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM