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

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

詳細はこちら
C++

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

Q&A

解決済

2回答

2422閲覧

ReadConsoleInput()関数でGetLastError();関数による998エラーが出る原因が知りたい。

退会済みユーザー

退会済みユーザー

総合スコア0

C++

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

0グッド

1クリップ

投稿2020/12/18 09:26

編集2020/12/18 10:27

提示コードのReadConsoleInput()関数ですがGetLastError();関数により[998]が発生しましたそのエラーの解決方法がわかりません。
コンストラクタでハンドルを受け取りそれをキー入力の時に使っています。

エラー[998] : メモリ ロケーションへのアクセスが無効です。

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

cpp

1#include "stdio.h" 2#include "stdlib.h" 3#include <Windows.h> 4#include "stdio.h" 5#include "stdlib.h" 6 7 8#include "DrawCharactor.hpp" 9 10 11#include "KeyInput.hpp" 12 13// ウインドウサイズ 14#define MAX_WIDTH ((int)100) 15#define MAX_HEIGHT ((int)40) 16 17FILE* fp = NULL; 18 19 20int main() 21{ 22 fopen_s(&fp,"Mian_Log.txt","w"); 23 DrawCharactor* dc = new DrawCharactor(); 24 KeyInput* key = new KeyInput(dc->getHandle()); 25 26 27 28 int y = 0; 29 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 30 while (true) 31 { 32 if (key->getKeyDown(KeyCode::UP_KEY) == true) 33 { 34 y--; 35 fprintf(fp, "UP\n"); 36 37 } 38 else if (key->getKeyDown(KeyCode::DOWN_KEY) == true) 39 { 40 fprintf(fp,"Down\n"); 41 y++; 42 } 43 // fprintf(fp, "Down\n"); 44 45 46 for (int i = 0; i < 5; i++) 47 { 48 if (y == i) 49 { 50 dc->setDraw("-> "); 51 dc->setDraw_Line("AAAA"); 52 53 } 54 else 55 { 56 dc->setDraw_Line("AAAA"); 57 } 58 } 59 60 61 62 63 64 65 66 67 /// dc->setDraw_Line("Menu "); 68 // dc->setDraw_Line("test"); 69 70 71 72 73 74 dc->GenerateOutput(); 75 } 76 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 77 78 delete dc; 79 delete key; 80 81 82 fclose(fp); 83 84 85 86 return 0; 87}

cpp

1#include "KeyInput.hpp" 2 3KeyInput::KeyInput(HANDLE h) 4{ 5 handle = h; 6 7 Length = sizeof(INPUT_RECORD); 8 lpNumber = 0; 9 10 fopen_s(&fp,"KeyInput.txt","w"); 11 12 13} 14 15// キーが押された瞬間だけ 16bool KeyInput::getKeyDown(KeyCode key) { 17 18////////////////////////////////////////////////////////////////////////// 19 if (ReadConsoleInput(handle, Buffer, Length, &lpNumber) != 0) 20 { 21 fprintf(fp, "あああ\n"); 22///////////////////////////////////////////////////////////////////////// 23 if (Buffer->Event.KeyEvent.bKeyDown == true) { 24 if (Buffer->Event.KeyEvent.wVirtualKeyCode == (int)key && b == false) 25 { 26 b = true; 27 return true; 28 } 29 } 30 else 31 { 32 b = false; 33 return false; 34 } 35 36 } 37 else { 38 fprintf(fp, "ReadConsoleInput()が無効です。 %d\n",GetLastError()); 39 40 return false; 41 } 42 43 return false; 44} 45 46 47 48bool KeyInput::getKeyHoldDown() 49{ 50 return false; 51} 52 53 54KeyInput::~KeyInput() 55{ 56 fclose(fp); 57} 58

hpp

1#ifndef ___KEYINPUT_HPP_ 2#define ___KEYINPUT_HPP_ 3#include <iostream> 4#include "stdlib.h" 5#include "stdio.h" 6 7#include <Windows.h> 8 9 10 11class KeyInput 12{ 13public: 14 15 16 KeyInput(HANDLE h); //コンストラクタ 17 ~KeyInput(); //デストラクタ 18 19 bool getKeyDown(enum class KeyCode key); //キーが押された時 (瞬間だけ) 20 bool getKeyHoldDown(); //キーが押されてる間 21 22 23 24private: 25 26 bool b = false; 27 HANDLE handle; 28 INPUT_RECORD *Buffer = nullptr; 29 DWORD Length; 30 DWORD lpNumber; 31 32 FILE* fp = NULL; //デバッグログ 33 34}; 35 36 37// キーコード 38enum class KeyCode 39{ 40 41 A_KEY = 0x41, 42 B_KEY = 0x43, 43 C_KEY = 0x44, 44 D_KEY = 0x45, 45 E_KEY = 0x46, 46 F_KEY = 0x47, 47 G_KEY = 0x48, 48 H_KEY = 0x49, 49 I_KEY = 0x4A, 50 J_KEY = 0x4B, 51 K_KEY = 0x4C, 52 L_KEY = 0x4D, 53 M_KEY = 0x4E, 54 N_KEY = 0x4F, 55 O_KEY = 0x50, 56 P_KEY = 0x51, 57 Q_KEY = 0x52, 58 R_KEY = 0x53, 59 S_KEY = 0x54, 60 T_KEY = 0x55, 61 U_KEY = 0x56, 62 V_KEY = 0x57, 63 W_KEY = 0x58, 64 X_KEY = 0x59, 65 Y_KEY = 0x5A, 66 Z_KEY = 0x5A, 67 68 LEFT_KEY = 0x25, //左矢印キー 69 UP_KEY = 0x26, //上矢印キー 70 RIGHT_KEY = 0x27, //右矢印キー 71 DOWN_KEY = 0x28, //下矢印キー 72 SPACE_KEY = 0x20, //スペースキー 73 74 75}; 76#endif

cpp

1#include "DrawCharactor.hpp" 2 3// コンストラクタ 4DrawCharactor::DrawCharactor() 5{ 6 fopen_s(&fp,"Log.txt","w"); //ファイル 7 8 9 //描画開始座標 10 mDraw_start.X = 0; 11 mDraw_start.Y = 0; 12 13 //描画範囲 14 mDraw_size.X = MAX_WIDTH; 15 mDraw_size.Y = MAX_HEIGHT; 16 17 //ウインドウサイズ 18 mRect.Left = (SHORT)0; 19 mRect.Top = (SHORT)0; 20 mRect.Right = (SHORT)MAX_WIDTH; 21 mRect.Bottom = (SHORT)MAX_HEIGHT; 22 23 // バッファーを作成 24 mHandle = CreateConsoleScreenBuffer(GENERIC_WRITE | GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CONSOLE_TEXTMODE_BUFFER, NULL); 25 26 SetConsoleActiveScreenBuffer(mHandle); //有効にする 27 28 if (mHandle == INVALID_HANDLE_VALUE) 29 { 30 fprintf(fp, "Invalid: INVALID_HANDLE_VALUE \n"); 31 } 32 33 // 画面バッファサイス変更 34 if (SetConsoleScreenBufferSize(mHandle, mDraw_size) == 0) 35 { 36 fprintf(fp,"Invalid: SetConsoleScreenBufferSize(); \n"); 37 } 38 39 // 画面サイズ変更 40 if (SetConsoleWindowInfo(mHandle, TRUE, &mRect) != 0) 41 { 42 fprintf(fp, "Invalid: SetConsoleWindowInfo(); \n"); 43 } 44 45} 46 47// バッファーに文字を書き込む 48void DrawCharactor::setDraw(const char* format, ...) 49{ 50 51 va_list ap; 52 char str[MAX_WIDTH]; 53 va_start(ap, format); 54 vsprintf_s(str, sizeof(str), format, ap); 55 va_end(ap); 56 57 wchar_t wc[MAX_WIDTH]; 58 size_t size = sizeof(wc); 59 60 size_t count = sizeof(wc) / sizeof(wchar_t); 61 mbstowcs_s(&size, wc, count, str, count - 1); //マルチ文字をワイド文字に変換 62 63 // ----------------------------------------------------------------------------------------------- 64 int i = 0; 65 for (; mNowBuffer_width[mNowBuffer_height] <= MAX_WIDTH; mNowBuffer_width[mNowBuffer_height]++) { 66 67 if (wc[i] != L'\0') { 68 69 if (mNowBuffer_width[mNowBuffer_height] <= MAX_WIDTH) { 70 mScreenBuffer[mNowBuffer_height][mNowBuffer_width[mNowBuffer_height]].Char.UnicodeChar = wc[i]; 71 mScreenBuffer[mNowBuffer_height][mNowBuffer_width[mNowBuffer_height]].Attributes = FOREGROUND_GREEN; 72 // mNowBuffer_width[mNowBuffer_height]++; 73 74 } 75 else 76 { 77 fprintf(fp,"setDraw() 一行の文字数を超えています。\n"); 78 } 79 i++; 80 } 81 else { 82 break; 83 } 84 } 85 86 // ----------------------------------------------------------------------------------------------- 87 //fprintf(fp, "ああああ\n"); 88} 89 90 91 92 93// バッファーに文字を書き込む 94void DrawCharactor::setDraw_Line(const char* format, ...) 95{ 96 97 va_list ap; 98 char str[MAX_WIDTH]; 99 va_start(ap, format); 100 vsprintf_s(str, sizeof(str), format, ap); 101 va_end(ap); 102 103 wchar_t wc[MAX_WIDTH]; 104 size_t size = sizeof(wc); 105 106 size_t count = sizeof(wc) / sizeof(wchar_t); 107 mbstowcs_s(&size, wc, count, str, count - 1); //マルチ文字をワイド文字に変換 108 109 // ----------------------------------------------------------------------------------------------- 110 int i = 0; 111 for (; mNowBuffer_width[mNowBuffer_height] <= MAX_WIDTH; mNowBuffer_width[mNowBuffer_height]++) { 112 113 if (wc[i] != L'\0') { 114 115 if (mNowBuffer_width[mNowBuffer_height] <= MAX_WIDTH) { 116 mScreenBuffer[mNowBuffer_height][mNowBuffer_width[mNowBuffer_height]].Char.UnicodeChar = wc[i]; 117 mScreenBuffer[mNowBuffer_height][mNowBuffer_width[mNowBuffer_height]].Attributes = FOREGROUND_GREEN; 118 //mNowBuffer_width[mNowBuffer_height]++; 119 120 } 121 else 122 { 123 fprintf(fp, "setDraw_Line() 一行の文字数を超えています。\n"); 124 } 125 i++; 126 } 127 else { 128 break; 129 } 130 } 131 132 mNowBuffer_height++; 133 134 135 // ----------------------------------------------------------------------------------------------- 136 //fprintf(fp, "ああああ\n"); 137} 138 139// 描画 140void DrawCharactor::GenerateOutput() 141{ 142 WriteConsoleOutput(mHandle,mScreenBuffer[0], mDraw_size, mDraw_start, &mRect); //現在のカーソル位置から始まる文字列をコンソール画面バッファーに書き込み 143 mNowBuffer_height = 0; 144 145 for (int i = 0; i < MAX_HEIGHT; i++) 146 { 147 mNowBuffer_width[i] = 0; 148 } 149 150} 151 152// ハンドルを返す 153HANDLE DrawCharactor::getHandle() 154{ 155 return mHandle; 156} 157 158 159// デストラクタ 160DrawCharactor::~DrawCharactor() 161{ 162 // スクリーンバッファを解放 163 CloseHandle(mHandle); 164 mHandle = NULL; 165 166 fclose(fp); 167 168}

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

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

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

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

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

SHOMI

2020/12/18 10:07

mainがないのでビルドして動作確認ができません。 コンストラクタでどんな値を渡したのかも不明ですし、動くコードをはっていただけますか。
退会済みユーザー

退会済みユーザー

2020/12/18 10:16

mainのソースコードを添付しました。
SHOMI

2020/12/18 10:25

DrawCharactorって何者ですか… dc->getHandle()で何が返っているのか不明ですが。 DrawCharactor* dc = new DrawCharactor(); KeyInput* key = new KeyInput(dc->getHandle());
退会済みユーザー

退会済みユーザー

2020/12/18 10:27

文字数の関係で定義コードは載せられましたが宣言のヘッダーファイルを載せられませんでした。
SHOMI

2020/12/18 10:36

コードを全部貼るのではなく、コンパイルが通り再現できる最小限のコードで良いのですが…
guest

回答2

0

ベストアンサー

Buffernullptrのままどこでも確保していないようです。


INPUT_RECORD Buffer;としまた。そしたらエラー番号6番[ハンドルが無効です]と表示されるのですがどうすればいいのでしょうか?

ReadConsoleInputの第3引数は第2引数の要素数なのでLengthsizeof(INPUT_RECORD)ではなく1では?

Length = sizeof(INPUT_RECORD);

以下のように修正し

diff

1- if (ReadConsoleInput(handle, Buffer, Length, &lpNumber) != 0) 2+ INPUT_RECORD Buffer; 3+ if (ReadConsoleInput(handle, &Buffer, 1, &lpNumber) != 0) 4 { 5 fprintf(fp, "あああ\n"); 6 ///////////////////////////////////////////////////////////////////////// 7- if (Buffer->Event.KeyEvent.bKeyDown == true) { 8+ if (Buffer.Event.KeyEvent.bKeyDown == true) { 9- if (Buffer->Event.KeyEvent.wVirtualKeyCode == (int)key && b == false) 10+ if (Buffer.Event.KeyEvent.wVirtualKeyCode == (int)key && b == false)

以下のコードで上矢印キーを押下した場合に"UP"が表示されることを確認しました。

C++

1int main() 2{ 3 KeyInput key(GetStdHandle(STD_INPUT_HANDLE)); 4 5 while (true) 6 { 7 if (key.getKeyDown(KeyCode::UP_KEY)) 8 { 9 printf("UP\n"); 10 } 11 } 12 return 0; 13}

getKeyDown()を二回呼んでいますが、ReadConsoleInput()も2回呼ばれるので取りこぼしてしまうのでは?
ReadConsoleInput()で読み取った値を覚えておきKeyCode::UP_KEYKeyCode::UP_KEYか判定すべきでは?

C++

1 if (key->getKeyDown(KeyCode::UP_KEY) == true) 2() 3 else if (key->getKeyDown(KeyCode::DOWN_KEY) == true)

投稿2020/12/18 09:39

編集2020/12/18 10:42
SHOMI

総合スコア4079

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

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

退会済みユーザー

退会済みユーザー

2020/12/18 09:44 編集

はい。INPUT_RECORD Buffer;としまた。そしたらエラー番号6番[ハンドルが無効です]と表示されるのですがどうすればいいのでしょうか?
SHOMI

2020/12/18 09:48

バッファはLength個必要ですが Length = sizeof(INPUT_RECORD); なぜsizeof?1個なら1では?
退会済みユーザー

退会済みユーザー

2020/12/18 10:01

なるほど。1としましたが同じくハンドルが無効ですというエラーコード6が表示されています。
SHOMI

2020/12/18 10:07 編集

mainがないのでビルドして動作確認ができません。 コンストラクタでどんな値を渡したのかも不明ですし、動くコードをはっていただけますか。
guest

0

Bufferはnullptrのままでしょうか。
そうであれば、それが原因と考えられます。

ReadConsoleInput(handle, Buffer, Length, &lpNumber) != 0

投稿2020/12/18 09:38

akiruno-oneone

総合スコア815

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

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

退会済みユーザー

退会済みユーザー

2020/12/18 09:49 編集

誤文です
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問