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

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

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

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

Q&A

解決済

2回答

1173閲覧

C++配列の宣言と要素の格納について

Mt.Sheep5

総合スコア7

C++

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

0グッド

0クリップ

投稿2019/08/06 05:28

前提・実現したいこと

AtCoderというサイトの Typical Contest001の問題A"深さ優先探索"に取り組んでいるのですが、エラーメッセージを見る限り、bool型配列のreachedとchar型配列のcのどちらか、もしくは両方に要素を入れられていないようです。

変数のスコープに関して致命的なミスがあるのでしょうか。

発生している問題・エラーメッセージ

terminate called after throwing an instance of 'std::out_of_range' what(): vector::_M_range_check: __n (which is 0) >= this->size() (which is 0)

該当のソースコード

C++

1#include <bits/stdc++.h> 2using namespace std; 3 4int x,y,h, w; 5 6vector<vector<bool>>reached(w,vector<bool>(h,false)); 7vector<vector<char>> c (w,vector<char>(h)); 8void search(int a, int b, int h, int w){ 9 if(a<0 || w<=a || b<0 || h<=b || c.at(a).at(b)=='#' ) return; 10 if(reached.at(a).at(b)) return; 11 12 reached.at(a).at(b)=true; 13 14 search(a+1,b,h,w); 15 search(a-1,b,h,w); 16 search(a,b+1,h,w); 17 search(a,b-1,h,w); 18} 19 20int main() { 21 int sx, sy; 22 int gx,gy; 23 cin >> h >> w; 24 25 for(int i=0;i<w;i++){ 26 for(int j=0;j<h;j++){ 27 cin >> c.at(i).at(j); 28 cout << c.at(i).at(j); 29 } 30 } 31 32 for(int i=0;i<w;i++){ 33 for(int j=0;j<h;j++){ 34 if(c.at(i).at(j)=='s'){ 35 sx=i; 36 sy=j; 37 } 38 } 39 } 40 41 search(sx,sy,h,w); 42 43 for(int i=0;i<w;i++){ 44 for(int j=0;j<h;j++){ 45 if(c.at(i).at(j)=='g'){ 46 gx=i; 47 gy=j; 48 } 49 } 50 } 51 52 if(reached.at(gx).at(gy)) cout <<"Yes"<<endl; 53 else cout<<"No"<<endl; 54}

試したこと

配列cの宣言の場所をint main()下に移動し、void search()部分とint main()下のsearch(sx,sy,h,w);からelse cout<<"No"<<endl;までをコメントアウトしたところ、配列cについて入出力のエラーは発生しませんでした。
原因は何でしょうか。

補足情報(FW/ツールのバージョンなど)

ここにより詳細な情報を記載してください。

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

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

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

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

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

guest

回答2

0

ベストアンサー

実行順番を考えてください。main関数よりも先にstatic storage durationな変数の初期化が行われます。つまり

cpp

1int x,y,h, w;

(static storage durationでとくに初期化指定子がないので0初期化)

cpp

1vector<vector<bool>>reached(w,vector<bool>(h,false));

コンストラクタの呼び出し、要素数0

cpp

1vector<vector<char>> c (w,vector<char>(h));

コンストラクタの呼び出し、要素数0

そしてmain関数が呼ばれます。なので範囲外アクセスの例外が呼ぶわけですね。

reachedにしてもcにしてもすでにお試しの通り、main関数内で定義すればいいと思います。そして引数経由で関数searchにわたす。

cpp

1void search(std::vector<std::vector<bool>>& reached, const std::vector<std::vector<char>>& c,constint a, int b, int h, int w);

投稿2019/08/06 06:21

yumetodo

総合スコア5850

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

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

Mt.Sheep5

2019/08/07 00:43

コンストラクタであるcとreachedが呼び出されたことで、それ以前に呼び出されてcin >> h >> w;で入力されたhとwが初期化されたということでしょうか?vectorは変数の一種であり、関数であるコンストラクタではないと勘違いしていたのですが、その勘違いがこのエラーの原因だったようです。
SHOMI

2019/08/07 01:04 編集

>それ以前に呼び出されてcin >> h >> w;で入力されたhとwが初期化されたということでしょうか? main()が呼ばれる前なのでcin >> h >> w;はまだ実行されていませんよ。 >vectorは変数の一種であり、関数であるコンストラクタではないと勘違いしていたのです vectorはclassです。競技プログラミングに手を出す前にまずはC++の勉強をされるべきかと。
Mt.Sheep5

2019/08/07 01:31

c++の基礎の部分から勉強してみます。 ありがとうございました!
yumetodo

2019/08/07 02:39

何々の時に〇〇コンストラクタが呼出しされるが覚えられないので特訓 https://qiita.com/yz2cm/items/7f8bf45838b35d970ce2 C++入門者に贈るclass入門とclass/structキーワードの使い分け https://qiita.com/yumetodo/items/b0ff58617f2733d4ffa1 C++のメモリーの話とストレージの有効期間の話をしようか https://qiita.com/yumetodo/items/067b2db266ae0779f030 関数の創世から深淵まで駆け抜ける関数とはなんぞや講座 https://qiita.com/yumetodo/items/cdfb41781d32d98be1b4 あたりを見ていただけると理解が深まるかもしれません
Mt.Sheep5

2019/08/07 03:36

すごく助かります! ありがとうございます!
guest

0

エラーメッセージにも書かれてますが、reachedとcのサイズが0なので下記の部分で配列外参照をしているだけですね...

cpp

1if(reached.at(gx).at(gy)) cout <<"Yes"<<endl;

投稿2019/08/06 06:18

kamitani

総合スコア22

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問