这是我的全部代码,看起来很有用,但效果不太好。
我会接受任何代码,就是这样工作的。
首先,代码可以工作,但是当我想向结构添加第三个名称时,它会崩溃。
还有别的办法吗?
我需要struct,因为在将来,我想添加一些其他参数,如年龄、平均值、性别等。
求你了,帮帮我。
//The student table
typedef struct students {
char name[50];
} students;
//Global params
int scount = 0;
students *s;
//Basic functions
void addNewStudent();
int main()
{
int loop = 1;
char in;
int ch;
printf("Willkommen.\n Wahlen Sie bitte von die folgenden Optionen:\n");
while (loop)
{
printf("\t[1] Neue Student eingeben\n");
printf("\t[9] Programm beenden\n");
scanf(" %c", &in);
while ((ch = getchar()) != '\n');
switch (in)
{
case '1':
addNewStudent();
break;
case '9':
loop = 0;
break;
default: printf("------\nOption nicht gefunden.\n------\n");
break;
}
}
free(s);
return 0;
}
void addNewStudent()
{
int index = 0;
if (scount == 0)
{
s = (students*)malloc(sizeof(students));
}
else
{
realloc(s, sizeof(students) * scount);
}
printf("Geben Sie Bitte die Name:\n");
fgets(s[scount].name, sizeof(s[scount].name), stdin);
while (s[scount].name[index] != '\n')
{
index++;
}
s[scount].name[index] = '\0';
scount++;
}
我在用Visual Studio。
谢谢你的帮助!
最佳答案
students *mynew= realloc(s, sizeof(students)* (scount+1));
if( mynew != NULL )
s=mynew;
另外你的记忆有漏洞。您没有使用返回值
realloc
。不要强制转换
malloc
的返回类型。根据标准7.22.2.35
void *realloc(void *ptr, size_t size)
realloc
函数释放ptr
指向的旧对象,并返回指向具有
size
指定大小的新对象的指针。最好不要使用调用
malloc
的同一指针变量,因为如果失败,也会丢失对旧指针变量的引用(除非它是通过其他方式存储的)。另外,您没有检查
malloc
的返回值。s = malloc(sizeof(students));
if( s == NULL ){
frpntf(stderr,"%s","Memory allocation failed");
exit(1);
}
您还应该检查
fgets()
的返回值。if( fgets(s[scount].name, sizeof(s[scount].name), stdin) == NULL){
fprintf(stderr,"%s","Error in input");
exit(1);
}
也试图编译你的代码它显示了
warning: ignoring return value of ‘realloc’, declared with attribute warn_unused_result [-Wunused-result]
realloc(s, sizeof(students) * scount);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
编译时,请不要忽略任何警告消息。它表明了你的问题。
要点:(为什么在
scount+1
中realloc
?)当重新分配时,总的想法是增加学生人数。为此,你需要为学生分配额外的内存。这就是代码中
scount+1
的原因。其他要点:
while (s[scount].name[index] != '\n')
{
index++;
}
s[scount].name[index] = '\0';
你也可以这样做
size_t len = strlen(s[scount].name);
if(len){
s[scount].name[len-1]='\0';
}
理解标准7.21.7.2中的原因
char *fgets(char * restrict s, int n,FILE * restrict stream)
realloc
函数最多读取一个小于由
fgets
指定的字符从由n
指向的流stream
指向的数组。在新行字符(保留)或文件结束后。空的
字符在最后一个字符读入后立即写入
阵列。
s
字符已经存在于输入的\0
中。您可以得到它的长度,但是您知道string
之前的那个字符是通过按Enter键输入的\0
字符1。我们正在用\n
覆盖它。一。这是常见的情况,但不是唯一的。有两种情况下,这可能不是正确的看待事物的方式。
输入行在
\0
之前有n-1
或更多字符。'\n'
之前的不是\0
而是用户输入的字符。最后一行是可能没有
\n
的流。(stdin关闭)。在这种情况下,输入也不包含'\n'
。因此,在这些情况下,删除
\n
的想法将失败。(楚克斯)一个比用这种方式覆盖更好、更安全的解决方案:
s[scount].name[strcspn(s[scount].name, "\n")] = '\0';
来自link的解释是,如果a
\n
作为输入,那么我们将基本上写入不需要的\0
。根据标准7.24.5.3
size_t strcspn(const char *s1, const char *s2)
s[scount].name[SIZE_MAX]
函数计算最大初始值的长度由
strcspn
指向的字符串段,它完全由不是由
s1
指向的字符串中的字符。关于c - 如何在C中正确分配结构,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/47289845/