Unicode Char используется неправильно для Int - PullRequest
1 голос
/ 08 марта 2019

Я пишу программу, которая читает оценку ученика, будь то 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 

Ответы [ 2 ]

2 голосов
/ 08 марта 2019

Используйте тип оценки в сравнении:

  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 голос
/ 08 марта 2019

Примечание: В моем первоначальном ответе использовалась таблица ASCII , но кто-то указал, что вместо этого я должен использовать таблицу UTF-8 .Тем не менее, оба действительно похожи для целей, описанных здесь.Тем не менее, технически компиляторы часто используют UTF-8 вместо ASCII, поэтому я отредактировал свой ответ, чтобы отразить это.

У Вилле-Вальттери есть очень хороший ответ, но я хотел бы объяснить, чтои так далее.

Итак, просмотрите таблицу UTF-8 .

Как мы надеемся, вы должны знать, что каждый символ на любом компьютере переводится в число.Это определяется вышеупомянутой таблицей.

В C и C ++ они как бы обрабатываются одинаково в том смысле, что если я назначу число для символа:

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) 

Итак, если это не класс Char«А», это должен быть международный класс, верно?Неправильно, потому что не проверял, является ли это знак чар, только то, что это не чар АВсе, что не так, и вы попадаете в этот тест.

Это означает, что буква 'b' попадет в этот тест со значением 98 (см. Таблицу UTF-8 снова).Так как C и C ++ обрабатывают числа и буквы как одно и то же (не технически, а близко), он проверяет это как int grade 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);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...