简体   繁体   English

char的unicode误用于int

[英]unicode of char misused for int

I'm writing a program that reads student grade whether it was a char or an int and store it in a union , then it prints the students whose grades are A or >90. 我正在编写一个程序来读取学生成绩,无论是char还是int ,并将其存储在union ,然后打印成绩为A或> 90的学生。

But when I try to do that I get an unexpected output because the program doesn't know which one (the char or the int) I want to compare. 但是当我尝试这样做时,我得到一个意外的输出,因为程序不知道我要比较哪一个(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;
}

And this is the output: 这是输出:

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 

Use the type of grade in the comparison: 在比较中使用等级类型:

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

Note: My original answer used the ASCII Table , but someone pointed out I should be using the UTF-8 Table instead. 注意:我的原始答案使用了ASCII表 ,但有人指出我应该使用UTF-8表 However, both are really similar for the purposes described here. 但是,两者都非常类似于此处描述的目的。 However, technically compilers will often use UTF-8 instead of ASCII, so I've edited my answer to reflect that. 但是,技术上的编译器通常会使用UTF-8而不是ASCII,所以我编辑了我的答案来反映这一点。

Ville-Valtteri has a perfectly good answer, but I would like to explain what's going on too. Ville-Valtteri有一个非常好的答案,但我想解释一下发生了什么。

So, please review the UTF-8 Table . 所以,请查看UTF-8表

As hopefully you should know, every character on any computer gets translated into a number. 希望您应该知道,任何计算机上的每个角色都会被翻译成一个数字。 This is determined by the aforementioned table. 这由上述表格确定。

In C and C++, these are sort of treated equally in the sense that if I assign a number to an char: 在C和C ++中,如果我为一个char分配一个数字,那么它们在某种意义上是同等对待的:

char c = 65;

It will treat it as the letter 'A' . 它将它视为字母'A'

Conversely, if I assign the letter 'A' to an int: 相反,如果我将字母'A'分配给int:

int i = int('A');

You end up with the number 65 . 你的结果是65

Okay, so now with your code. 好的,现在你的代码。 Let's look at your first test: 让我们看看你的第一个测试:

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

You test to see if the value is == to 'A' . 您测试以查看值是否= = 'A' Note you do not check for type, so 65 is perfectly acceptable for this test, even if you added it as an int because you are not testing for that. 请注意,您不检查类型,因此65对于此测试是完全可以接受的, 即使您将其添加为int也是因为您没有对此进行测试。 You are testing ONLY for 'A' or its equivalent 65 . 测试'A'或等值65

Now, your second test: 现在,你的第二次测试:

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

So, if it's not a char grade 'A', it must be an int grade right? 那么,如果它不是一个字母等级'A',它必须是一个int等级的权利? Wrong, because didn't test for if it's a char grade, only that it isn't char grade 'A'. 错了,因为没有测试它是否是一个char等级,只是它不是char等级'A'。 Anything not that, and you get to this test. 没有那个,你接受这个测试。

That means the letter 'b' would get to this test, which has a value of 98 (see the UTF-8 table again). 这意味着字母'b'将进入此测试,其值为98 (再次参见UTF-8表 )。 Since C and C++ treat numbers and letters as sort of the same (not technically, but close), it tests this as a int grade 98, even though it's intended to be a char grade. 由于C和C ++将数字和字母视为相同(不是技术上,但是接近),因此它将测试为98级,即使它是一个char等级。 That means it passes you >= 90 check. 这意味着它通过你> = 90检查。

Which brings us to Ville-Valtteri's solution , which is to account for the type of grade in your check. 这将我们带到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); 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM