我真的需要你对我的程序的帮助。我是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 - 修改元素 - 链表中的搜索 - 保存到文件 - 和一个菜单
答案 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
返回的数据进行比较......如果这两个数字匹配,那么你可以安全地使用所有三个参数(尽管如下所述,它们可能不一定包含您希望它们包含的值。)
您也不应在&
,name
或telnum
使用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
,导致您未提出问题?