【问题标题】:unicode of char misused for intchar 的 unicode 误用于 int
【发布时间】:2019-07-30 05:36:16
【问题描述】:

我正在编写一个程序来读取学生成绩,无论是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 

【问题讨论】:

  • 您的预期结果是什么?可以发一下吗?
  • 同时使用 C 和 C++ 语言标签时要小心,因为它们是非常不同的语言。特别是在联合方面,语言之间存在语义差异。所以请编辑你的问题,只包含你真正编程的语言的语言标签。
  • 至于你的问题,你已经把typeOfGrade保存在了结构体中,那你打印成绩的时候为什么不用那个呢?
  • @Chipster 我认为预期的结果是输出与输入相同。所以学生 1 的成绩为“A”,学生 3 的成绩为“99”,其他人则不显示。
  • 感谢@Ville-Valteri。我现在明白了。

标签: c++ c unicode union


【解决方案1】:

在比较中使用等级类型:

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

【讨论】:

    【解决方案2】:

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

    Ville-Valtteri 有一个非常好的答案,但我也想解释一下发生了什么。

    所以,请查看UTF-8 Table

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

    在 C 和 C++ 中,如果我为 char 分配一个数字,这些在某种意义上是同等对待的:

    char c = 65;
    

    它会将其视为字母'A'

    相反,如果我将字母 'A' 分配给 int:

    int i = int('A');
    

    您最终会得到号码65

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

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

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

    现在,你的第二个测试:

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

    那么,如果不是 char 等级 'A',它一定是 int 等级,对吧?错了,因为没有测试它是否是 char 等级,只是它不是 char 等级'A'。不这样,你就可以参加这个测试。

    这意味着字母'b' 将进入此测试,其值为98(再次参见UTF-8 table)。由于 C 和 C++ 将数字和字母视为相同的(技术上不是,但很接近),因此它将其测试为 int 等级 98,即使它打算成为 char 等级。这意味着它通过了您 >= 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);
    

    【讨论】:

    • “这是由前面提到的表格决定的。”:不经常是那个表格。对于像“A”这样的文字,它将是编译器被告知发出的字符编码表(/execution-charset-fexec-charset)。在用户输入的情况下,应该排列一些东西:控制台的字符编码和程序当前的locale。在本世纪的许多情况下,所有这些都是 UTF-8(不幸的是,在许多情况下不是)。 ASCII 可以用作“最小公分母”参考,但这很少是实际使用的。你已经知道 ? 不是 ASCII,对吧?
    • 笑脸?是的,我知道那些不是ASCII。所以你说的是它使用默认/指定的表。这曾经是 ASCII,但现在是 ITF-8?
    • 我想不出一个编译器是 ASCII 是/是默认值。可以肯定的是,ASCII 与许多其他字符编码兼容。但是,在实践中,只有一个被使用;相似的存在是无关紧要的。
    • 啊。好的。好点子。当我有机会时,我会改变它。 UTF-8 中的 A 和 b 仍然是 65 和 98 吗?
    • @TomBlodget 并已编辑。如果您愿意,请随时校对更多内容:)
    猜你喜欢
    • 2015-06-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多