Числовой индекс элемента массива

Задача

Преобразование числа в китайский пиньинь. Знак минус равен «фу».

ключ-значение

# номер: пиньинь

0: ling
1: yi
2: er
3: san
4: si
5: wu
6: liu
7: qi
8: ba
9: jiu

Код

#include <stdio.h>

int main() {
    char ipt[100];
    char py[10][6] = {"ling", "yi", "er", "san", "si", "wu", "liu", "qi", "ba", "jiu"};

    fgets(ipt, 100, stdin);

    int i = 0;
    if (ipt[0] == '-') {
        printf("%s ", "fu");
        i++;
    }

    for (i; i < strlen(ipt); i++) {
        if (i < strlen(ipt) - 1)
            printf("%s ", py[ipt[i] - '0']);
        else
            printf("%s", py[ipt[i] - '0']);
    }
    return 0;
}

Протестированный случай

Я ввел 600, на выходе «лю лин лин». Я проверил некоторые другие цифры, и все они кажутся хорошими, но веб-сайт проверки сказал, что я ошибаюсь.

Помните, что fgets в большинстве случаев добавит к строке конечный символ новой строки. Вы не обрабатываете символ новой строки '\n' в своем коде.

Some programmer dude 25.04.2024 15:12

Что касается нескольких других, но не связанных между собой заметок, сначала не сокращайте имена. Вместо ipt используйте input. Это облегчает чтение и понимание кода. То же самое и с py. Другое дело, что все три предложения цикла for являются необязательными. Вы можете иметь, например. for (;;) для бесконечного цикла. В вашем случае ведущее предложение «инициализации» не требуется, поэтому вы можете использовать for (; i < strlen(input); i++). Еще лучше, я бы предложил input[i] != '\0' в качестве условия, чтобы вам не приходилось звонить strlen(input) повторно.

Some programmer dude 25.04.2024 15:15

@Someprogrammerdude Но не заходите слишком далеко в другом направлении и не делайте переменные настолько длинными, что из-за них будет сложнее прочитать выражение в целом. Назовите это input (или line) вместо ipt, но не называйте previousLineReceivedFromUser. Также помните, какие существуют соглашения для коротких имен переменных. Например, pt for point намного читабельнее, чем ipt for input, и никого не смутит переменная цикла с именем i (хотя я предпочитаю idx для облегчения поиска).

Ray 26.04.2024 20:44
Структурированный массив Numpy
Структурированный массив Numpy
Однако в реальных проектах я чаще всего имею дело со списками, состоящими из нескольких типов данных. Как мы можем использовать массивы numpy, чтобы...
T - 1Bits: Генерация последовательного массива
T - 1Bits: Генерация последовательного массива
По мере того, как мы пишем все больше кода, мы привыкаем к определенным способам действий. То тут, то там мы находим код, который заставляет нас...
Что такое деструктуризация массива в JavaScript?
Что такое деструктуризация массива в JavaScript?
Деструктуризация позволяет распаковывать значения из массивов и добавлять их в отдельные переменные.
2
3
108
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Функция fgets может добавить символ новой строки '\n' к введенной строке, если в соответствующем массиве символов есть место.

Вам следует удалить его, например:

ipt[ strcspn( ipt, "\n" ) ] = '\0';

В противном случае ваш код также выводит строку для символа новой строки.

И после этого этот оператор if в цикле for:

    if (i < strlen(ipt) - 1)
        printf("%s ", py[ipt[i] - '0']);
    else
        printf("%s", py[ipt[i] - '0']);

следует удалить. Достаточно написать:

printf("%s ", py[ipt[i] - '0']);

В общем, вам следует проверить, действительно ли введенная строка содержит только знак и цифры.

Веб-сайт проверки в конце запрашивает вывод без пробела, поэтому я написал этот подробный код.

mamaruo 25.04.2024 15:59
Ответ принят как подходящий

Вы проигнорировали возвращаемое значение fgets():

fgets(ipt, 100, stdin);

fgets() вернуть нулевой указатель, указывающий на ошибку. Кроме того, fgets() включите во входные данные новую строку (если достаточно места). Самое простое решение по его удалению:

ipt[strcspn(ipt, "\n")] = 0;

Теперь вы можете перебирать strlen() байты, как и изначально. За исключением того, что вам не нужно вызывать strlen() дважды на каждой итерации. Просто кэшируйте значение:

size_t ipt_len = strlen(ipt);

Теперь код становится:

for (i; i < ipt_len; i++) {
    if (i < ipt_len - 1)

Но поскольку вы уже используете strlen(), вы можете избежать вызова strcspn() и сделать:

size_t ipt_len = strlen(ipt); 

if (ipt_len > 0 && name[ipt_len - 1] == '\n') {
    name[--ipt_len] = '\0';
}

Вы также можете упростить вызовы printf():

#if 0
if (i < ipt_len - 1) 
    printf("%s ", py[ipt[i] - '0']);
else
    printf("%s", py[ipt[i] - '0']);
#else
printf("%s%s", py[ipt[i] - '0'], i < ipt_len - 1 ? " " : "");
#endif

Или вообще пропустите пробелы.

Однако вам не удалось проверить, действительно ли входные данные полностью состояли из цифр и знака минус. Должна быть предусмотрена хотя бы какая-то элементарная проверка.

Также обратите внимание, что внутренний размер py:

char py[10][6] = {"ling", "yi", "er", "san", "si", "wu", "liu", "qi", "ba", "jiu"};

должно быть не более 5, а не 6, поскольку самая длинная строка — "ling" и имеет размер 5.

Или вы можете использовать массив char *:

static const char *const py[] = {"ling", "yi", "er", "san", "si", "wu", "liu", "qi", "ba", "jiu" };

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

Проблема с вашим текущим кодом в первую очередь связана с обработкой символа новой строки, который включается при использовании fgets для чтения ввода. Когда вы читаете ввод с помощью fgets, он захватывает символ новой строки \n в конце ввода. Вот почему вы получаете неожиданные результаты. Символом новой строки необходимо правильно управлять, чтобы не интерпретировать его как часть числа. Попробуйте что-то вроде этого:

#include <stdio.h>
#include <string.h>

#define MAX_INPUT_LENGTH 100
#define NUM_DIGITS 10

const char *PYININ_DIGITS[NUM_DIGITS] = {
    "ling", "yi", "er", "san", "si", "wu", "liu", "qi", "ba", "jiu"
};

void trim_newline(char *input) {
    int len = strlen(input);
    if (input[len - 1] == '\n') {
        input[len - 1] = '\0';
    }
}

void print_pinyin(const char *input) {
    int i = 0;
    if (input[0] == '-') {
        printf("fu ");
        i++;
    }
    for (; input[i] != '\0'; i++) {
        printf("%s", PYININ_DIGITS[input[i] - '0']);
        if (input[i + 1] != '\0') {
            printf(" ");
        }
    }
    printf("\n");
}

int main() {
    char input[MAX_INPUT_LENGTH];
    if (fgets(input, sizeof(input), stdin)) {
        trim_newline(input);
        print_pinyin(input);
    }
    return 0;
}

Пример использования 1:

600
liu ling ling

Пример использования 2:

-600
fu liu ling ling

Идентификаторы, начинающиеся с _ и затем строчной буквы, зарезервированы в области файла. _trim_newline должно быть просто trim_newline.

Harith 25.04.2024 15:31

TIL использовал практику подчеркивания в Python для «частных» функций.

Sash Sinha 25.04.2024 17:31

#include<stdio.h>
#include<string.h>

int main()
{
    char s[100];
    char table[11][10] = {"ling","yi","er","san","si","wu","liu","qi","ba","jiu"};
    scanf("%s",s);
    int first = 1;
    for(int i = 0;s[i]!='\0';i++)
    {
        if (i == 0 && s[i] == '-')
        {
            printf("fu"); first = 0; continue;
        }
        int j = s[i] - '0';
        if (first == 0) printf(" ");
        if (first == 1) first = 0;
        printf("%s",table[j]);
    }
    return 0;
}

Вы используете scanf() вместо fgets(). Спасибо за ваш ответ, но похоже, это не то, что я хочу.

mamaruo 26.04.2024 04:11

Благодарим вас за вклад в сообщество Stack Overflow. Возможно, это правильный ответ, но было бы очень полезно предоставить дополнительные пояснения к вашему коду, чтобы разработчики могли понять ваши рассуждения. Это особенно полезно для новых разработчиков, которые не так хорошо знакомы с синтаксисом или пытаются понять концепции. Не могли бы вы отредактировать свой ответ, включив в него дополнительную информацию на благо сообщества?

Jeremy Caney 30.04.2024 03:52

Другие вопросы по теме