🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

1回答

1987閲覧

ReadConsoleInput();関数でアクセスエラーが出る原因がわからない。

退会済みユーザー

退会済みユーザー

総合スコア0

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2020/12/10 14:51

**Input();関数部のコメント部ですがなぜアクセスエラーがでるのでしょうか?Handle変数の設定が悪いのかと思いCreateConsoleScreenBuffer()**関数を確認しましたがしっかり読み書きできる設定になっています。これはなぜでしょうか?

公式リファレンス: https://docs.microsoft.com/ja-jp/windows/console/readconsoleinput

cpp

1#include "stdio.h" 2#include "stdlib.h" 3#include <Windows.h> 4 5// ウインドウサイズ 6#define MAX_WIDTH ((int)100) 7#define MAX_HEIGHT ((int)40) 8 9 10void Input(HANDLE &hConsole) 11{ 12 //HANDLE hConsole = nullptr; 13 14 PINPUT_RECORD Buffer = 0; 15 DWORD Length = 100; 16 LPDWORD lpNumber = 0; 17 18///////////////////////////////////////////////////////////////////////////// 19 if (ReadConsoleInput(hConsole, Buffer, Length, lpNumber) == true) 20 { 21 printf("ああああ\n"); 22 } 23//////////////////////////////////////////////////////////////////////////// 24 25 26} 27 28 29 30 31int main() 32{ 33 HANDLE mhScreen; //ウインドウハンドル 34 COORD mDraw_start; //描画開始位置 35 COORD mDraw_size; //画面のサイズ 36 _SMALL_RECT mRect; //画面の描画範囲 37 int mNowBuffer_width = 0; 38 int mNowBuffer_height = 0; 39 40 41 42 mhScreen = nullptr; //ウインドウハンドル 43 44 //描画開始座標 45 mDraw_start.X = 0; 46 mDraw_start.Y = 0; 47 48 //描画範囲 49 mDraw_size.X = MAX_WIDTH; 50 mDraw_size.Y = MAX_HEIGHT; 51 52 //ウインドウサイズ 53 mRect.Left = (SHORT)0; 54 mRect.Top = (SHORT)0; 55 mRect.Right = (SHORT)MAX_WIDTH; 56 mRect.Bottom = (SHORT)MAX_HEIGHT; 57 58 int num = 0; 59 60 // バッファーを作成 61 mhScreen = CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, CONSOLE_TEXTMODE_BUFFER, NULL); 62 if (mhScreen == INVALID_HANDLE_VALUE) 63 { 64 fprintf(stderr, "INVALID_HANDLE_VALUE"); 65 } 66 67 68 SetConsoleScreenBufferSize(mhScreen, mDraw_size); // バッファサイズ変更 69 SetConsoleWindowInfo(mhScreen, TRUE, &mRect); // ウィンドウサイズ変更 70 SetConsoleActiveScreenBuffer(mhScreen); //有効化 71 72 73 CHAR_INFO mWindowBuffer[MAX_HEIGHT][MAX_WIDTH] = { 0 }; 74 75 76 mWindowBuffer[0][0].Char.UnicodeChar = L'A'; 77 mWindowBuffer[0][0].Attributes = FOREGROUND_GREEN; 78 79 mWindowBuffer[1][0].Char.UnicodeChar = L'B'; 80 mWindowBuffer[1][0].Attributes = FOREGROUND_GREEN; 81 82 83 while (true) 84 { 85 Input(mhScreen); 86 87 88 SetConsoleCursorPosition(mhScreen,mDraw_start); 89 WriteConsoleOutput(mhScreen, mWindowBuffer[0], mDraw_size, mDraw_start, &mRect); //現在のカーソル位置から始まる文字列をコンソール画面バッファーに書き込み 90 FlushConsoleInputBuffer(mhScreen); 91 92 } 93 94 95 96 97 98 // スクリーンバッファを解放 99 CloseHandle(mhScreen); 100 mhScreen = NULL; 101 102 103 104 105 106 107 return 0; 108} 109

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

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

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

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

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

guest

回答1

0

ベストアンサー

ReadConsoleInputの使い方が正しくないからです。第2引数に着目すると

cpp

1PINPUT_RECORD Buffer = 0; 2if (ReadConsoleInputW(hConsole, Buffer, Length, lpNumber))

となっていますが、必要なのはINPUT_RECORD Buffer型の領域へのポインタです。また第3引数は第2引数の領域の要素数です。適当に100を渡せばいいってもんじゃありません。というかCにおいて、配列の先頭要素へのポインタと、配列の要素数を関数の引数に渡すパターンは頻出しますから覚えてください。

同様にして第4引数もDWORD型変数へのポインタを要求しています。

適当にこの関数を使ってるまともそうなサンプルを見つけたので参照してください。
https://gist.github.com/yoggy/809224

ちなみにWindows 10 の WriteConsoleOutputWは幅が2セルの文字を出力しようとすると表示が壊れるバグがあります。半角スペースを詰めるワークアラウンドが知られています。
https://github.com/nsf/termbox-go/pull/213
https://twitter.com/mattn_jp/status/1162706834265821184?s=20

投稿2020/12/10 16:42

編集2020/12/10 17:16
yumetodo

総合スコア5852

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

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

yumetodo

2020/12/10 16:57

あとCreateConsoleScreenBufferの戻り値のチェックですが、fprintfするのはいいのですが、そのあとプログラムを終了するなりしてないので、無効なハンドルを使い続けてしまいます。
退会済みユーザー

退会済みユーザー

2020/12/11 04:23 編集

bool Input(HANDLE& hConsole) { //HANDLE hConsole = nullptr; printf("ええええ\n"); INPUT_RECORD Buffer; DWORD Length = 1; // DWORD Length = sizeof(INPUT_RECORD); DWORD n = 0; printf("%d\n",Length); LPDWORD lpNumber = nullptr; if (ReadConsoleInput(hConsole,&Buffer,1,&n) != 0) { fputs("あああ\n", fp); printf("いいいいいいいいいいいいいいいいいいいいいいいいいいいい\n"); return true; } else { printf("ええええええええええええええええええええええええええ: %d\n", GetLastError()); fprintf(fp,"いいいい: %d \n",GetLastError()); } return false; } としましたがGetLastError();関数で6という値が帰ってきて "ハンドルが無効です" というエラーが帰って来てしまします。これはどうしたらいいのでしょうか? https://docs.microsoft.com/en-us/windows/win32/debug/system-error-codes--0-499-
yumetodo

2020/12/11 06:37

CreateConsoleScreenBufferの戻り値のチェックの部分は直しましたか?
退会済みユーザー

退会済みユーザー

2020/12/11 06:46

はい、無限ループの一番上に配置して消す処理をループの一番下に入れました。また そうではなくHANDLE H = GetStdHandle(STD_INPUT_HANDLE);という感じでハンドルを指定するみたいです。しかしながらエラーが発生しておりました。「待機する子プロセスはありません。」と表示されます。
退会済みユーザー

退会済みユーザー

2020/12/11 06:49

INPUT_RECORD Buffer[128]; DWORD Length = 128; DWORD n = 0; DWORD lpNumber = 0; HANDLE H = GetStdHandle(STD_INPUT_HANDLE); if (ReadConsoleInput((void*)H,Buffer,Length,&lpNumber) != 0) { fputs("あああ\n", fp); printf("いいいいいいいいいいいいいいいいいいいいいいいいいいいい\n"); return true; } else { printf("ええええええええええええええええええええええええええ: %d\n", GetLastError()); fprintf(fp,"いいいい: %d \n",GetLastError()); } ようにすることで”解決できました。”ありがとうございました。
yumetodo

2020/12/12 16:13

> (void*)H そのキャスト、いる?
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問