実現したいこと
入力:しんぶんし
回分です。
発生している問題・分からないこと
回分です。になりません。
該当のソースコード
#include <stdio.h> #include <wchar.h> #include <locale.h> int main(void) { wchar_t str[256]; size_t len; setlocale(LC_ALL, ""); //(UTF-8対応) wprintf(L"文字列を入力してください:"); fgetws(str, 256, stdin); // 改行削除 len = wcslen(str); if (len > 0 && str[len - 1] == L'\n') { str[len - 1] = L'\0'; len--; } // 回文判定 int is_palindrome = 1; size_t left = 0, right = len - 1; while (left < right) { if (str[left] != str[right]) { is_palindrome = 0; break; } left++; right--; } if (is_palindrome) wprintf(L"回文です。\n"); else wprintf(L"回文ではありません。\n"); return 0; }
試したこと・調べたこと
- teratailやGoogle等で検索した
- ソースコードを自分なりに変更した
- 知人に聞いた
- その他
上記の詳細・結果
数字、英文字では、「回文です」とでるのですが、日本語だとでません。
補足
vs code+mingw64です。
utf-8で保存です。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2025/08/22 13:05

回答4件
0
既に解決済みなので御参考です。
マルチバイト文字列(UTF-8)からワイド文字列に変換せずに,マルチバイト文字列で回文判定を行うという方法も考えられます。mblen() 関数を用いた記述例と実行例(Windows11, PowerShell 7.5.2)を下記に示します。
C
1#include <stdio.h> 2#include <stdlib.h> 3#include <locale.h> 4 5#define N_STR 1024 6 7int main(void) 8{ 9 char str[N_STR]; 10 int str_len, len, is_palindrome; 11 int c, i, j, k; 12 13 if (setlocale(LC_CTYPE, "ja_JP.UTF-8") == NULL) { 14 fprintf(stderr, "error: failed to set locale.\n"); 15 exit(1); 16 } 17 18 printf("文字列を入力してください:"); 19 for (i = 0; i < N_STR - 1 && (c = fgetc(stdin)) != '\n'; i++) 20 str[i] = c; 21 str[i] = '\0'; 22 str_len = i; 23 24 is_palindrome = 1; 25 for (i = 0; i < str_len / 2 && is_palindrome == 1;) { 26 if ((len = mblen(&str[i], MB_CUR_MAX)) <= 0) { 27 fprintf(stderr, "error: contains invalid characters.\n"); 28 exit(2); 29 } 30 for (j = str_len - i - len, k = 0; k < len; i++, j++, k++) 31 if (str[i] != str[j]) { 32 is_palindrome = 0; 33 break; 34 } 35 } 36 37 if (is_palindrome) 38 printf("回文です。\n"); 39 else 40 printf("回文ではありません。\n"); 41 42 exit(0); 43}
PowerShell
1PS > chcp 2Active code page: 65001 3PS > gcc --version 4clang version 19.1.7 5PS > gcc main.c 6PS > .\a.exe 7文字列を入力してください:しんぶん 8回文ではありません。 9PS > .\a.exe 10文字列を入力してください:しんぶんし 11回文です。
(追記)
_setmode()
を使うとマルチバイト文字列(UTF-8)からワイド文字列(Windows: UTF-16)へ変換できると教えていただいたので,指摘されていたサロゲートペア文字(例えば辰𠮷𠀋一郎さんの「𠮷」や「𠀋」などで,ワイド文字のペアに変換される)に対応する記述例を「該当のソースコード」に追記する形で簡単な実行例とともに示します。なお,サロゲートペア文字が変換されているワイド文字ペアの1文字目の値は「0xD800 〜 0xDBFF」(2文字目の値は「0xDC00 〜 0xDFFF」)の範囲であることを用いています。
C
1#include <stdio.h> 2#include <wchar.h> 3#include <locale.h> 4#ifdef _WIN32 5#include <fcntl.h> 6#include <io.h> 7#endif 8 9int main(void) { 10 wchar_t str[256]; 11 size_t len; 12 13 setlocale(LC_ALL, ""); 14#ifdef _WIN32 15 if (_setmode(_fileno(stdin), _O_U8TEXT) == -1) { 16 fprintf(stderr, "error: cannat set mode.\n"); 17 return 1; 18 } 19#endif 20 21 wprintf(L"文字列を入力してください:"); 22 fgetws(str, 256, stdin); 23 24 // 改行削除 25 len = wcslen(str); 26 if (len > 0 && str[len - 1] == L'\n') { 27 str[len - 1] = L'\0'; 28 len--; 29 } 30 31 // 回文判定 32 int is_palindrome = 1; 33 size_t left = 0, right = len - 1; 34 while (left < right) { 35#ifdef _WIN32 36 if (str[left] >= 0xD800 && str[left] <= 0xDBFF) { 37 if (str[left] != str[right - 1] || str[left + 1] != str[right]) { 38 is_palindrome = 0; 39 break; 40 } 41 left += 2; 42 right = right < 2 ? 0 : right - 2; 43 continue; 44 } 45#endif 46 if (str[left] != str[right]) { 47 is_palindrome = 0; 48 break; 49 } 50 left++; 51 right--; 52 } 53 54 if (is_palindrome) 55 wprintf(L"回文です。\n"); 56 else 57 wprintf(L"回文ではありません。\n"); 58 59 return 0; 60}
PowerShell
1PS > chcp 2Active code page: 65001 3PS > gcc --version 4clang version 20.1.8 5PS > gcc main.c 6PS > .\a.exe 7文字列を入力してください:吉𠀋𠮷𠀋吉𠀋吉 8回文ではありません。 9PS > .\a.exe 10文字列を入力してください:吉𠀋𠮷丈𠮷𠀋吉 11回文です。
投稿2025/08/24 23:07
編集2025/08/29 05:22総合スコア533
0
_setmode
で stdin/stdout の変換モードを UTF-16 に変更するとよいかと思います。
The _setmode function sets to mode the translation mode of the file given by fd.
:
You can also pass _O_U16TEXT, _O_U8TEXT, or _O_WTEXT to enable Unicode mode
手元の環境は Windows10 22H2 19045.5737/PowerShell 5.1.19041.5737/MinGW 13.0.0/gcc 15.2.0
です。
c
1#include <stdio.h> 2#include <wchar.h> 3#include <locale.h> 4#include <fcntl.h> 5 6int main(void) { 7 wchar_t str[256]; 8 size_t len; 9 10 _setmode(_fileno(stdin), _O_U16TEXT); 11 fflush(stdout); 12 _setmode(_fileno(stdout), _O_U16TEXT); 13 14 wprintf(L"文字列を入力してください:"); 15 fgetws(str, 256, stdin); 16 17 // 改行削除 18 len = wcslen(str); 19 if (len > 0 && str[len - 1] == '\n') { 20 str[len - 1] = '\0'; 21 len--; 22 } 23 24 // 回文判定 25 int is_palindrome = 1; 26 size_t left = 0, right = len - 1; 27 while (left < right) { 28 wprintf(L"left = %C right = %C\n", str[left], str[right]); 29 if (str[left] != str[right]) { 30 is_palindrome = 0; 31 break; 32 } 33 left++; 34 right--; 35 } 36 37 if (is_palindrome) 38 wprintf(L"回文です。\n"); 39 else 40 wprintf(L"回文ではありません。\n"); 41 42 return 0; 43}
実行結果
powershell
1PS C:\Users\nemo> chcp 2Active code page: 65001 3 4PS C:\Users\nemo> gcc -Wall -Wextra -g -o palindrome palindrome.c 5PS C:\Users\nemo> ./palindrome 6文字列を入力してください:しんぶんし 7left = し right = し 8left = ん right = ん 9回文です。 10PS C:\Users\nemo> ./palindrome 11文字列を入力してください:しんぶん 12left = し right = ん 13回文ではありません。
投稿2025/08/24 12:57
総合スコア21491
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2025/08/24 13:44

0
参考までにGLibを使ってUTF-8で回文判定するコードを挙げておく。
C
1#include <stdio.h> 2#include <stdlib.h> 3#include <locale.h> 4#include <glib.h> 5 6/* GLib 7 https://docs.gtk.org/glib/index.html 8 */ 9 10#define SIZE 256 11 12gchar* input(const gchar* prompt) 13{ 14 g_print("%s", prompt); 15 gchar* buf = g_new(gchar, SIZE * 4); 16 if (fgets(buf, SIZE * 4, stdin)) 17 { 18 /* UTF-8 として妥当か確認 */ 19 if (!g_utf8_validate(buf, -1, NULL)) 20 { 21 g_printerr("UTF-8の入力ではありません。\n"); 22 g_free(buf); 23 return NULL; 24 } 25 } 26 else 27 { 28 g_free(buf); 29 return NULL; 30 } 31 /* 改行を除去 */ 32 buf[strcspn(buf, "\n")] = '\0'; 33 return buf; 34} 35 36/* 回文判定 */ 37gboolean is_palindrome(const gchar* str) 38{ 39 glong len = g_utf8_strlen(str, -1); 40 41 for (glong i = 0; i < len / 2; i++) 42 { 43 gunichar left = g_utf8_get_char(g_utf8_offset_to_pointer(str, i)); 44 gunichar right = g_utf8_get_char(g_utf8_offset_to_pointer(str, len - i - 1)); 45 46 if (left != right) 47 { 48 return FALSE; 49 } 50 } 51 52 return TRUE; 53} 54 55 56int main(void) 57{ 58 setlocale(LC_ALL, ""); /* (UTF-8対応) */ 59 gchar* str = input("文字列を入力してください : "); 60 if (!str) 61 { 62 return EXIT_FAILURE; 63 } 64 g_print("%s", is_palindrome(str) ? "回文です。\n" : "回文ではありません。\n"); 65 g_free(str); 66 return EXIT_SUCCESS; 67} 68
Linux等では
sh
1gcc -Wall ソースコード.c $(pkg-config --cflags --libs glib-2.0
等でコンパイル可能だろう。
ただし、Debian系だとpkg-config
をまずは弄らないとならないかも。
また、GLibはWindows版もあるようだが、詳細は分からん。
GLibは一応、UTF-8前提で文字列をイジる事が出来る、と言う建前ではあるんだけど、ぶっちゃけ苦労した(笑)。
あまりデータ変換しまくるとWarningが取れない、ってぇんで、結果一番シンプルなカタチになっちまった。
まぁ、シンプル・イズ・ベストって事なのかもしんないが。
256文字が上限、って事だが、結果その4倍の量のバッファを取っている。
というのも、マルチバイト文字の場合、とある研究に依ると、世界中のあらゆる文字を合わせても大体4バイト以下に収まる、と言われている。
UTF-8は一文字辺りのバイトが伸びたり縮んだりするけど、最悪のケースでも、1024バイトあればどんな文字だろうと256文字分は格納可能だ、ってぇんで256バイトの4倍を上限としてる。
fgets
は実は「どういう文字コードで入力されているのか」感知しない。単にバイト毎に読み込むだけだ。
そこで、GLibのg_utf8_validateで入力がUTF-8なのかどうかをチェックして、あとは単に回文判定へと回す、と言ったシンプルなカタチになっている。
また、Cの標準装備のヘッダを使わないで、GLibだけで何とかなるか、とか思ったけど何ともならんかった(笑)。
GIOChannelとか使えばfgets
とか使わんでも・・・と淡い夢を見たが、余計複雑になってどうにもならんかった。もっとGLibに詳しい人ならもっとカッコいいコードを書けたかもしれないが。
結局僕はカッコよくなかったわけだ(笑)。クソ。
まぁ、これが僕の限界かな(笑)。
投稿2025/08/23 18:34
総合スコア212
0
ベストアンサー
以下の2環境で確認しました。ソースはUTF-8で保存です。
OS | コンパイラー | PowerShell |
---|---|---|
Windows 11 | Visual Studio 2022 | 5.1.26100.4768 |
Windows 11 | gcc(mingw64) 15.2.0 | 5.1.26100.4768 |
PowerShellのコードページが932(Shift_JIS)のときは、提示されたソースで正しく動作します。
65001(UTF-8)のときは、提示されたソース、setlocale(LC_ALL, ".UTF-8");
に変更したソースの両方とも正しく動作しませんでした。
(65001に変更するときはchcp 65001
、932に戻すときはchcp 932
と打ちます。確認するときはchcp
のみです)
おそらくですが、fgetws
関数の動作がOS標準のコードページ→UTF-16の変換
のみをサポートしていて、setlocaleが効いていないと思われます。
コメントの2人とも、LinuxではOS標準のコードページがUTF-8なので、setlocaleがそのままでUTF-8→UTF-16の変換
に対応しています。
- 質問者さんのPowerShellのコードページは、何でしょうか?
- fgetwsの入力コードページをsetlocale以外で変更する方法をご存じの方は、教えてください。
あと、このプログラムは、ほとんどのUTF-16はwchar_tが1個で1文字なので、たまたま動作しています。
サロゲートペア文字(wchar_tが2個で1文字)では上手くいかないと思います。
(追記)
詳細は、melianさんの回答の通りですが、
#include <fcntl.h>
と
_setmode(_fileno(stdin), _O_U8TEXT);
の追加で、65001でも動作します。
投稿2025/08/23 07:46
編集2025/08/24 14:01総合スコア1642
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2025/08/23 08:01
2025/08/23 10:03

あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。