Акцентированные / umlauted символы в C?

Я просто узнаю о C и получил задание, где мы должны перевести текст в морском коде и обратно. (Я в основном знаком с Java, так что несите меня на условиях, которые я использую).

Для этого у меня есть массив со строками для всех букв.

char *letters[] = { ".- ", "-... ", "-.-. ", "-.. ", ".", "..-." etc 

Я написал функцию для возврата позиции нужной буквы.

 int letter_nr(unsigned char c) { return c-97; } 

Это работает, но спецификации присваивания требуют обработки шведских букв umäauted åäö. Шведский алфавит в конце концов совпадает с английским с этими тремя буквами. Я попытался проверить их, например:

 int letter_nr(unsigned char c) { if (c == 'å') return 26; if (c == 'ä') return 27; if (c == 'ö') return 28; return c-97; } 

К сожалению, когда я попытался проверить эту функцию, я получаю то же значение для всех этих трех: 98. Вот моя основная функция тестирования:

 int main() { unsigned char letter; while(1) { printf("Type a letter to get its position: "); scanf("%c", &letter); printf("%d\n", letter_nr(letter)); } return 0; } в int main() { unsigned char letter; while(1) { printf("Type a letter to get its position: "); scanf("%c", &letter); printf("%d\n", letter_nr(letter)); } return 0; } 

Что я могу сделать, чтобы решить эту проблему?

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

 printf("letter 0x%x is number %d\n", letter, letter_nr(letter)); 

Это даст шестую ценность для ваших умляутов. Вместо того, чтобы просто заменить в заявлениях ваше письмо с номером.

EDIT. Вы говорите, что вы всегда получаете 98, чтобы ваш сканер получил 98 + 97 = 195 = 0x3C с консоли. Согласно этой таблице 0x3C – это начало последовательности UTF8 для общего LATIN SMALL LETTER N WITH Something в Latin1 block . Вы находитесь в Mac OS X ?

EDIT Это мой последний звонок. Достаточно хакерство, но оно работает для меня 🙂

 #include  // scanf for for letter. Return position in Morse Table. // Recognises UTF8 for swedish letters. int letter_nr() { unsigned char letter; // scan for the first time, scanf("%c", &letter); if(0xC3 == letter) { // we scanf again since this is UTF8 and two byte encoded character will come scanf("%c", &letter); //LATIN SMALL LETTER A WITH RING ABOVE = å if(0xA5 == letter) return 26; //LATIN SMALL LETTER A WITH DIAERESIS = ä if(0xA4 == letter) return 27; // LATIN SMALL LETTER O WITH DIAERESIS = ö if(0xB6 == letter) return 28; printf("Unknown letter. 0x%x. ", letter); return -1; } // is seems to be regular ASCII return letter - 97; } // letter_nr int main() { while(1) { printf("Type a letter to get its position: "); int val = letter_nr(); if(-1 != val) printf("Morse code is %d.\n", val); else printf("Unknown Morse code.\n"); // strip remaining new line unsigned char new_line; scanf("%c", &new_line); } return 0; } в #include  // scanf for for letter. Return position in Morse Table. // Recognises UTF8 for swedish letters. int letter_nr() { unsigned char letter; // scan for the first time, scanf("%c", &letter); if(0xC3 == letter) { // we scanf again since this is UTF8 and two byte encoded character will come scanf("%c", &letter); //LATIN SMALL LETTER A WITH RING ABOVE = å if(0xA5 == letter) return 26; //LATIN SMALL LETTER A WITH DIAERESIS = ä if(0xA4 == letter) return 27; // LATIN SMALL LETTER O WITH DIAERESIS = ö if(0xB6 == letter) return 28; printf("Unknown letter. 0x%x. ", letter); return -1; } // is seems to be regular ASCII return letter - 97; } // letter_nr int main() { while(1) { printf("Type a letter to get its position: "); int val = letter_nr(); if(-1 != val) printf("Morse code is %d.\n", val); else printf("Unknown Morse code.\n"); // strip remaining new line unsigned char new_line; scanf("%c", &new_line); } return 0; } 

Кодирование символьных констант действительно зависит от ваших настроек локали.

Самая безопасная ставка – использовать широкие символы и соответствующие функции. Вы объявляете алфавит как const wchar_t* alphabet = L"abcdefghijklmnopqrstuvwxyzäöå" , а отдельные персонажи – L'ö';

Эта небольшая примерная программа работает для меня (также на консоли UNIX с UTF-8) – попробуйте.

 #include  #include  #include  #include  int main(int argc, char** argv) { wint_t letter = L'\0'; setlocale(LC_ALL, ""); /* Initialize locale, to get the correct conversion to/from wchars */ while(1) { if(!letter) printf("Type a letter to get its position: "); letter = fgetwc(stdin); if(letter == WEOF) { putchar('\n'); return 0; } else if(letter == L'\n' || letter == L'\r') { letter = L'\0'; /* skip newlines - and print the instruction again*/ } else { printf("%d\n", letter); /* print the character value, and don't print the instruction again */ } } return 0; } в #include  #include  #include  #include  int main(int argc, char** argv) { wint_t letter = L'\0'; setlocale(LC_ALL, ""); /* Initialize locale, to get the correct conversion to/from wchars */ while(1) { if(!letter) printf("Type a letter to get its position: "); letter = fgetwc(stdin); if(letter == WEOF) { putchar('\n'); return 0; } else if(letter == L'\n' || letter == L'\r') { letter = L'\0'; /* skip newlines - and print the instruction again*/ } else { printf("%d\n", letter); /* print the character value, and don't print the instruction again */ } } return 0; } 

Пример сеанса:

 Type a letter to get its position: a 97 Type a letter to get its position: A 65 Type a letter to get its position: Ö 214 Type a letter to get its position: ö 246 Type a letter to get its position: Å 197 Type a letter to get its position: <^D> 

Я понимаю, что в Windows это не работает с символами за пределами Unicode BMP, но это не проблема.

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

Попробуйте это (добавьте оставшиеся биты):

 char buf[100]; printf("Enter a string with funny characters: "); fflush(stdout); fgets(buf, sizeof buf, stdin); /* now print it, as if it was a sequence of `char`s */ char *p = buf; while (*p) { printf("The character '%c' has value %d\n", *p, *p); p++; } 

Теперь попробуйте то же самое с широкими символами: #include и замените printf на wprintf , fgets с fgetws и т. Д. …