我正在编写一个读取学生等级的程序,无论是char
还是int
并将其存储在union
中,然后打印出成绩为A
或> 90的学生。
但是,当我尝试这样做时,我会得到意外的输出,因为该程序不知道我要比较哪一个(char或int)。
#include <stdio.h>
#include <stdlib.h>
union StuGrade {
char charGrade;
int intGrade;
};
struct Student {
int ID;
int typeOfGrade;
union StuGrade grade;
};
int main () {
const int size = 5;
struct Student *sList[size];
for (int i = 0; i < size; i++) {
sList[i] = (struct Student *)calloc(1, sizeof(struct Student));
if (!sList[i]) {
puts("Error allocating memory");
return 1;
}
printf("Enter ID: ");
scanf("%d", &(sList[i]->ID));
printf("0 for char grade or 1 for int grade: ");
scanf("%d", &(sList[i]->typeOfGrade));
if (sList[i]->typeOfGrade) {
printf("Enter an int grade: ");
scanf("%d", &(sList[i]->grade.intGrade));
} else {
printf("Enter a char grade: ");
scanf(" %c", &(sList[i]->grade.charGrade));
}
} //end for loop
printf("n***Student(s) who take grade 'A' is/are***n");
for (int i = 0; i < size; i++) {
if (sList[i]->grade.charGrade == 'A')
printf("ID: %d nGrade: %c n", sList[i]->ID, sList[i]->grade.charGrade);
else if (sList[i]->grade.intGrade >= 90)
printf("ID: %d nGrade: %d n", sList[i]->ID, sList[i]->grade.intGrade);
}
for (int i = 0; i < size; i++)
free(sList[i]);
return 0;
}
这是输出:
Enter ID: 1
0 for char grade or 1 for int grade: 0
Enter a char grade: A
Enter ID: 2
0 for char grade or 1 for int grade: 0
Enter a char grade: b
Enter ID: 3
0 for char grade or 1 for int grade: 1
Enter an int grade: 99
Enter ID: 4
0 for char grade or 1 for int grade: 1
Enter an int grade: 84
Enter ID: 5
0 for char grade or 1 for int grade: 1
Enter an int grade: 65
***Student(s) who take grade 'A' is/are***
ID: 1
Grade: A
ID: 2
Grade: 98
ID: 3
Grade: 99
ID: 5
Grade: A
在比较中使用等级类型:
if (sList[i]->typeOfGrade == 0 && sList[i]->grade.charGrade == 'A')
printf("ID: %d nGrade: %c n", sList[i]->ID, sList[i]->grade.charGrade);
else if (sList[i]->typeOfGrade == 1 && sList[i]->grade.intGrade >= 90)
printf("ID: %d nGrade: %d n", sList[i]->ID, sList[i]->grade.intGrade);
注意:我的原始答案使用了ASCII表,但是有人指出我应该使用UTF-8表。但是,对于此处描述的目的,两者都非常相似。但是,从技术上讲,编译器通常会使用UTF-8而不是ASCII,因此我已经编辑了答案以反映这一点。
ville-valtteri有一个很好的答案,但我也想解释发生了什么。
所以,请查看UTF-8表。
希望您应该知道,任何计算机上的每个字符都会翻译成一个数字。这是由上述表确定的。
在C和C 中,这些是同样处理的,因为我将数字分配给char:
char c = 65;
它将将其视为字母'A'
。
相反,如果我将字母'A'
分配给int:
int i = int('A');
您最终获得了数字65
。
好吧,现在使用您的代码。让我们看一下您的第一个测试:
if (sList[i]->grade.charGrade == 'A')
您测试以查看该值是否为== to 'A'
。请注意,您不检查类型,因此65对于此测试完全可以接受,即使您将其添加为INT ,因为您没有为此进行测试。您正在为'A'
或其等效的65
进行测试。
现在,您的第二个测试:
else if (sList[i]->grade.intGrade >= 90)
所以,如果不是字符级" A",那一定是int等级的权利吗?错误,因为没有测试是否是char等级,只是它不是字符级" A"。没有什么,您可以参加此测试。
这意味着字母'b'
将进入此测试,该测试的值为98
(再次请参见UTF-8表)。由于C和C 将数字和字母视为相同的(不是技术上的,而是关闭),因此它将其作为INT 98级测试,即使它打算是char等级。这意味着它通过您> = 90检查。
将我们带到Ville-Valtteri的解决方案,该解决方案是您支票中的等级类型。
if (sList[i]->typeOfGrade == 0 && sList[i]->grade.charGrade == 'A') printf("ID: %d nGrade: %c n", sList[i]->ID, sList[i]->grade.charGrade); else if (sList[i]->typeOfGrade == 1 && sList[i]->grade.intGrade >= 90) printf("ID: %d nGrade: %d n", sList[i]->ID, sList[i]->grade.intGrade);