質問するログイン新規登録
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

タグ

特殊な記法により文書に埋め込む形で記述される付加情報をタグと呼びます。文書構造や書式、文字飾りなどを指示したり、画像や他の文書へのリンクを埋め込むことができる。

Q&A

解決済

4回答

626閲覧

c言語 回分について

bishop

総合スコア2

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

タグ

特殊な記法により文書に埋め込む形で記述される付加情報をタグと呼びます。文書構造や書式、文字飾りなどを指示したり、画像や他の文書へのリンクを埋め込むことができる。

0グッド

0クリップ

投稿2025/08/22 11:28

0

0

実現したいこと

入力:しんぶんし

回分です。

発生している問題・分からないこと

回分です。になりません。

該当のソースコード

#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ページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

melian

2025/08/22 11:52

Ubuntu Linux 25.04/gcc 14.2.0 でビルド、「しんぶんし」を入力すると「回文です。」と表示されます。もしかして文字エンコーディングを CP932 にしたままで文字列を入力していませんか?
cametan

2025/08/22 13:05

追試。 Xubuntu 24.04LTSでclang18.1.3でコンパイル。同様に「しんぶんし」で入力すると「回文です。」と表示。 melian氏が言ってる通り、恐らくWindowsで?ターミナル(DOS窓/PowerShell)の文字コードがUTF-8になってない、って事だろうね。 文字コードの設定(CHCP): https://www.javadrive.jp/command/display/index5.html
bishop

2025/08/23 09:15

chcp で確認しました。 Active code page: 65001 でした。 システムロケールのところもチェックはいってました。
guest

回答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回文です。

投稿2025/08/24 23:07

編集2025/08/25 09:58
little_street

総合スコア489

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

bishop

2025/08/25 10:38 編集

ありがとうございます、研究します。 melianさんのところへ乗せます。
guest

0

_setmode で stdin/stdout の変換モードを UTF-16 に変更するとよいかと思います。

_setmode | Microsoft Learn

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

melian

総合スコア21428

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hiroki-o

2025/08/24 13:44

こちらのWindows 11では、 - %Cを%cに変更しないとleft,rightが正しく表示されない - _O_U16TEXTでも_O_U8TEXTでも正しく動いているみたい ですが、65001で動作確認できました。 私の調査では`_setmode`にたどり着けませんでした。 さすがです。
bishop

2025/08/25 10:54

 みなさま、いろいろありがとうございました。 自分でもいろいろためして、mingwも最新のに入れ直しました。 vs code+mingw+code runnerという環境です。 文字化けをなおすために、 cの設定のところを-fexec-charset=CP932を追加していたので、 これを元にもどしましたら。うまく作動しました。
guest

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

cametan

総合スコア178

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

bishop

2025/08/25 10:39 編集

ありがとうございます。 melianさんのところへ乗せます。
guest

0

ベストアンサー

以下の2環境で確認しました。ソースはUTF-8で保存です。

OSコンパイラーPowerShell
Windows 11Visual Studio 20225.1.26100.4768
Windows 11gcc(mingw64) 15.2.05.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
hiroki-o

総合スコア1559

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

cametan

2025/08/23 08:01

そもそもワイド文字≠UTF-8だしねぇ。 他の言語ならいざ知らず、Cだとこの辺悩ましい。 みんなどうしてんだろ? 結局、実の事言うと、問題構成として「アルファベットしか使わない」回文の方が、Cの問題としては適切なんだよなぁ。orz
bishop

2025/08/23 09:19 編集

chcp で確認しました。 Active code page: 65001 でした。 hiroki-oさんのいわれた方法でやりました。 コードページが932(Shift_JIS)にして chcp 932でやったところ、「回文です」とでました。 chcp65001にもどしますと、成立しませんでした。
hiroki-o

2025/08/23 09:37

bishopさん なるほど、こちらで把握している現象と同じですね。 Windowsはそういうものだと納得して932で実行するか、fgetwsの設定を変える方法の回答を待つか。 後者は、調べてもわかりませんでした。 cametanさん 今どきは、UTFがどうの、みたいなプログラムはCで作らない流れなのでは。
cametan

2025/08/23 10:03

ん〜。「今どき」と言うより正攻法だと元々向いてない。 多分UTF-8を導入したのってJavaが最初じゃなかったかしらん? よって「Java以前言語」ってそもそも怪しいんだよな。Python 2.xも対応が怪しかったし。 C用のライブラリがあるかも、とか思ったけど見つけられなかったです。
bishop

2025/08/23 10:08

みな様ありがとうございます。 一応の解決といたします。 ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.30%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問