在主函数中,用户必须输入ID。然后显示输入的ID数据(学生姓名、ID和课程)。
我需要编写缺少的部分,它必须旨在将用户输入的“ID”与从函数“populate()”存储的ID进行比较,然后它将如何显示来自函数内部的多个结构体的数据?
是否可以将学生结构s1 - s10作为变量访问?like; if(id == '1001'){ printf(“学生ID:%s\n学生姓名:%s\n课程:%s”,student s1);
#include <stdio.h>
#include <string.h>
struct Student {
char id[4];
char name[8];
char course[5];
};
void populate() {
FILE* fp;
fp = fopen("students.csv", "w");
struct Student s1 = {"1001", "John", "BSCS"};
fprintf(fp, "%s,%s,%s\n", s1.id, s1.name, s1.course);
struct Student s2 = {"1002", "Bob", "BSIT"};
fprintf(fp, "%s,%s,%s\n", s2.id, s2.name, s2.course);
struct Student s3 = {"1003", "Jane", "BSIT"};
fprintf(fp, "%s,%s,%s\n", s3.id, s3.name, s3.course);
struct Student s4 = {"1004", "Karla", "BSIT"};
fprintf(fp, "%s,%s,%s\n", s4.id, s4.name, s4.course);
struct Student s5 = {"1005", "Clarisse", "BSCS"};
fprintf(fp, "%s,%s,%s\n", s5.id, s5.name, s5.course);
struct Student s6 = {"1006", "Peter", "BSCS"};
fprintf(fp, "%s,%s,%s\n", s6.id, s6.name, s6.course);
struct Student s7 = {"1007", "Bob", "BSCS"};
fprintf(fp, "%s,%s,%s\n", s7.id, s7.name, s7.course);
struct Student s8 = {"1008", "Stewie", "BSIT"};
fprintf(fp, "%s,%s,%s\n", s8.id, s8.name, s8.course);
struct Student s9 = {"1009", "Bryan", "BSCS"};
fprintf(fp, "%s,%s,%s\n", s9.id, s9.name, s9.course);
struct Student s10 = {"1010", "Kent", "BSIT"};
fprintf(fp, "%s,%s,%s\n", s10.id, s10.name, s10.course);
fclose(fp);
}
void display(const char* id) {
FILE* fp;
fp = fopen("students.csv", "r");
struct Student student;
if (strcmp(student.id, id) == 0) {
printf("Student Id: %s\n", student.id);
printf("Student Name: %s\n", student.name);
printf("Course: %s\n", student.course);
}
fclose(fp);
}
int main() {
populate();
char id[4];
printf("Enter student_id: ");
fgets(id, 4, stdin);
display(id);
return 0;
}
2条答案
按热度按时间9jyewag01#
具有storage auto的变量由编译器在堆栈上分配。它们还具有声明它们的块的作用域。因此,这些变量(s1-s10)在populate函数之外不可访问。如果从该函数返回,它们也会被释放。如果你想让它们在之后仍然存在,你必须把它们分配到其他地方。如果你想从外部访问它们,你可以在某个地方传递一个指向它们的指针,但这并不能解决释放问题。如果你返回一个指向局部变量的指针,你将得到未定义的行为,因为变量将被释放,指针将悬空(指向无意义)。所以你有两个选择
作为第三种方法,你也可以用全局作用域来声明它们,但我不推荐这样做。(除非你只是有点黑客,但不是为了一些真实的东西)
请注意,我将10个变量改为一个数组,因为否则您必须传递10个单独的指针。
0h4hbjxa2#
首先,字符串
"1001"
需要5字节的内存。必须始终考虑字符串结尾处的空终止字节('\0'
)。在内存中,它看起来像:您的结构定义
将没有足够的空间来存储这些strings。C的一个警告是,数组(例如
char id[4];
)可能是initialized,因为字符串文字太大了一个字节。结果数组将省略null终止字节,您将不再拥有字符串。因此,当结构初始化工作时,下面的
通过向
printf
说明符%s
传递非字符串的内容,立即调用Undefined Behaviour。还有这里
id
总是太小,无法存储任何将写入populate
文件的ID,因为fgets
总是在成功时空终止缓冲区。另外,如果fgets
读取了一个换行符,它也将被存储在缓冲区中。是否可以访问
struct Student
s1
-s10
作为变量?变量
s1
到s10
表示automatic storage duration的对象。它们只存在于其封闭 block 的duration中,在本例中是函数调用populate
。当函数返回时,它们不再存在。但你似乎混淆了两个概念:
如果你想要前者,你应该在
main
中声明你的变量,并将指向这些对象的指针传递给你的不同函数。或者,变量可以在file scope处“全局”定义。如果您想要后者,那么
display
需要从它打开的文件(fp
)中实际读取信息。现在,struct Student student;
是一个未初始化的结构,阅读它的成员(如strcmp(student.id, id)
)会调用Undefined Behaviour。旁白:任何时候你发现自己在枚举变量名(
s1
,s2
,s3
,...),你应该问问自己,如果一个 * 数组 * 不会更合适。看起来最有可能的情况是,您正在寻找写入文件,然后搜索文件的内容。
考虑以下简化示例:
示例用法: