プロが教える店舗&オフィスのセキュリティ対策術

『scanfを使わずに_getch()でキーボードからファイル名を入力していき、入力した文字をprintfで表示する流れについて質問です。
表示された文字をバックスペースで消していっても打ち込んだ文字は消えないですよね?
間違ったファイル名を入力してしまった際に文字が残っているので、正しく入力し直しても間違ったファイル名となってします。
一度打った文字を消す方法はありますでしょうか?


以前このような質問をさせていただき、_getch()で得た文字のキーボード上での削除の仕方は分かりました。
今度はそのやり方をプログラムで作るとしたら、どう組んでいけば良いのか教えて頂けないでしょうか。
できればそのプログラムを教えて頂けたら嬉しいです。

今現在書いてるプログラムのgetchを使っている部分です。
ファイルがオープンできたら別の処理に移行しますが、その関数は長くなるので省略しています。

#include <stdio.h>
#include <conio.h>

int main() {

int key;
int i;
char file_name[256] = { 0 };
FILE *fp;
errno_t e;

while(1)
{
i = 0;
// エンタキーが押されるまで入力を続ける
do
{
printf("%c", key);
file_name[i] = key;
key = _getch();
i++;
} while(key != 0x0d);

printf("\n");

if(e = fopen_s(&fp, file_name, "rb") != 0) {
printf("ファイルが存在しません\n");
return 0;
}
else {
// 成功したらプログラムの処理をする関数に移行
return 1;
}
}
}

A 回答 (3件)

getch() で 取得したキーコードがBSだったら、iを減算すれば良いかと思います。



(そうなると、DELキーだったら、とか、そもそもファイル名に使えないコードだったら、なども心配になりますが、それは、いずれにしてもkey の値で、case文などを使うと良いかと思います。)

◆元のプログラムの部分:
  printf("%c", key);
  file_name[i] = key;
  key = _getch();
  i++;

◆改造案 (案なので、概念的に記述してあります。


key = _getch();   ← do whileの最初に持って来ないとまずいと思います。

switch( key ) {
    case : ファイル名に使えるコード
        printf("%c", key);
        file_name[i++] = key;
        break;
    case : バックスペースキー
        if ( i > 0 ) i--;        iは0以上でないといけません。
        break;
    default:    それ以外はなにもしない。
        break;



こんな考え方でいかがでしょうか?

ご参考に。
    • good
    • 0
この回答へのお礼

こちらの考え方を参考にプログラムを組んでみたところ、こちらの方法でもちゃんと文字を消せるようにできました。
case文の"ファイル名に使えるコード"の定数部分をどうしようか若干悩みましたが、なんとか組み込めました。

ずっとif文で分岐させることしか考えてなかったんですが、switch文で組んでみると中々スッキリした記述になりますね。

ご回答ありがとうございました。

お礼日時:2012/06/14 17:54

http://oshiete.goo.ne.jp/qa/7508673.html
の続きですかね。
閉じずに向こうで続けるべきでしたけど。

>_getch()で得た文字のキーボード上での削除の仕方

が、何を意味しているのか不明…ですが……
画面の表示ですか????

>do
>{
> printf("%c", key);
> file_name[i] = key;
> key = _getch();
> i++;
>} while(key != 0x0d);

file_nameの1文字目が不定な文字が入るのは許容という仕様でいいのでしょうか?
最初に
> file_name[i] = key;
が実行される時のkeyには何が入っていますかね?
いきなりEnter押された場合にも問題になりそうですが……

バックスペースが入力されたら
file_name[i--] = '\0';
で1文字戻すのと消去を行えばよいでしょう。
ただし、iが0の時に上記の処理を行うと高確率で吹っ飛ぶのでその辺りのエラー処理は必要ですが。
# 入力位置は移動できないのですからDeleteキーの対応は不要…ですよね?
    • good
    • 0
この回答へのお礼

すみません、最初はあの方法で消せるならいいと思っていたんですが、やはりバックスペースを一回押すだけで消せるようにした方がスマートだなと思いまして。

>が、何を意味しているのか不明…ですが……
>画面の表示ですか????

これは、"BS,スペース,BS"で消せるのは分かりましたが、バックスペースを一回押すだけで消せるプログラムを作りたいという意味で書きました。
言葉が足りず申し訳ありませんでした。

>file_nameの1文字目が不定な文字が入るのは許容という仕様でいいのでしょうか?

投稿時に記述したプログラムは、元のプログラムから必要最低限の部分だけを抜粋して書き直していたので、最初にgetch()を使っているプログラム部分は含んでいませんでした。
なので別の部分に一文字目を入力する処理はあります。

>file_name[i--] = '\0';

この'\0'を入れてi--するという文法を思いつかなかったので大変参考になります。

># 入力位置は移動できないのですからDeleteキーの対応は不要…ですよね?

はい、今回はバックスペースだけ使えればいいのでDeleteキーは不要です。

ご回答ありがとうございました。

お礼日時:2012/06/14 17:53

#include <stdio.h>


#include <conio.h>

int main() {

int key;
int i;
char file_name[256] = { 0 };
FILE *fp;
errno_t e;

while(1)
{
i = 0;
// エンタキーが押されるまで入力を続ける
do
{
key = _getch();
if (key == '\b') { //このif文と次の行のif文を1行にまとめて
if (i) { //if ((key == '\b') && (i)) {にするとバグるので注意
printf("\b \b");
i--;
}
} else if (key != '\r') {
printf("%c", key);
file_name[i] = key;
i++;
}
file_name[i] = '\0';
} while(key != '\r');

printf("\n");

if(e = fopen_s(&fp, file_name, "rb") != 0) {
printf("ファイルが存在しません\n");
return 0;
}
else {
// 成功したらプログラムの処理をする関数に移行
return 1;
}
}
}
    • good
    • 0
この回答へのお礼

記述してくださったプログラムを自分のソースに組み込んでみたところ、文字が消せるようになっていました!
>//このif文と次の行のif文を1行にまとめて
>//if ((key == '\b') && (i)) {にするとバグるので注意
ここをまとめてみて実行してみましたが、最初の入力時に打ち間違えた時確かにバグが発生しますね。
多分、自分で組んでいたら分割した方がいいとすぐには思いつかなかったと思います。
本当にご回答ありがとうございました。

お礼日時:2012/06/14 17:48

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!