#c
#c
Вопрос:
Учитывая оценку аллергии человека, определите, есть ли у него аллергия на данный продукт и его полный список аллергий.
Тест на аллергию выдает единую числовую оценку, которая содержит информацию обо всех аллергиях, которые есть у человека (на которые они были протестированы).
Список продуктов (и их стоимость), которые были протестированы, являются:
яйца (1) арахис (2) моллюски (4) клубника (8) помидоры (16) шоколад (32) пыльца (64) кошки (128) Таким образом, если у Тома аллергия на арахис и шоколад, он получает 34 балла.
Теперь, учитывая только этот показатель 34, ваша программа должна быть в состоянии сказать:
Есть ли у Тома аллергия на какой-либо из перечисленных выше аллергенов. Все аллергены, на которые у Тома аллергия. Примечание: данная оценка может включать аллергены, не перечисленные выше (т. Е. аллергены, набравшие 256, 512, 1024 и т.д.). Ваша программа должна игнорировать эти компоненты оценки. Например, если оценка аллергии равна 257, ваша программа должна сообщать только об аллергии на яйца (1).
int main()
{
int score;
printf("Enter the score:");
scanf("%d",amp;score);
if(score >1024)
{
score -= 1024;
check_allergies(score);
}
else if(score > 512 amp;amp; score<1024)
{
score -= 512;
check_allergies(score);
}
else if(score > 256 amp;amp; score <512)
{
score -= 256;
check_allergies(score);
}
else if(score > 128 amp;amp; score <256)
{
score -= 128;
check_allergies(score);
score = 128;
check_allergies(score);
}
else if (score > 64 amp;amp; score < 128)
{
score -= 64;
check_allergies(score);
score = 64;
check_allergies(score);
}
else if (score > 32 amp;amp; score <64)
{
score -= 32;
check_allergies(score);
score = 32;
check_allergies(score);
}
else if (score > 16 amp;amp; score <32)
{
score -= 16;
check_allergies(score);
score = 16;
check_allergies(score);
}
else if(score > 8 amp;amp; score < 16)
{
score -= 8;
check_allergies(score);
score = 8;
check_allergies(score);
}
else if(score > 4 amp;amp; score < 8)
{
score -= 4;
check_allergies(score);
score = 4;
check_allergies(score);
}
else if(score > 2 amp;amp; score < 4)
{
score -= 2;
check_allergies(score);
score = 2;
check_allergies(score);
}
else if(score > 1 amp;amp; score < 2)
{
score -= 1;
check_allergies(score);
score = 1;
check_allergies(score);
}
else
check_allergies(score);
}
void check_allergies(int score)
{
if (score == 1)
printf("Egg");
else if(score==2)
printf("Peanuts");
else if(score==4)
printf("Shellfish, ");
else if(score==8)
printf("Strawberries, ");
else if(score==16)
printf("Tomatoes, ");
else if(score==32)
printf("Chocolate, ");
else if(score==64)
printf("Pollen, ");
else if(score==128)
printf("Cats, ");
else
printf("No disease");
}
Я почти получаю правильный ответ для таких значений, как 130,33,68 и т.д. Но для таких чисел, как 35, 133 и т.д., Я не получаю правильного ответа, возможно, они не проходят проверку состояния check_allergies. Я могу записать каждое условие в функции check_allergies, например, для score == 3, score == 5 и т.д. Но это увеличит строку кодов. Можете ли вы помочь мне сделать это каким-либо другим способом?
Комментарии:
1. Совет: Проверьте последовательность цифр, 1, 2, 4, 8, 16, 32 и т.д. … это кажется вам знакомым? Ответ, как сделать это простым способом, находится там.
2. Знаете ли вы, почему вы не получаете правильного ответа на 35?
3. Опубликованный код не компилируется чисто! 1) в нем отсутствует оператор:
#include <stdio.h>
2) нет прототипа дляcheck_allergies()
перед его вызовом.
Ответ №1:
Аллергии кодируются как битовая схема, занимающая 8 бит (1 байт).
Чтобы игнорировать компоненты оценки, не входящие в ваш диапазон, вы можете и ввести оценку с помощью 0xff
.
Чтобы проверить, была ли аллергия закодирована во входных данных, вы можете и это с помощью bit.
Примеры:
#define eggs 1
#define peanuts 2
#define shellfish 4
#define strawberries 8
#define tomatoes 16
#define chocolate 32
#define pollen 64
#define cats 128
Или:
#define eggs 0x01
#define peanuts 0x02
#define shellfish 0x04
#define strawberries 0x08
#define tomatoes 0x10
#define chocolate 0x20
#define pollen 0x40
#define cats 0x80
Чтобы игнорировать неопределенные части аллергии:
int allergies= input amp; 0xff;
Чтобы проверить аллергию, вы проверяете, установлен ли бит:
if (allergies amp; cats) {
// allergic to cats
}
Ответ №2:
Использование растровых изображений, как предложено в других ответах, является очень хорошей идеей и настоятельно рекомендуется, но вот ответ, почему ваша оригинальная программа работает некорректно:
else if(score > 128 amp;amp; score <256)
{
score -= 128;
check_allergies(score); /* HINT 1 */
score = 128; /* HINT 2 */
check_allergies(score);
}
ПОДСКАЗКА 1: вот почему это работает, например, для 129 — если остаток (1) является допустимым кодом allgergy, он выведет это название аллергии.
ПОДСКАЗКА 2: вот почему это не работает, например, для 131 — строка ПОДСКАЗКИ 1 не выдает правильный вывод (потому что 3 не является кодом для аллергии), и теперь score
установлено значение 128
, поэтому все остальные коды аллергии, которые были закодированы в score
, теряются.
Замените этот блок (и подобные блоки) на эту конструкцию, и это сработает.
else if(score >= 128 amp;amp; score <256)
{
check_allergies(128); /* HINT 1 */
score -= 128;
}
Ответ №3:
Эта задача очень подходит для битовых масок.
Вот краткий пример:
// The bit masks, note that they are powers of two
const int egg=1;
const int peanuts=2;
const int shellfish=4;
// How we check if allergic to peanuts
if(score amp; peanuts)
printf("Peanuts, ");
Это работает, потому что любая степень двойки в двоичном формате будет равна единице 1
, а остальные будут нулями. score amp; peanuts
вернет число, в котором все биты равны нулю, за исключением тех, которые равны единице в ОБОИХ score
И peanuts
. И если хотя бы один бит установлен равным единице, это будет ненулевое число и, таким образом, score amp; peanuts
будет оценено как true.
Таким образом, на самом деле нет необходимости уменьшать значение score
снова и снова.
Вот короткий фрагмент, демонстрирующий это:
void check_allergies(int score)
{
const struct {
int mask;
char *name;
} allergies[] = {{1, "Egg"},
{2, "Peanuts"},
{4, "Shellfish"}
}; // Just add more allergies in this array
if(score == 0) {
printf("No allergies");
return;
}
for(int i=0; i<sizeof allergies/sizeof allergies[0]; i ){
if(score amp; allergies[i].mask)
printf("%s, ", allergies[i].name);
}
}
int main(void)
{
int score;
printf("Enter the score:");
if(scanf("%d",amp;score) != 1) { // Always check scanf for error
perror("Error reading score");
exit(EXIT_FAILURE);
}
check_allergies(score);
}
Комментарии:
1. Судя по содержанию вопроса, OP может не иметь знаний о побитовых операторах или о том, как они работают, или, возможно, даже о том, как числа представлены в двоичном формате, и, вероятно, не имеет знаний о массивах, структурах
sizeof
и, возможно, циклах.2. @EricPostpischil Возможно, но кто-то другой может извлечь из этого пользу.