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

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

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

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

Q&A

解決済

3回答

4220閲覧

C言語 _getch()で2バイト文字(平仮名・片仮名・漢字)を対応させる方法

Alyn

総合スコア50

C

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

0グッド

0クリップ

投稿2018/07/24 06:16

編集2018/07/30 01:39

前提・実現したいこと

_getch()を使用してシフトJISの1~2バイト文字を入力するプログラムを作りたい。
1バイト文字ならソースコードができていますが、2バイト文字にはどう対応していいのかわかりません。

該当のソースコード

C

1#include <stdio.h> 2#include <conio.h> 3 4void main() 5{ 6 /*--------変数・配列の宣言--------*/ 7 int iCount = 0; /* 入力した文字数を数える変数 */ 8 int iFlg = 0; /* 不正入力の有無のフラグ(1が不正入力) */ 9 char cInput = 0; /* 入力した文字を代入される変数 */ 10 char cBuffer[200] = {'\0'}; /* 入力した文字を出力するための配列 */ 11 12 printf("1_文字列を入力し、その文字列をそのまま出力します。\n"); 13 printf(" Enterで入力完了及びBackSpaceで一文字消去\n"); 14 15 printf("文字列を入力:"); 16 17 /*--------文字列の入力--------*/ 18 while(cInput != 0x0d) /* ループ条件:cInputがEnterでない間 */ 19 { 20 /*--------1文字ずつ入力--------*/ 21 while(1) /* 無限ループ */ 22 { 23 cInput = _getch(); /* 入力した文字をcInputに代入 */ 24 if(iCount != 0 || cInput != 0x08) /* 条件:iCountが0でないまたはcInputがBackSpaceでない時 */ 25 { 26 printf("%c", cInput); /* cInputを出力 */ 27 iCount++; /* 文字数をカウント */ 28 break; /* ループを抜ける */ 29 } 30 } 31 /*--------入力した文字の判定--------*/ 32 if( (cInput < 0x08) || ( (0x08 < cInput)&&(cInput < 0x0d) ) /* 条件:cInputがEnter,BackSpaceでない時 */ 33 || ( (0x0d < cInput)&&(cInput < 0x20) ) || (cInput == 0x7f) ) /* 条件:cInputが0x20~0x7eでない時 */ 34 { 35 printf("\n不正入力です。"); /* 不正入力を通知 */ 36 iFlg = 1; /* iFlgに1を代入 */ 37 break; /* ループを抜ける */ 38 } 39 else if(cInput == 0x08) /* 条件:cInputがBackSpaceの時 */ 40 { 41 printf(" %c", cInput); /* 一文字消去 */ 42 iCount = iCount - 2; /* iCountを-2する */ 43 } 44 else if(iCount == 1 && cInput == 0x0d) /* 条件:iCountが1で、かつcInputがEnterの時 */ 45 { 46 printf("\n不正入力です。"); /* 不正入力を通知 */ 47 iFlg = 1; /* iFlgに1を代入 */ 48 break; /* ループを抜ける */ 49 } 50 else if(cInput != 0x0d && iCount > 10) /* 条件:cInputがEnterでない、かつ入力した文字数が10文字を超えた時 */ 51 { 52 printf("\n不正入力です。"); /* 不正入力を通知 */ 53 iFlg = 1; /* iFlgに1を代入 */ 54 break; /* ループを抜ける */ 55 } 56 /*--------文字を配列に格納--------*/ 57 if(cInput != 0x08 && cInput != 0x0d) /* 条件:cInputがEnter,BackSpaceでない時 */ 58 { 59 cBuffer[iCount - 1] = cInput; /* Buffer[iCount - 1]にcInputを格納 */ 60 } 61 else if(cInput == 0x0d) /* 条件:cInputがEnterの時 */ 62 { 63 cBuffer[iCount - 1] = '\0'; /* Buffer[iCount - 1]にNUL文字を格納 */ 64 } 65 66 } 67 putchar('\n'); /* 改行 */ 68 /*--------文字列の出力--------*/ 69 if(iFlg == 0) /* 条件:iFlgが0の時 */ 70 { 71 printf("入力した文字列は「%s」です。\n", cBuffer); /* 入力した文字列を出力 */ 72 73 } 74}

追記

fgetsやgets_sでは文字以外の不正入力通知やオーバーフローの阻止ができるのでしょうか?

追記2

_getch()ではできないみたいなので、新しく別の質問を設置しました。ありがとうございました。

「C言語 fgetsで半分に切れてしまった2バイト文字を判定し、出力させないようにする方法」
https://teratail.com/questions/138562

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

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

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

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

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

guest

回答3

0

まずもって認識するべきなのは、_getchは文字入力を受けるものというよりはいっそキーボード入力を受けるものということです。そもそも2byte文字という考え方自体ももはや化石級で投げ捨てるべきで、すべての文字は可変長であると考えるべきです。例えばUnicodeでは4つの「文字」の定義があります。結合文字列まで考えだしたら2byteどころか4byteでも足りません。固定長にしようとするすべての試みはすべて完全に挫折しています。

文字入力に対してはオーバーフローの通知やEOFの管理やその他エラーを確実に補足できるfgets/gets_sに、これらがNULLを返したときに理由を判別するfeofferror関数を組み合わせて使用します。

数値入力の例ですがfgetsを利用しているので参考までに
C言語で安全に標準入力から数値を取得 - Qiita

投稿2018/07/24 18:32

yumetodo

総合スコア5850

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

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

0

fgetsやgets_sでは文字以外の不正入力通知やオーバーフローの阻止ができるのでしょうか?

オーバーフローの阻止はできますね。不正入力は、中身を見て行うしかないですね。ただ、getch()だと、一文字(1byte)毎の入力なので、2bye文字の判別は自分でしなくてはならないし、Backspaceとかも自分で行う必要があります。結構、面倒だと思います。(もともと、Ascii 1bye文字前提)
getch()も、1byte系のみならば、それなりに重宝した(過去形)が、日本語とか、扱いだした途端に破綻。(真面目にハンドルするのが大変と言う意味)
ゲームとかで、キー入力が欲しいとき以外は使うべきでないと思います。

一度、getch()で入力した文字を 16進表記で、出力してみると良いかもしれません。その時は、キーボードの全てのキーを(shift, ctrlとか組み合わせて)押してみる事をお勧めします。

投稿2018/07/24 13:29

pepperleaf

総合スコア6383

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

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

0

ベストアンサー

2バイト文字とはShiftJISのことでしょうか。
それなら、ShiftJISの1バイト目かどうかを判定できるので、それが来たら続けて2バイト目を読めばいいです

って、そもそも、なぜgetchで読む必要があるのか疑問ですが


fgetsだと、オーバーフローはしなくなりますねー

まあ、_getchで実装してもいいと思いますが。一度やってみるのもいいかと。

投稿2018/07/24 06:20

編集2018/07/24 12:50
y_waiwai

総合スコア87774

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

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

Alyn

2018/07/24 12:38 編集

Sift JISです。 scanfだとオーバーフローしてしまうからです。
y_waiwai

2018/07/24 06:29

fgets使いましょうよ
yumetodo

2018/07/24 07:03

もしくはC11で追加されたgets_s
Alyn

2018/07/24 10:07

ファイルを扱うのですか?
y_waiwai

2018/07/24 11:07

ファイルポインタのところは、stdin と書いておけば標準入力になります
Alyn

2018/07/24 12:20

ちなみに_getch()では作れないのですか?
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問