如何在 C 中正确定位结构



这是我的完整代码,它看起来可以工作,但它工作得不是很好。 我会接受任何像这样工作的代码。

首先,代码有效,但是当我想将第三个名称添加到结构中时,它崩溃了。

还有其他方法可以做到这一点吗?

我需要结构,因为将来我想添加一些其他参数,如年龄、平均值、性别等。

请帮帮我。

//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 eingebenn");
printf("t[9] Programm beendenn");
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] = '';
scount++;
}

我正在使用Visual Studio。

感谢您的帮助!

students *mynew= realloc(s, sizeof(students)* (scount+1));
if( mynew != NULL )
s=mynew;

Otehrwise,您有内存泄漏。您没有使用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+1realloc

重新分配时,总体思路是增加学生人数。为此,您需要为学生分配额外的内存。这就是代码中scount+1的原因。(realloc)。


其他几点:

while (s[scount].name[index] != 'n')
{
index++;
}
s[scount].name[index] = '';

你也可以这样做

size_t len = strlen(s[scount].name);
if(len){ 
s[scount].name[len-1]=''; 
}

从标准§7.21.7.2了解原因

char *fgets(char * restrict s, int n,FILE * restrict stream)

fgets函数读取的读数最多比 由streaminto 指向的流中的n指定的字符s指向的数组。在 换行符(保留)或文件末尾之后。空值 字符在读入的最后一个字符之后立即写入 数组。

输入string中已经存在字符。您可以获取它的长度,但您知道之前的那个是您通过按Enter键输入的n字符1。我们正在用覆盖它.

1.这是通常的情况,但不是唯一的情况。在两种情况下,这可能不是看待事物的正确方式。

  • 输入行在'n'之前有n-1个或更多字符。前面的那个不会是n而是用户输入的某个字符。

  • 最后一行是可能没有'n'的流。(标准已关闭)。在这种情况下,输入也不包含n

因此,在这些情况下,删除n的想法将失败。在评论中讨论。(楚克斯)


比以这种方式覆盖更好、更安全的解决方案:

s[scount].name[strcspn(s[scount].name, "n")] = '';

链接的解释是,如果给出一个作为输入,那么我们基本上会写入s[scount].name[SIZE_MAX]这是不需要的。


来自标准§7.24.5.3

size_t strcspn(const char *s1, const char *s2)

strcspn函数计算最大初始值的长度 由s1指向的字符串段,其完全由字符不是来自s2指向的字符串。

如何在 C 中正确定位结构?

p = malloc(sizeof *p);
if (p == NULL) Handle_OutOfMemory();

如何在 C 中正确重新分配结构?

void *t = realloc(p, sizeof *p * number_of_elements);
if (t == NULL && number_of_elements > 0) {
Handle_OutOfMemory();
} else {
p = t;
}

p指出了一些struct。 请注意,上面没有这种类型的编码


OP 的主要问题是不使用realloc()的返回值并分配 1-too-little

// realloc(s, sizeof(students) * scount);
s = realloc(s, sizeof *s * (scount+1));  // or use above code with check for out-of-memory.

realloc返回一个需要保留的新指针:

students* snew = realloc(s, sizeof(students) * (scount + 1));
if (!snew) {
free(s); // If there is not enough memory, the old memory block is not freed
// handle out of memory
} else { 
s = snew;
}

你没有把它分配回来!看看realloc是如何工作的。您需要在进行这样的重新分配后重新分配指针。

if (scount == 0)
{
s = (students*)malloc(sizeof(students));
}
else
{
students *temp = realloc(s, sizeof(students) * (scount+1));
if(temp == NULL){
free(s);
}
else{
s = temp;
}
}

根据定义,realloc 返回一个 void 指针,但你没有收集它。

void *realloc(void *ptr, size_t size);

如果没有足够的空间,Realloc 会返回一个NULL。因此,当您确定它不是NULL时,您可以重新分配它

只需在上面做一个小的更改,你的代码就像一个魅力!

干杯!

相关内容

  • 没有找到相关文章

最新更新