質問をすることでしか得られない、回答やアドバイスがある。

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

新規登録して質問してみよう
ただいま回答率
85.48%
C

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

Q&A

解決済

3回答

4538閲覧

C言語 fgetsで半分に切れてしまった2バイト文字を判定し、出力させないようにする方法

Alyn

総合スコア50

C

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

0グッド

0クリップ

投稿2018/07/30 01:33

実現したいこと

fgetsで文字をオーバーフローせず出力するものを作ってみたのですが、「aあああああ」と入力すると「 aああああ・」となってしまいます。
この"・"のような2バイト文字が半分に切れてしまった文字を判定し、出力させないようにするにはどうしたらよいでしょうか?

ソースコード

C

1#include <stdio.h> 2void main() 3{ 4 /*--------変数・配列の宣言--------*/ 5 int iCount = 0; /* 入力した文字数を数える変数 */ 6 char cBuffer[200] = {'\0'}; /* 入力した文字を出力するための配列 */ 7 8 printf("1_文字列を入力し、その文字列をそのまま出力します。\n"); 9 10 printf("文字列を入力:"); 11 12 /*--------文字列の入力--------*/ 13 fgets(cBuffer, 11, stdin); 14 15 /*--------NAL文字を配列の最後にする--------*/ 16 while(cBuffer[iCount] != 0x00) 17 { 18 if(cBuffer[iCount] == 0x0a) 19 { 20 cBuffer[iCount] = 0x00; 21 putchar('\n'); /* 改行 */ 22 break; 23 } 24 iCount++; 25 } 26 27 /*--------文字列の出力--------*/ 28 printf("入力した文字列は「 %s 」です。\n", cBuffer); /* 入力した文字列を出力 */ 29}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

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

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

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

guest

回答3

0

既に解決済みのようですが、、、。

第2バイトが0x81~0x9fまたは0xe0~0xefの文字ってありますか?

MS-IME より、
0x81-0x9F

0xE0-0xEF

投稿2018/07/30 12:10

pepperleaf

総合スコア6383

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

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

0

ベストアンサー

おそらく文字コードはSJISと思われるので、その前提で。
全角文字は2バイト構成で1バイト目は0x81~0x9f 0xe0~0xef の範囲と決まっています。
参考
文字コード表 シフトJIS(Shift_JIS)

なので文字列の末尾の文字コードがこの範囲であればNULLに置き換えてあげれば文字化けはなくなります。
単純に書くなら最後のprintfの前に以下のコードを足してください。
但しcBufferの定義をcharからunsigned charに変更することをお忘れなく。
またstring.hのインクルードも追加してください。

c

1 int n; 2 n = strlen(cBuffer) - 1; 3 if((0x81 <= cBuffer[n] && cBuffer[n] <= 0x9f) || (0xe0 <= cBuffer[n] && cBuffer[n] <= 0xef)){ 4 cBuffer[n] = 0x00; 5 } 6 7 /*--------文字列の出力--------*/ 8 printf("入力した文字列は「%s」です。\n", cBuffer); /* 入力した文字列を出力 */

もしVisualStudioをお使いなら_ismbblead関数が使えると思うので、そちらを使ったほうが楽と思います。
https://msdn.microsoft.com/ja-jp/library/3hd1xf60.aspx

訂正
皆さんの回答より1バイト目のみ判定では不完全であることがわかりました。
私の中途半端な知識でご迷惑をおかけしました。
やはり先頭から順に見ていく必要があるということで、判定処理を考えてみました。

c

1 unsigned char *p = cBuffer; 2 int f = 0; 3 while(*p != 0x00) { 4 if(f == 2){ 5 f = 3; // 全角2バイト目 6 } else 7 if((0x81 <= *p && *p <= 0x9f) || (0xe0 <= *p && *p <= 0xef)){ 8 f = 2; // 全角1バイト目 9 } else { 10 f = 1; // 半角 11 } 12 p++; 13 } 14 if(f == 2){ 15 *(--p) = 0x00; 16 } 17 18 /*--------文字列の出力--------*/ 19 printf("入力した文字列は「%s」です。\n", cBuffer); /* 入力した文字列を出力 */

投稿2018/07/30 02:01

編集2018/07/31 04:40
ttyp03

総合スコア16998

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

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

Alyn

2018/07/30 02:36

とても親切に回答をいただきありがとうございました!
a_saitoh

2018/07/30 03:19

SHIFTJISは第2バイトが40-7Eならびに80-FCなので、あるバイトだけを見て1バイトめか2バイト目かを判断することができません。cBufferの先頭から順にみていく必要があると思いますよ。
Alyn

2018/07/30 05:48

第2バイトが0x81~0x9fまたは0xe0~0xefの文字ってありますか?
a_saitoh

2018/07/31 03:38

全角の「=」は0x8181ですね。
guest

0

ShiftJISなら、全角文字の1バイト目、というのが判定できるので、その1バイト目しかないデータを削除/表示しないようにすればいいです

投稿2018/07/30 01:37

y_waiwai

総合スコア87774

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

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

Alyn

2018/07/30 01:41

どのように判定するのですか?
y_waiwai

2018/07/30 01:42

「shiftjis 1バイト目」とかでぐぐると解説が出てきます
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問