Я решаю задачи cs50 из набора задач 2, и моя функция «точка» неправильно добавляет очки. Функция продолжает игнорировать все операторы if и else if, даже если есть символы, соответствующие этому оператору if.
#include <cs50.h>
#include <stdio.h>
#include <string.h>
int score1 = 0;
int score2 = 0;
int point(string ply);
void compare(int pl1, int pl2);
int main(void)
{
string ply1 = get_string("Player 1: ");
string ply2 = get_string("Player 2: ");
score1 = point(ply1);
score2 = point(ply2);
compare(score1, score2);
}
//calculate point
int point(string ply)
{
int score = 0;
for(int i = 0; i < strlen(ply); i++)
{
if (ply[i] == ('a'|'e'|'i'|'l'|'n'|'o'|'r'|'s'|'t'|'u'))
{
score += 1;
printf("yes\n");
}
else if (ply[i] == ('d'|'g'))
{
score += 2;
}
else if (ply[i] == ('b'|'c'|'m'|'p'))
{
score += 3;
}
else if (ply[i] == ('f'|'h'|'v'|'w'|'y'))
{
score += 4;
}
else if (ply[i] == 'k')
{
score +=5;
}
else if (ply[i] == ('j'|'x'))
{
score += 8;
}
else
(
score += 10
);
}
return score;
}
//compare score
void compare(int pl1, int pl2)
{
if (pl1 < pl2)
{
printf("Player 2 won!\n");
}
else if (pl1 > pl2)
{
printf("player 1 won!\n");
}
else
{
printf("tie\n");
}
}
Я запускаю это в отладчике cs50, и когда дело доходит до функции if, она ничего не добавляет к оценке, а просто пропускает.
И ply[i] == ('a'|'e'|'i'|'l'|'n'|'o'|'r'|'s'|'t'|'u') не делает того, что вы думаете. Он вычисляет ('a'|'e'|'i'|'l'|'n'|'o'|'r'|'s'|'t'|'u') с использованием побитового ИЛИ, создавая ненулевое значение. Затем вы сравниваете это ненулевое значение с ply[i]. Если вы хотите сравнить несколько значений, вам необходимо выполнить несколько сравнений. Например, ply[i] == 'a' || ply[i] == 'e' и т. д. Также обратите внимание на использование логического оператора ИЛИ ||.
как мне написать это так, чтобы ply[i] сравнивал себя с этими буквами индивидуально и возвращал true, когда оно правильное. я пытался использовать || но это не позволяет мне сделать это
«но это не позволяет мне это сделать», значит, вы сделали это неправильно. То, как SomeProgrammerDude показал это в комментарии выше вашего, правильно. Если это не работает для вас, вам нужно обновить свой вопрос. Добавьте новую версию внизу, не удаляйте исходный код.
Проблема в том, что вы просто вводите случайные данные и надеетесь, что именно так работает язык программирования. Но программирование так не работает — здесь нет метода «рискнуть», метода проб и ошибок. Вы либо знаете, как что-то работает, либо нет. Если нет, вы ищете это в книге или другом источнике обучения.
Кроме того: ошибка расчета: пустое значение равно 0. point() дает ему оценку 10.





Условия, которые у вас есть, не делают того, что вы думаете.
Во-первых, напоминаем, что литералы char, такие как 'a', на самом деле являются просто причудливым способом записи чисел — они интерпретируются как их значения ASCII. | — это оператор bitwsie или . Итак, когда у вас есть оператор типа ply[i] == ('a'|'e'|'i'|'l'|'n'|'o'|'r'|'s'|'t'|'u'), вычисляется правая часть равенства (она равна 127), а затем ply[i] сравнивается с ней.
Правильный синтаксический способ записи условия, которое вы намеревались написать, — это серия логических или условий:
if (ply[i] == 'a' ||
ply[i] == 'e' ||
ply[i] == 'i' ||
ply[i] == 'l' ||
ply[i] == 'n' ||
ply[i] == 'o' ||
ply[i] == 'r' ||
ply[i] == 's' ||
ply[i] == 't' ||
ply[i] == 'u') {
score += 1;
}
// else if etc...
Но это очень громоздко. Более аккуратное решение могло бы заключаться в реализации хэш-карты бедняка.
Каждый персонаж от 'a' до 'z' приносит определенное количество очков. А поскольку литералы char — это просто причудливые числа, если из каждого 'a' вычесть char, вы получите числа от 0 до 25, которые можно использовать в качестве индексов массива.
Вы можете создать массив значений точек:
const int POINTS[] = {1, 3, 3, 2, 1, 4, 2, 4, 1, 8, 5, 1, 3, 1, 1, 3, 10, 1, 1, 1, 1, 4, 4, 8, 4, 10};
int points (char* str) {
int score = 0;
for (int i = 0; i < strlen(str); ++i) {
score += POINTS[str[i] - 'a'];
}
return score;
}
Строго говоря, не стоит учить новичков выполнять арифметические действия с символьными константами, поскольку, строго говоря, нет никакой гарантии, что a и z соседствуют (утомительный старый аргумент EBCDIC). Вместо этого я бы пожертвовал несколькими сотнями байт ПЗУ и сделал что-то вроде const uint8_t POINTS[256] = { ['a']=1, ['b']=3, ...};... score += POINTS[str[i]];. Желающие могут добавить версию в верхнем регистре внутри той же таблицы. В качестве бонуса это также дает ноль баллов за все небуквы.
Если суммируемая плитка представляет собой blank, POINTS[str[i] - 'a'] будет проблемой.
@Lundin педантичный: score += POINTS[str[i]]; будет проблемой, когда char в str[i] будет отрицательным.
@Mureinik хорошо объясняет проблему ОП.
Альтернативные подведения итогов, как прокомментировал @Lundin
#include <ctype.h>
int point_alternative1(string ply) {
static const unsigned char points[] = { ['A']=1, ['B']=3, /* 23 more */ ['Z']=10};
int score = 0;
for(size_t i = 0; ply[i]; i++) {
unsigned char character = str[i];
character = toupper(character);
if (character < sizeof points) {
score += points[character];
}
}
return score;
}
// OR
#include <limits.h>
int point_alternative2(string ply) {
static const unsigned char points[UCHAR_MAX + 1] = { //
['A']=1, ['B']=3, /* 23 more */ ['Z']=10, //
['a']=1, ['b']=3, /* 23 more */ ['z']=10 };
int score = 0;
for(size_t i = 0; ply[i]; i++) {
score += points[(unsigned char) ply[i]];
}
return score;
}
// OR
#include <limits.h>
int point_alternative3(const char *s) {
static const unsigned char points[UCHAR_MAX + 1] = { //
['A']=1, ['B']=3, /* 23 more */ ['Z']=10, //
['a']=1, ['b']=3, /* 23 more */ ['z']=10 };
const unsigned char *us = (const unsigned char *) s;
int score = 0;
while (*us) {
score += points[*us++];
}
return score;
}
Что вам расскажет курс CS50 о передаче аргументов функциям? Он должен был научить вас, что аргументы передаются по значению. Это означает, что значение в вызове копируется в переменную локального аргумента функции. Любые изменения, которые вы вносите в переменные локальных аргументов функции, будут потеряны при возврате функции.