Преобразование числа в китайский пиньинь. Знак минус равен «фу».
# номер: пиньинь
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, на выходе «лю лин лин». Я проверил некоторые другие цифры, и все они кажутся хорошими, но веб-сайт проверки сказал, что я ошибаюсь.
Что касается нескольких других, но не связанных между собой заметок, сначала не сокращайте имена. Вместо ipt используйте input. Это облегчает чтение и понимание кода. То же самое и с py. Другое дело, что все три предложения цикла for являются необязательными. Вы можете иметь, например. for (;;) для бесконечного цикла. В вашем случае ведущее предложение «инициализации» не требуется, поэтому вы можете использовать for (; i < strlen(input); i++). Еще лучше, я бы предложил input[i] != '\0' в качестве условия, чтобы вам не приходилось звонить strlen(input) повторно.
@Someprogrammerdude Но не заходите слишком далеко в другом направлении и не делайте переменные настолько длинными, что из-за них будет сложнее прочитать выражение в целом. Назовите это input (или line) вместо ipt, но не называйте previousLineReceivedFromUser. Также помните, какие существуют соглашения для коротких имен переменных. Например, pt for point намного читабельнее, чем ipt for input, и никого не смутит переменная цикла с именем i (хотя я предпочитаю idx для облегчения поиска).



Функция 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']);
В общем, вам следует проверить, действительно ли введенная строка содержит только знак и цифры.
Веб-сайт проверки в конце запрашивает вывод без пробела, поэтому я написал этот подробный код.
Вы проигнорировали возвращаемое значение 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.
TIL использовал практику подчеркивания в Python для «частных» функций.
#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(). Спасибо за ваш ответ, но похоже, это не то, что я хочу.
Благодарим вас за вклад в сообщество Stack Overflow. Возможно, это правильный ответ, но было бы очень полезно предоставить дополнительные пояснения к вашему коду, чтобы разработчики могли понять ваши рассуждения. Это особенно полезно для новых разработчиков, которые не так хорошо знакомы с синтаксисом или пытаются понять концепции. Не могли бы вы отредактировать свой ответ, включив в него дополнительную информацию на благо сообщества?
Помните, что fgets в большинстве случаев добавит к строке конечный символ новой строки. Вы не обрабатываете символ новой строки
'\n'в своем коде.