char的unicode被误用于int

时间:2019-03-08 07:59:37

标签: c++ c unicode union

我正在编写一个程序,读取学生的成绩,无论是char还是int,并将其存储在union中,然后打印成绩为{{ 1}}或> 90。

但是当我尝试这样做时,由于程序不知道我想比较哪个(字符或整数),所以我得到了意外的输出。

A

这是输出:

#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;
}

2 个答案:

答案 0 :(得分:2)

在比较中使用成绩类型:

  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);

答案 1 :(得分:1)

  

注意:我最初的答案是使用ASCII Table,但有人指出我应该使用UTF-8 Table。但是,对于此处描述的目的,两者确实非常相似。但是,从技术上讲,编译器通常会使用UTF-8而不是ASCII,因此我已经编辑了答案以反映这一点。

维勒-瓦尔特利(Ville-Valtteri)的回答很好,但我也想解释发生了什么事。

因此,请查看UTF-8 Table

希望您应该知道,任何计算机上的每个字符都会被翻译成数字。这由上述表格确定。

在C和C ++中,如果我将一个数字分配给char,则它们在某种意义上被平等对待:

char c = 65;

它将视为字母'A'

相反,如果我将字母'A'分配给一个整数:

int i = int('A');

您最终得到数字65

好的,现在使用您的代码。让我们看看您的第一个测试:

if (sList[i]->grade.charGrade == 'A')

您要测试值是否等于'A' ==。请注意,您无需检查类型,因此65完全可以接受此测试,即使您将其添加为int ,因为您也没有为此进行测试。您正在对'A'或等效的65进行测试。

现在,您的第二项测试:

else if (sList[i]->grade.intGrade >= 90) 

因此,如果它不是字符等级“ A”,那么它必须是整数等级,对吗?错误的,因为没有测试它是否为字符等级,仅是它不是字符等级“ A”。没什么,您就可以参加这项测试。

这意味着字母'b'将到达此测试,其值为98(再次参见UTF-8 table)。由于C和C ++将数字和字母视为相同(在技术上不是,但近似),因此即使将其用作char级,也将其作为int等级98进行测试。这意味着它可以通过您> = 90支票。

这将我们带到Ville-Valtteri's solution,这是对您支票中成绩等级的说明。

 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);