C - 垃圾字符,即使有空终止符,结构
C - garbage characters even with null terminator, structures
因此,作为学校作业的一部分,我必须创建一个应用程序来使用结构处理各种字段的输入。在 main 之外定义如下
typedef struct stud {
struct number {
int studNum;
} number;
struct name {
char firstName[NAME_SIZE];
char lastName[NAME_SIZE];
} name;
struct cellNum {
int areaCode;
int prefix;
int suffix;
} cellNum;
struct courses {
struct fall {
char className[NAME_SIZE];
float mark;
} fall;
struct winter {
char className[NAME_SIZE];
float mark;
} winter;
} courses;
} stud;
NAME_SIZE 定义为 30
我访问结构如下
stud studArray[100]; // max 100 students
stud *studPtr;
for (int i = 0; i < studCount; i++) {
studPtr = &studArray[i];
initializeStrings(studPtr[i]);
getNum(studPtr[i]);
getName(studPtr[i]);
getCell(studPtr[i]);
getCourses(studPtr[i]);
}
initializeStrings 是我添加空终止符的地方
void initializeStrings(stud student) {
student.name.firstName[NAME_SIZE - 1] = '[=12=]';
student.name.lastName[NAME_SIZE -1] = '[=12=]';
student.courses.fall.className[NAME_SIZE -1] = '[=12=]';
student.courses.winter.className[NAME_SIZE -1] = '[=12=]';
}
这就是现在出现问题的地方:在我的各种函数中的任何一个中,当我尝试访问我写入字符串的任何信息时,我得到一个看起来像横向 T 的垃圾字符输出,但是仅当我以不同的功能访问数据时。
示例:这是获得 2 个课程和分数的代码
void getCourses(stud student) {
getchar();
printf("\n%s", "Enter Course name - Fall 2016: ");
fgets(student.courses.fall.className, NAME_SIZE - 1, stdin);
fflush(stdin); // suggested by my prof to fix the issue, did nothing
printf("\n%s%s%s", "Enter mark received for ", student.courses.fall.className, ": ");
scanf("%f", &student.courses.fall.mark);
getchar();
printf("\n%s", "Enter Course name - Winter 2017: ");
fgets(student.courses.winter.className, NAME_SIZE - 1, stdin);
printf("\n%s%s%s", "Enter mark received for ", student.courses.winter.className, ": ");
scanf("%f", &student.courses.winter.mark);
}
如果我输入 helloWorld 作为课程名称,系统会正确打印
输入 helloWorld
收到的标记
但是当我尝试从打印功能打印数据时:
void printData(stud student) {
// various other values (none of which work)
printf("\t%s\t%s\t%f\n", "Fall2016", student.courses.fall.className, student.courses.fall.mark);
}
我得到垃圾数据输出(image)
欢迎任何help/code批评
编辑:谢谢 Eddiem 和其他所有人,您为我指明了正确的方向。
这段代码没有任何意义。首先,为什么不将 stud*
指针传递给您在下面调用的每个函数?无论如何,这里的方式是初始化 studPtr
以指向 studArray
数组中的特定元素,但随后仍将 i
索引到该指针中。您可能会通过 studPtr[0]
,但这很奇怪。
原代码:
stud studArray[100]; // max 100 students
stud *studPtr;
for (int i = 0; i < studCount; i++) {
studPtr = &studArray[i];
initializeStrings(studPtr[i]);
getNum(studPtr[i]);
getName(studPtr[i]);
getCell(studPtr[i]);
getCourses(studPtr[i]);
}
我建议修改如下:
void initializeStrings(stud *student) {
student->name.firstName[NAME_SIZE - 1] = '[=11=]';
student->name.lastName[NAME_SIZE -1] = '[=11=]';
student->courses.fall.className[NAME_SIZE -1] = '[=11=]';
student->courses.winter.className[NAME_SIZE -1] = '[=11=]';
}
如果当前采用 stud
参数的函数,则需要对每个函数进行这些修改。然后,将循环初始化更改为:
for (int i = 0; i < studCount; i++) {
initializeStrings(&studArray[i]);
getNum(&studArray[i]);
getName(&studArray[i]);
getCell(&studArray[i]);
getCourses(&studArray[i]);
}
这是不对的:
studPtr = &studArray[i];
initializeStrings(studPtr[i]);
假设您要访问数组的第三个元素,因此 i
为 3。这为您提供了第三个条目的偏移量:
studPtr = &studArray[i];
现在你使用索引....
initializeStrings(studPtr[i]);
所以你访问的元素比你已经访问的第三个元素多了 3 个;即元素 6。您可以看到您将离开数组的末尾,或者访问您尚未初始化的元素。
所以使用或者:
studPtr = &studArray[i];
initializeStrings(studPtr);
或
initializeStrings(&studArray[i]);
两者是一回事,指向同一个地方
问题是您没有通过引用传递(也就是使用指针)。如果您不使用指针,那么像 getCourses
这样的函数会修改临时数据而不是直接修改数据。因此,原始数据中的垃圾值永远不会被删除。
改变
void getCourses(stud student) { // no pointer = copy data to temporary memory, original data is unmodified in this function.
getchar();
printf("\n%s", "Enter Course name - Fall 2016: ");
fgets(student.courses.fall.className, NAME_SIZE - 1, stdin);
fflush(stdin); // suggested by my prof to fix the issue, did nothing
printf("\n%s%s%s", "Enter mark received for ", student.courses.fall.className, ": ");
scanf("%f", &student.courses.fall.mark);
getchar();
printf("\n%s", "Enter Course name - Winter 2017: ");
fgets(student.courses.winter.className, NAME_SIZE - 1, stdin);
printf("\n%s%s%s", "Enter mark received for ", student.courses.winter.className, ": ");
scanf("%f", &student.courses.winter.mark);
}
到
void getCourses(stud *student) { // notice the pointer used. Original data is to be modified.
getchar();
printf("\n%s", "Enter Course name - Fall 2016: ");
fgets(student->courses.fall.className, NAME_SIZE - 1, stdin);
fflush(stdin); // suggested by my prof to fix the issue, did nothing
printf("\n%s%s%s", "Enter mark received for ", student.courses.fall.className, ": ");
scanf("%f", &student->courses.fall.mark);
getchar();
printf("\n%s", "Enter Course name - Winter 2017: ");
fgets(student->courses.winter.className, NAME_SIZE - 1, stdin);
printf("\n%s%s%s", "Enter mark received for ", student.courses.winter.className, ": ");
scanf("%f", &student->courses.winter.mark);
}
此外,您必须修改 for 循环以处理指针。即,将getCourses(studPtr[i]);
改为getCourses(&studPtr[i]);
因此,作为学校作业的一部分,我必须创建一个应用程序来使用结构处理各种字段的输入。在 main 之外定义如下
typedef struct stud {
struct number {
int studNum;
} number;
struct name {
char firstName[NAME_SIZE];
char lastName[NAME_SIZE];
} name;
struct cellNum {
int areaCode;
int prefix;
int suffix;
} cellNum;
struct courses {
struct fall {
char className[NAME_SIZE];
float mark;
} fall;
struct winter {
char className[NAME_SIZE];
float mark;
} winter;
} courses;
} stud;
NAME_SIZE 定义为 30
我访问结构如下
stud studArray[100]; // max 100 students
stud *studPtr;
for (int i = 0; i < studCount; i++) {
studPtr = &studArray[i];
initializeStrings(studPtr[i]);
getNum(studPtr[i]);
getName(studPtr[i]);
getCell(studPtr[i]);
getCourses(studPtr[i]);
}
initializeStrings 是我添加空终止符的地方
void initializeStrings(stud student) {
student.name.firstName[NAME_SIZE - 1] = '[=12=]';
student.name.lastName[NAME_SIZE -1] = '[=12=]';
student.courses.fall.className[NAME_SIZE -1] = '[=12=]';
student.courses.winter.className[NAME_SIZE -1] = '[=12=]';
}
这就是现在出现问题的地方:在我的各种函数中的任何一个中,当我尝试访问我写入字符串的任何信息时,我得到一个看起来像横向 T 的垃圾字符输出,但是仅当我以不同的功能访问数据时。
示例:这是获得 2 个课程和分数的代码
void getCourses(stud student) {
getchar();
printf("\n%s", "Enter Course name - Fall 2016: ");
fgets(student.courses.fall.className, NAME_SIZE - 1, stdin);
fflush(stdin); // suggested by my prof to fix the issue, did nothing
printf("\n%s%s%s", "Enter mark received for ", student.courses.fall.className, ": ");
scanf("%f", &student.courses.fall.mark);
getchar();
printf("\n%s", "Enter Course name - Winter 2017: ");
fgets(student.courses.winter.className, NAME_SIZE - 1, stdin);
printf("\n%s%s%s", "Enter mark received for ", student.courses.winter.className, ": ");
scanf("%f", &student.courses.winter.mark);
}
如果我输入 helloWorld 作为课程名称,系统会正确打印 输入 helloWorld
收到的标记但是当我尝试从打印功能打印数据时:
void printData(stud student) {
// various other values (none of which work)
printf("\t%s\t%s\t%f\n", "Fall2016", student.courses.fall.className, student.courses.fall.mark);
}
我得到垃圾数据输出(image)
欢迎任何help/code批评
编辑:谢谢 Eddiem 和其他所有人,您为我指明了正确的方向。
这段代码没有任何意义。首先,为什么不将 stud*
指针传递给您在下面调用的每个函数?无论如何,这里的方式是初始化 studPtr
以指向 studArray
数组中的特定元素,但随后仍将 i
索引到该指针中。您可能会通过 studPtr[0]
,但这很奇怪。
原代码:
stud studArray[100]; // max 100 students
stud *studPtr;
for (int i = 0; i < studCount; i++) {
studPtr = &studArray[i];
initializeStrings(studPtr[i]);
getNum(studPtr[i]);
getName(studPtr[i]);
getCell(studPtr[i]);
getCourses(studPtr[i]);
}
我建议修改如下:
void initializeStrings(stud *student) {
student->name.firstName[NAME_SIZE - 1] = '[=11=]';
student->name.lastName[NAME_SIZE -1] = '[=11=]';
student->courses.fall.className[NAME_SIZE -1] = '[=11=]';
student->courses.winter.className[NAME_SIZE -1] = '[=11=]';
}
如果当前采用 stud
参数的函数,则需要对每个函数进行这些修改。然后,将循环初始化更改为:
for (int i = 0; i < studCount; i++) {
initializeStrings(&studArray[i]);
getNum(&studArray[i]);
getName(&studArray[i]);
getCell(&studArray[i]);
getCourses(&studArray[i]);
}
这是不对的:
studPtr = &studArray[i];
initializeStrings(studPtr[i]);
假设您要访问数组的第三个元素,因此 i
为 3。这为您提供了第三个条目的偏移量:
studPtr = &studArray[i];
现在你使用索引....
initializeStrings(studPtr[i]);
所以你访问的元素比你已经访问的第三个元素多了 3 个;即元素 6。您可以看到您将离开数组的末尾,或者访问您尚未初始化的元素。
所以使用或者:
studPtr = &studArray[i];
initializeStrings(studPtr);
或
initializeStrings(&studArray[i]);
两者是一回事,指向同一个地方
问题是您没有通过引用传递(也就是使用指针)。如果您不使用指针,那么像 getCourses
这样的函数会修改临时数据而不是直接修改数据。因此,原始数据中的垃圾值永远不会被删除。
改变
void getCourses(stud student) { // no pointer = copy data to temporary memory, original data is unmodified in this function.
getchar();
printf("\n%s", "Enter Course name - Fall 2016: ");
fgets(student.courses.fall.className, NAME_SIZE - 1, stdin);
fflush(stdin); // suggested by my prof to fix the issue, did nothing
printf("\n%s%s%s", "Enter mark received for ", student.courses.fall.className, ": ");
scanf("%f", &student.courses.fall.mark);
getchar();
printf("\n%s", "Enter Course name - Winter 2017: ");
fgets(student.courses.winter.className, NAME_SIZE - 1, stdin);
printf("\n%s%s%s", "Enter mark received for ", student.courses.winter.className, ": ");
scanf("%f", &student.courses.winter.mark);
}
到
void getCourses(stud *student) { // notice the pointer used. Original data is to be modified.
getchar();
printf("\n%s", "Enter Course name - Fall 2016: ");
fgets(student->courses.fall.className, NAME_SIZE - 1, stdin);
fflush(stdin); // suggested by my prof to fix the issue, did nothing
printf("\n%s%s%s", "Enter mark received for ", student.courses.fall.className, ": ");
scanf("%f", &student->courses.fall.mark);
getchar();
printf("\n%s", "Enter Course name - Winter 2017: ");
fgets(student->courses.winter.className, NAME_SIZE - 1, stdin);
printf("\n%s%s%s", "Enter mark received for ", student.courses.winter.className, ": ");
scanf("%f", &student->courses.winter.mark);
}
此外,您必须修改 for 循环以处理指针。即,将getCourses(studPtr[i]);
改为getCourses(&studPtr[i]);