我用C编写了以下代码:
#include <stdio.h>
#include <string.h>
#define MAX_NAMES 5
#define MAX_NAME_LENGTH 20
char* names[MAX_NAMES];
void addNames();
int main(){
addNames();
printf("\n");
for(int i=0; i<MAX_NAMES; i++){
// printing "name" from array
printf("Name from array #%d: %s\n", i+1, names[i]);
}
return 0;
}
void addNames(){
char name[MAX_NAME_LENGTH];
for(int i=0; i<MAX_NAMES; i++){
printf("Give me the name #%d: ", i+1);
fgets(name, MAX_NAME_LENGTH, stdin);
name[strlen(name)-1]='\0';
// adding "name" to array "names"
names[i]=name;
// printing "name" from array
printf("Name given: %s\n", names[i]);
}
}
names
它声明了一个指向 char 数组 ( ) 的指针类型的全局变量char*
。一切addNames()
都很好。我可以将用户的输入存储在name
type变量中char[MAX_NAME_LENGTH]
,然后将其保存到数组names
并打印名称。但是一旦我离开addNames()
模块并返回到main()
,如果我尝试打印数组中的名称,它将带有外部字符串:
我认为发生这种情况是因为保存在数组中的指针names
在返回时被“销毁”,main()
因为addNames()
这些指针是在那里创建的。
抱歉有任何错字或冗余,我不是母语人士 xD。希望您能帮助了解发生了什么,以及我该如何解决这个问题,或者哪种方法效果更好。谢谢
您正在处理一些有趣的问题。
数组大小 ≠ 使用的元素数量
第一个是您的数组具有声明的大小,并且您要求用户为您提供恰好那么多的名称。我建议您还跟踪实际使用的名称数量,并让用户有机会提供更少的名称。
执行此操作的方法可以很简单,只需识别用户何时按下Enter而不输入名称即可。您的指示可以很简单:
strdup()
现在,要将名称添加到您的列表中,只需:
如果您使用
strdup()
,则还必须使用free()
使用的名称:strcpy()
您可以使用字符串数组来代替指针数组。
现在您可以用来
strcpy()
复制从用户处获得的字符串。有了这个,你就不再需要
free()
任何东西了。fgets() 和换行符
您应该检查输入操作的结果以验证它们是否有效。
如果尝试读取文件失败,则程序应该失败。
同样,如果用户提供的行太长,程序就会失败。
原因很简单:如果用户没有提供正确的输入,就会使程序失败。要求用户提供正确的输入!
全局变量
人们会让你对全局变量感到悲伤。它们并不像每个人都喜欢重复的那样邪恶,但是“全局是邪恶的”这句话是在说你应该考虑它们的影响。
对于家庭作业解决方案来说,没什么大不了的。对于很多程序来说,没什么大不了的。
当事情开始变得复杂时,全球化开始让生活变得比实际需要的更加困难。
因此,将来,您应该开始考虑在不使用全局变量的情况下执行此操作的方法。例如,您可以将函数签名重写为:
或者:
然后
main()
你可以得到如下名称:变化比比皆是,但要点是您已将名称(和名称计数)数据从全局对象移动到可以本地化的对象。