csvファイルを入力する

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
DOG
記事: 27
登録日時: 5年前

csvファイルを入力する

#1

投稿記事 by DOG » 5年前

連続で質問をしてしまい、申し訳ありません。
csvファイルの数値をvectorの2次元配列に格納するプログラム書いているのですが、なかなかうまくいきません。
とりあえず、カンマ","も含めてvectorの2次元配列に格納しようとしているのですが、
Debug Assertion Failed!
Expression: vector subscript out of range
といったエラーが出ます。以下に、コードを載せます。
visual studio Express 2013を使っています。
vectorの確保領域以上の所にアクセスしているという旨のエラーらしいのですが、vectorってメモリを動的確保できるものではないのですか?
ちなみに、20行目のコメント部分を解除しても同様のエラーが出てしまいます。
原因はいったい何なのでしょうか?

コード:

#include <iostream>
#include <fstream>
#include <string>
#include <vector>

using namespace std;

int main(int argc, char **argv){

	int i = 0;
	string str;
	vector<vector<string>> vss;
	ifstream fin;
	fin.open("sample.csv");

	if (!fin){
		cout << "入力ファイルをオープンできませんでした\n";
		return 1;
	}
	//vss.resize(100);
	while (true){
		getline(fin, str);
		vss[i].push_back(str);
		++i;
		if (fin.eof()){
			break;
		}
	}

	for (int k = 0; k < (int)vss.size(); k++){
		for (int j = 0; j < (int)vss[j].size(); j++){
			cout << vss[k][j] << endl;
		}
	}

	return 0;
}

Kaien
記事: 6
登録日時: 5年前
住所: 東京

Re: csvファイルを入力する

#2

投稿記事 by Kaien » 5年前

こんばんは。
DOG さんが書きました: vectorの確保領域以上の所にアクセスしているという旨のエラー
その通りです。それが起こりそうな所をみるしかないですね。
DOG さんが書きました: ちなみに、20行目のコメント部分を解除しても同様のエラーが出てしまいます。
解除しても、別の所で領域外をアクセスしているので、同様のエラーが出ています。
20行目の文は必要ですので、コメントは外してください。


因みに原因はfor文の方にあります。
1箇所だけ不自然な所があると思います。
よく見てみてください。

DOG
記事: 27
登録日時: 5年前

Re: csvファイルを入力する

#3

投稿記事 by DOG » 5年前

Kaienさんご返信ありがとうございます。
csvファイルの中身は、
2,3,4
6,4,1,9,0,5
7,2,5,6
となっています。
ちなみになのですが、
getline(fin, str);
でデータを格納したstrを表示させると、
2,3,4,,,
6,4,1,9,0,5
7,2,5,6,,
となりますので、
vss.size() は 3
vss[j].size() はそれぞれ 8, 11, 9
となるはずです。
う~ん、正直for文のどこが原因なのかがさっぱり分かりません・・・
この部分は正しいと思っていたもので・・・

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: csvファイルを入力する

#4

投稿記事 by softya(ソフト屋) » 5年前

デバッガでステップ実行で動作を確認されていますか? していれば気付けると思います。

> う~ん、正直for文のどこが原因なのかがさっぱり分かりません・・・
そういう思い込みを排除するためにもデバッガは有用です。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アバター
usao
記事: 1565
登録日時: 6年前

Re: csvファイルを入力する

#5

投稿記事 by usao » 5年前

オフトピック
今回のみたいに数行しかないような箇所であれば,
 今のコードとは別にもう一度書いてみる(当たり前だと思ってることは当たり前に書かれる)
 →今のコードとdiffをとってみる(当たり前だと思ってた箇所が間違っていたのが発覚)
という手段も有効.

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: csvファイルを入力する

#6

投稿記事 by softya(ソフト屋) » 5年前

オフトピック
プログラミングというかデバッグの基本ですが自分を信用してはいけません。
信頼できない人(=自分)の書いたプログラムを検証するのはどうするのか、そこを考えてみてください。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

N.R

Re: csvファイルを入力する

#7

投稿記事 by N.R » 5年前

そうですね
そういう時はソースコードを見やすく書き直してみるのも方法です。

forの中に .size() を直接書いていますが
いったん int の変数に代入してから使用してみるとか

そうする事でデバッガで変数の値も確認しやすくなります

ISLe
記事: 2645
登録日時: 9年前
連絡を取る:

Re: csvファイルを入力する

#8

投稿記事 by ISLe » 5年前

そもそも23行目で空のvectorに添字参照しようという考え方がおかしいと思います。
resizeしても確保分超えたら同じことなので問題を先送りしてるだけですよね。


質問とは関係ないですが、EOFをチェックする位置もおかしいです。


#近ごろ回答者側に確認不足が顕著な気がします。

N.R

Re: csvファイルを入力する

#9

投稿記事 by N.R » 5年前

>resizeしても確保分超えたら同じことなので問題を先送りしてるだけですよね
まずKaienさんの指摘する問題を直さないと先に進むべきではないと思います

>vectorってメモリを動的確保できるものではないのですか
と議題者は書いているのでresizeしたくないであろう事は分かっています

しかし今 resize した事によって別の間違いが浮き彫りになっている状態です
だからKaienさんはまずそれを指摘しているのだと思います
私もパッと見分からなかったので、「これは確かに議題者自身に気が付いてほしい」と思ったので同じようにヒントのみにしました
議題者自身きっとよい勉強になると思います

実際軽く動的確保に直してみるとエラーもなく通ってしまいました。
次に問題として現れるときはもっと分かりにくくなっているかもしれません

少なくとも私の周りではそういうのを問題の先送りと呼んでいます

Kaien
記事: 6
登録日時: 5年前
住所: 東京

Re: csvファイルを入力する

#10

投稿記事 by Kaien » 5年前

私の言葉不足が露呈してますね。

N.R様の言うように、まずresizeありだと別の問題が出てしまいますが、まずその間違いを直した方がいいと思いましたので、resizeのコメントを外すように書きました。

実はこの質問、約1年前に初めてSTLを触った頃の自分が陥ったミスと全く同じものでして、DOG様本人が気づいて欲しい点だと思いましたので、ヒントという形にしました。
DOG さんが書きました: う~ん、正直for文のどこが原因なのかがさっぱり分かりません・・・
この部分は正しいと思っていたもので・・・
そういう訳ですので、DOG様、頑張って見つけてください。

しかしながら、それでもresizeをする事で発生する別の問題のについては、言及すべきだったかもしれません。その件について、言葉足らずで申し訳ありませんでした。

最後に、ISLe様のおっしゃるEOFのチェック場所は素で見落としていました。
確認不足でした事、深く反省しております。

DOG
記事: 27
登録日時: 5年前

Re: csvファイルを入力する

#11

投稿記事 by DOG » 5年前

皆様、ご返信ありがとうございます。
プログラミングの勉強を始めてまだ数か月しかたっていないので、醜いコードになっているとは思いますが、どうかご容赦くださいませ。
さて、for文中の原因ですが、31行目のfor文の条件式の中の
j < (int)vss[j].size()
がおかしいことに気づきました。正しくは、
j < (int)vss[k].size()
だと思いました。
それで、20行目のコメント解除すると、正しく実行されました。

そこで、N.Rさんが仰っている
>>しかし今 resize した事によって別の間違いが浮き彫りになっている状態です
ですが、resize()で前もって確保しておかないと同じエラーが出ます。
vectorの良いところは領域の動的確保なのに、これだとvectorの良いところが消えてしまっているように思えます。
C++の入門書でvectorの2次元配列を扱っている箇所があるのですが、そこでも前もってresize()で領域確保されています。
vectorの2次元配列の場合は前もって確保しなければならないのでしょうか?

DOG
記事: 27
登録日時: 5年前

Re: csvファイルを入力する

#12

投稿記事 by DOG » 5年前

連投すみません。EOFの位置についてコメントさせて下さい。
正しくは、

コード:

while (true){
        if (fin.eof()){
            break;
        }
        getline(fin, str);
        vss[i].push_back(str);
        ++i;
    }
で、よろしいでしょうか?
よろしくお願い致します。

かずま

Re: csvファイルを入力する

#13

投稿記事 by かずま » 5年前

DOG さんが書きました: csvファイルの数値をvectorの2次元配列に格納するプログラム書いているのですが、なかなかうまくいきません。
とりあえず、カンマ","も含めてvectorの2次元配列に格納しようとしているのですが、
"," を含めなくてよいのなら、

コード:

#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>
 
int main(void)
{
    using namespace std;

    ifstream ifs("sample.csv");
    if (!ifs) return 1;

    vector< vector<string> > vvs;

    string line, word;
    for (size_t i = 0; getline(ifs, line); i++) {
        istringstream iss(line);
        vvs.push_back(vector<string>());
        while (getline(iss, word, ','))
            vvs[i].push_back(word);
    }
    for (size_t i = 0; i < vvs.size(); i++) {
        for (size_t j = 0; j < vvs[i].size(); j++)
            cout << " [" << vvs[i][j] << "]";
        cout << endl;
    }
    return 0;
}
sample.csv

コード:

2,3,4
6,4,1,9,0,5
7,2,5,6
実行結果

コード:

 [2] [3] [4]
 [6] [4] [1] [9] [0] [5]
 [7] [2] [5] [6]
 
それとも、次のようにしたいのですか?

コード:

 [2,] [3,] [4]
 [6,] [4,] [1,] [9,] [0,] [5]
 [7,] [2,] [5,] [6]
 

ISLe
記事: 2645
登録日時: 9年前
連絡を取る:

Re: csvファイルを入力する

#14

投稿記事 by ISLe » 5年前

質問者さんは気付いたようですが、resizeしたまま添字を直して動いたから『解決』というストーリーもあり得たと思います。

あとステップ実行すれば分かると思いますが、kのカウンタがresizeした分回るのはとても無駄だと思います。
取得したデータを加工する処理を加える際、空回りするループが邪魔になるかもしれません。

アバター
usao
記事: 1565
登録日時: 6年前

Re: csvファイルを入力する

#15

投稿記事 by usao » 5年前

DOG さんが書きました:連投すみません。EOFの位置についてコメントさせて下さい。
正しくは、

コード:

while (true){
        if (fin.eof()){
            break;
        }
        getline(fin, str);
        vss[i].push_back(str);
        ++i;
    }
で、よろしいでしょうか?
よろしくお願い致します。
最初のコードと特に動作に差が生まれないように思います.
(eof()が,ループの初回でtrueを返すことはないから)

例えば空のファイルだった場合に,どのように動くかなどを調べてみるとよいかと思います.
(eof()を使わない方法は既に示されていますが,この問いに関して誰も答えていないようなので…)

N.R

Re: csvファイルを入力する

#16

投稿記事 by N.R » 5年前

>#近ごろ回答者側に確認不足が顕著な気がします。
これは正しいですね
確認がきちんとできる人は後から後からコメントを書き換えたりしないでしょう

ISLe
記事: 2645
登録日時: 9年前
連絡を取る:

Re: csvファイルを入力する

#17

投稿記事 by ISLe » 5年前

N.R さんが書きました:>#近ごろ回答者側に確認不足が顕著な気がします。
これは正しいですね
確認がきちんとできる人は後から後からコメントを書き換えたりしないでしょう
わたしはしばしば投稿を書き換えますが、結論が変わるような書き換えはしていないつもりです。

フォーラムルールでは禁止行為として、記事の内容を無暗に変更する行為、とあります。
記事を無暗に変更する行為、ではありませんから問題無いのではないでしょうか。

ISLe
記事: 2645
登録日時: 9年前
連絡を取る:

Re: csvファイルを入力する

#18

投稿記事 by ISLe » 5年前

N.R さんが書きました:>resizeしても確保分超えたら同じことなので問題を先送りしてるだけですよね
まずKaienさんの指摘する問題を直さないと先に進むべきではないと思います
わたしが指摘した問題を直してもKaienさんが指摘した問題は無くなりません。
Kaienさんが指摘した問題を無くすと、わたしが指摘した問題は無くなったようにみえるかもしれません。
まずKaienさんの指摘する問題を直さないといけない理由は何ですか?
N.R さんが書きました:>vectorってメモリを動的確保できるものではないのですか
と議題者は書いているのでresizeしたくないであろう事は分かっています
質問者さんはresizeの有無でエラーが発生する箇所が違うことに気付いていません。
resizeをすることで動的確保が可能になる、と誤って理解してしまう可能性は少なくないと思います。
N.R さんが書きました:しかし今 resize した事によって別の間違いが浮き彫りになっている状態です
だからKaienさんはまずそれを指摘しているのだと思います
私もパッと見分からなかったので、「これは確かに議題者自身に気が付いてほしい」と思ったので同じようにヒントのみにしました
議題者自身きっとよい勉強になると思います
繰り返しますが、わたしの指摘した問題を直してもKaienさんが指摘した問題は無くなりません。
N.R さんが書きました:実際軽く動的確保に直してみるとエラーもなく通ってしまいました。
次に問題として現れるときはもっと分かりにくくなっているかもしれません

少なくとも私の周りではそういうのを問題の先送りと呼んでいます
少なくともわたしには手っ取り早く直せる方に先に手を付けただけのように見えますが。

ちなみに読み込み部分を直すことで後半のループ自体が不要になる可能性があるのでまず前半を指摘しました。

ISLe
記事: 2645
登録日時: 9年前
連絡を取る:

Re: csvファイルを入力する

#19

投稿記事 by ISLe » 5年前

Kaien さんが書きました:しかしながら、それでもresizeをする事で発生する別の問題のについては、言及すべきだったかもしれません。その件について、言葉足らずで申し訳ありませんでした。
この時点でkをカウントするループがファイルから読み込んだ行数を越えてresizeで指定した分まで空回りするということに気付いていたのか正直に教えていただけないでしょうか。

気付いていたか気付いていなかったに関わらず、質問に書かれたコードの『仕様』が変わることについて、また、そのような回答をすることについて、どうお考えなのでしょう。

ISLe
記事: 2645
登録日時: 9年前
連絡を取る:

Re: csvファイルを入力する

#20

投稿記事 by ISLe » 5年前

DOG さんが書きました:連投すみません。EOFの位置についてコメントさせて下さい。
かずまさんの投稿したコードにヒントがありますが…

コード:

while (getline(fin, str)) {
    vss[i].push_back(str);
    ++i;
}
EOF以外の状態変化にも対応するのでより汎用になります。

ISLe
記事: 2645
登録日時: 9年前
連絡を取る:

Re: csvファイルを入力する

#21

投稿記事 by ISLe » 5年前

DOG さんが書きました:そこで、N.Rさんが仰っている
>>しかし今 resize した事によって別の間違いが浮き彫りになっている状態です
ですが、resize()で前もって確保しておかないと同じエラーが出ます。
vectorの良いところは領域の動的確保なのに、これだとvectorの良いところが消えてしまっているように思えます。
C++の入門書でvectorの2次元配列を扱っている箇所があるのですが、そこでも前もってresize()で領域確保されています。
vectorの2次元配列の場合は前もって確保しなければならないのでしょうか?
いいえ、resizeするのは姑息な手段です。
少なくともわたしはDOGさんが本来望む動作を実装するのに遠回りをしていると感じます。

#ここでは姑息を本来の意味で使用しています。

N.R

Re: csvファイルを入力する

#22

投稿記事 by N.R » 5年前


私は同意したのであってISLeさんに問題があると書いたつもりはないのですが

しかし掲示板の内容を書き換える事は信頼性を揺るがす事に繋がるので多くの人がやっているように
修正線を入れるのが適切です。書き方一つでニュアンスも変わってしまいますからね。

それも「投稿前にちきんと確認していれば、そもそもそんな必要ないのにな」
という意見に何かおかしい所がありますか

アバター
みけCAT
記事: 6243
登録日時: 9年前
住所: 千葉県
連絡を取る:

Re: csvファイルを入力する

#23

投稿記事 by みけCAT » 5年前

オフトピック
N.R さんが書きました:それも「投稿前にちきんと確認していれば、そもそもそんな必要ないのにな」
という意見に何かおかしい所がありますか
「ちきんと」という部分がおかしい(ジョークとして面白い、という意味で)ですね。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

N.R

Re: csvファイルを入力する

#24

投稿記事 by N.R » 5年前

確認はするもんだ
という教訓ですw

かずま

Re: csvファイルを入力する

#25

投稿記事 by かずま » 5年前

DOG さんが書きました: csvファイルの中身は、
2,3,4
6,4,1,9,0,5
7,2,5,6
となっています。
ちなみになのですが、
getline(fin, str);
でデータを格納したstrを表示させると、
2,3,4,,,
6,4,1,9,0,5
7,2,5,6,,
となりますので、
本当ですか?
信じられません。

かずま

Re: csvファイルを入力する

#26

投稿記事 by かずま » 5年前

DOG さんが書きました:vectorの2次元配列の場合は前もって確保しなければならないのでしょうか?
push_back() を使えば、前もって確保する必要はありません。

ISLe
記事: 2645
登録日時: 9年前
連絡を取る:

Re: csvファイルを入力する

#27

投稿記事 by ISLe » 5年前

resizeしない方法は、KaienさんやN.Rさんがフォローしてくださるに違いありません。
そうでなければ問題の先送りどころか問題の棚上げですからね。

ISLe
記事: 2645
登録日時: 9年前
連絡を取る:

Re: csvファイルを入力する

#28

投稿記事 by ISLe » 5年前

オフトピック
わたしは投稿を書き換えるということについて自分の意見を述べただけです。
わたしが何を確認することについて不足を感じているかは分かっていただけないようです。
N.R さんが書きました:それも「投稿前にちきんと確認していれば、そもそもそんな必要ないのにな」
という意見に何かおかしい所がありますか
そもそも噛み合ってないので何とも言えません。

ISLe
記事: 2645
登録日時: 9年前
連絡を取る:

Re: csvファイルを入力する

#29

投稿記事 by ISLe » 5年前

そもそも
DOG さんが書きました:とりあえず、カンマ","も含めてvectorの2次元配列に格納しようとしているのですが、
というのがおかしい。

とりあえず一行ごとに読み込むなら2次元配列はおかしい。
vector<string>
で良い。

その後一行ごとに分解するときに、
vector<string> → vector<vector<int>>
と置き換えればエラーを回避するためだけに不自然なコードを記述する必要などない。

だから先に後半部分のデバッグをすることはまったく時間の無駄だとわたしには思える。


そしてかずまさんはずっと先を突っ走っている。

かずま

Re: csvファイルを入力する

#30

投稿記事 by かずま » 5年前

数値として読み込みたいのなら、vector<vector<int> > ですね。

コード:

#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>

int main(void)
{
    using namespace std;

    ifstream ifs("sample.csv");
    if (!ifs) return 1;

    vector< vector<int> > vvs;

    string line;
    for (size_t i = 0; getline(ifs, line); i++) {
        istringstream iss(line);
        vvs.push_back(vector<int>());
        int value;
        while (iss >> value) {
            vvs[i].push_back(value);
            char comma;
            iss >> comma;
        }
    }
    for (size_t i = 0; i < vvs.size(); i++) {
        for (size_t j = 0; j < vvs[i].size(); j++)
            cout << " [" << vvs[i][j] << "]";
        cout << endl;
    }
    return 0;
}

Kaien
記事: 6
登録日時: 5年前
住所: 東京

Re: csvファイルを入力する

#31

投稿記事 by Kaien » 5年前

ISLe さんが書きました:
Kaien さんが書きました:しかしながら、それでもresizeをする事で発生する別の問題のについては、言及すべきだったかもしれません。その件について、言葉足らずで申し訳ありませんでした。
この時点でkをカウントするループがファイルから読み込んだ行数を越えてresizeで指定した分まで空回りするということに気付いていたのか正直に教えていただけないでしょうか。
kをカウントするループがresizeによって空回りしてしまうことには、気づいていました。
DOG さんが書きました: 原因はいったい何なのでしょうか?
今回のケースに関しては、原因を聞く質問でしたのでアクセス領域外を触っている事が一目で分かる所を指摘してしまった事になります。
それが早計であった点は弁明のしようがありません。
実際"最初の回答"では、for文しか指摘していませんし、resize推奨していますし。
ISLe さんが書きました: 気付いていたか気付いていなかったに関わらず、質問に書かれたコードの『仕様』が変わることについて、また、そのような回答をすることについて、どうお考えなのでしょう。
質問に書かれたコードが"どうやってもこれは動作しない"等の理由から仕様を変更する必要がありそうな場合、及び質問者がそれを望んでいる場合は仕様変更も止む無しだと思いますが、基本的には、回答者は質問者の仕様を通すべきではないかと思っています。
そうでないと回答者の意思の押し付けになってしまいますから。

今回の件で、確認作業を怠ったこと、中途半端な回答をしてしまったことを反省しています。
質問者のDOG様、ISLe様を始め多くの方にご迷惑をおかけしてしまい、申し訳ありませんでした。
DOG さんが書きました: csvファイルの数値をvectorの2次元配列に格納するプログラム書いている
最後にresizeを使わない方法で、「,」を含めたCSVファイル読み込みのコードは以下みたいな感じでしょうか。
まあ、こういうやつが書いたコードですので、DOG様の求めるコードとは程遠いとは思いますが、私なりにDOG様の最初の文だけを見て、組みたいのであろうなと思えるものを書き出してみました。


実用的な意味で言えば、かずま様のコードの方が後々有効だと思いますので、あくまでこんな偏屈な方法もあるよ的な目で見て頂ければと。

コード:

#include <iostream>
#include <fstream>
#include <vector>
#include <string>

int main(int args, char* argv[])
{
    using namespace std;

    ifstream ifs;
    ifs.open("sample.csv"); // 中身はDOG様と同じ物を使っています

    // ifs.open() == true : ファイルオープン成功
    // ifs.open() == false : ファイルオープン失敗,エラー処理へ
    if (!ifs)
    {
        cout << "ファイルオープン失敗" << endl;
        return -1;
    }

    vector<vector<string>> vss; 
    
    // 読み込み
    string line; 
    while (getline(ifs, line))    // getline 失敗時 ループ終了
    {
        static size_t num = 0;
        num = vss.size(); // 1ファイルのみ1回だけ読み込むのならば、push_back後に++numでも可
        vss.push_back(vector<string>());
        vss[num].push_back(line);
    }
    ifs.close(); // デストラクタで閉じるけれど明示する派の人間なので。
    // 表示
    for (size_t i = 0; i < vss.size(); ++i)
    {
        for (size_t j = 0; j < vss[i].size(); ++j)
        {
            cout << vss[i][j] << endl;
        }
    }
    return 0;
}
// 本当にすみません。プログラムの一部が間違ってました。

実行結果

コード:

2,3,4
6,4,1,9,0,5
7,2,5,6
長文失礼しました。

N.R

Re: csvファイルを入力する

#32

投稿記事 by N.R » 5年前

一応質問として来ているのでお答えしたいのですが
何分多すぎて・・・resizeが夢に出そうです

No.8 の最初の投稿ではresizeに触れていませんでしたね
確か内容は変わらないんでしたね
resizeを使わずに指摘できますでしょうか

ISLe
記事: 2645
登録日時: 9年前
連絡を取る:

Re: csvファイルを入力する

#33

投稿記事 by ISLe » 5年前

N.R さんが書きました:No.8 の最初の投稿ではresizeに触れていませんでしたね
確か内容は変わらないんでしたね
resizeを使わずに指摘できますでしょうか
この部分ですね。
ISLe さんが書きました:そもそも23行目で空のvectorに添字参照しようという考え方がおかしいと思います。
resizeしても確保分超えたら同じことなので問題を先送りしてるだけですよね。
resizeという単語を使わなければ良いのですか?

そもそも23行目で空のvectorに添字参照しようという考え方がおかしいと思います。
もしもcsvファイルの中身が最初から150行とかあったらKaienさんの指摘する問題を直してもやはり同じエラーが出ましたよね。

という感じでどうですか。
Kaienさんの指摘投稿時点ではcsvファイルの中身は分かっていませんでした。

空の要素にアクセスすることが問題だという主旨です。
その可能性をゼロにすることが先決だと思ったので「そもそも」です。
2次元配列であること自体がおかしいと思っていたので「考え方がおかしい」です。

N.R

Re: csvファイルを入力する

#34

投稿記事 by N.R » 5年前

問題が分かりやすくなりましたね

まず議題者の質問ですが「エラーが出て困っている」んですね
「resizeさせてもエラーが出た」んですね
議題者の投稿を見れば後々行、列を2次元配列に格納したい、動的確保したいであろう事を察するのは難しくないですね

そうなれば後のfor文も変更されますね
そちらから直そうと言うのは別におかしくないですね
更に議題者がそこだけ解決して「ありがとうございました」と去っても諦めてもそれは議題者の自由ですね
議題者がresizeでいいのだ、と言うのを我々がとやかく言う権利はないです
動的確保が知りたければまた質問するでしょう。いらないと思ったら去るでしょう
csvの中身が多すぎでダメだったならまた質問するでしょう。順次解決するだけです

冒頭の回答者に
確保していないvectorの添字参照するのが問題である事が分からない
resizeで解決させておけばいいや
と考える人がいるとは思えないですね(Kaienさんはよく知らないですが)
もっともそうした所でそれも回答者の自由ですよね。
動的確保は別の人に任せて今取り組んでいる問題にだけ手助けする事は全く問題ではありませんね

直し方の方針は人それぞれあるでしょう
しかし今回Kaienさんが一番乗りして方針を決めているのですね
なので皆それを邪魔しないように見守っていたのですね
それを横からちゃちゃを入れるなとは言いません。そういう人に注意が効いた試しはないので「いるよねそういう人」で流すだけです
皆流してますね。理由は明白ですね。


このことから考えてもどの辺に確認不足があったのかさっぱり分からないですね
反省して直しようがないです

ちなみにNo:3でcsvの中身は分かっていますね
Kaienさんへの個人攻撃だっのを全体に向けてしまったのでしょうか、かなりマナー悪いですね
私にはソースと質問から見て議題者が150行あるものを 100 だけ確保してエラーだーと言うほどのバカには見えませんが、Kaienさんがそれを確認しなかったのが不足なんでしょうか
それとも他の掲示板、題について思う事をここで述べただけなのでしょうか。エチケットに問題ありですね

ちなみに
 参照しようという考え方がおかしい
のと
 参照しているのがおかしい
も意味合いが結構変わってきますね。内容が変わるかというと微妙ですね
別に深い意味はないです。これは使わないよう言わなかったので使ってもいいんですよ

N.R

Re: csvファイルを入力する

#35

投稿記事 by N.R » 5年前

なんか非難しているみたいな書き方になっていますね、スミマセン

これは私が確認した経緯ではありますが、ソースを見れば
 vss.push_back(str);
が原因であろう事は分かります。
しかしresizeしてもエラーが出た。これは解せません。
見て確認より実行確認です(目は信用するな)。
すると一発ですね。for文に間違いがある事が分かります。
それを直す話で議題が進んでいるのでそれに乗りました。

しかし別の意見もあるものです。No:8
要するにこういう事だ、というものを纏めてもらえたので(No:33)
そこから「考え方」と「そもそも」を除いてみましょうか
これを除いても根本的に伝えたい内容は変わらない事をISLeさんは保証してくれています。


>23行目で空のvectorに添字参照しているのがおかしいと思います。
 (それは分かっています)
>もしもcsvファイルの中身が最初から150行とかあったらKaienさんの指摘する問題を直してもやはり同じエラーが出ましたよね。
 (No:3で分かっているので無意味ですね。それでなくとも普通十分な容量をとるものなのでは?)
>空の要素にアクセスすることが問題だという主旨です。
 (そうですね、それも分かっています)
>その可能性をゼロにすることが先決だと思ったのです。
 (後ではダメなんですか?既に進んでいる方針を壊してでも優先しなくてはならないほどの理由なのですよね)
>2次元配列であること自体がおかしいです。
 (後々行、列を格納したいのだろうから特に不思議はないです)

と普通なら括弧内のツッコミを入れる所ですが
そこでポイントとなるのが私たちは確認不足だ、という事です。
つまり何かを確認すれば「ツッコミ」は「納得」に変わるのでしょう。

私が確認した経緯は上記の通りですが実際確認した時間なんてたかが知れているので不十分だとは思います。
後学のためにその確認方法を知りたいのです。

ISLe
記事: 2645
登録日時: 9年前
連絡を取る:

Re: csvファイルを入力する

#36

投稿記事 by ISLe » 5年前

N.R さんが書きました:ちなみにNo:3でcsvの中身は分かっていますね
Kaienさんへの個人攻撃だっのを全体に向けてしまったのでしょうか、かなりマナー悪いですね
私にはソースと質問から見て議題者が150行あるものを 100 だけ確保してエラーだーと言うほどのバカには見えませんが、Kaienさんがそれを確認しなかったのが不足なんでしょうか
それとも他の掲示板、題について思う事をここで述べただけなのでしょうか。エチケットに問題ありですね
なるほど。
KairenさんはNo.2の投稿の時点で、No.3の投稿を予測できていたのですね。
そうでなければ、コメントアウトしてあるresizeを復活させても読み込み時のエラーが無くなる確証はないですからね。

Kairenさんは本当のエスパーなのでしょうか。
だとしたら、このトピックが荒れないようにすることも可能だったのではないでしょうか。

ISLe
記事: 2645
登録日時: 9年前
連絡を取る:

Re: csvファイルを入力する

#37

投稿記事 by ISLe » 5年前

N.R さんが書きました:>23行目で空のvectorに添字参照しているのがおかしいと思います。
 (それは分かっています)
その問題が隠れてしまう可能性は無視したのですか?
N.R さんが書きました:>もしもcsvファイルの中身が最初から150行とかあったらKaienさんの指摘する問題を直してもやはり同じエラーが出ましたよね。
 (No:3で分かっているので無意味ですね。それでなくとも普通十分な容量をとるものなのでは?)
resizeを復活させればpush_backの問題はなくなるかのように書いているのはNo.2です。
ふつうはこうする、というのは思い込みですよね。
思い込みは排除すべきなのでは?
N.R さんが書きました:>空の要素にアクセスすることが問題だという主旨です。
 (そうですね、それも分かっています)
その問題が隠れてしまう可能性は無視したのですか?
N.R さんが書きました:>その可能性をゼロにすることが先決だと思ったのです。
 (後ではダメなんですか?既に進んでいる方針を壊してでも優先しなくてはならないほどの理由なのですよね)
後ではダメです。
問題が隠れてしまう可能性があります。
それは最初から指摘しています。
N.R さんが書きました:>2次元配列であること自体がおかしいです。
 (後々行、列を格納したいのだろうから特に不思議はないです)
わたしは思考の過程を整理することが効率の良いプログラミングに重要な要素だと考えています。
N.R さんが書きました:と普通なら括弧内のツッコミを入れる所ですが
そこでポイントとなるのが私たちは確認不足だ、という事です。
つまり何かを確認すれば「ツッコミ」は「納得」に変わるのでしょう。

私が確認した経緯は上記の通りですが実際確認した時間なんてたかが知れているので不十分だとは思います。
後学のためにその確認方法を知りたいのです。
例外を食わせるというのは、デバッグの基本中の基本だと思っていました。
それが浸透していないということに驚きを禁じえないのですが、考えてみればこれも思い込みでした。

ISLe
記事: 2645
登録日時: 9年前
連絡を取る:

Re: csvファイルを入力する

#38

投稿記事 by ISLe » 5年前

そもそもこれが真摯な回答なのでしょうか。
掲示板の総意としてそうだというのであれば、わたしはこの掲示板を見限るだけですが。
Kaien さんが書きました:こんばんは。
DOG さんが書きました: vectorの確保領域以上の所にアクセスしているという旨のエラー
その通りです。それが起こりそうな所をみるしかないですね。
DOG さんが書きました: ちなみに、20行目のコメント部分を解除しても同様のエラーが出てしまいます。
解除しても、別の所で領域外をアクセスしているので、同様のエラーが出ています。
20行目の文は必要ですので、コメントは外してください。


因みに原因はfor文の方にあります。
1箇所だけ不自然な所があると思います。
よく見てみてください。
resizeのコメントアウトを解除するというのは、質問文では「ちなみに~」以降に書かれていることです。
「必要ですので、コメントは外してください」と言い切っています。

どう考えても質問者さんにきちんと向き合って回答しているようには思えません。
N.R さんが書きました:そうなれば後のfor文も変更されますね
そちらから直そうと言うのは別におかしくないですね
更に議題者がそこだけ解決して「ありがとうございました」と去っても諦めてもそれは議題者の自由ですね
議題者がresizeでいいのだ、と言うのを我々がとやかく言う権利はないです
動的確保が知りたければまた質問するでしょう。いらないと思ったら去るでしょう
csvの中身が多すぎでダメだったならまた質問するでしょう。順次解決するだけです
そもそも、vectorでメモリを動的確保できずエラーになるのはなぜか、という質問ですよ。

「動的確保が知りたければまた質問するでしょう」?
何を言っているのですか?
あなたの日本語がわたしには分かりません。

zeek

Re: csvファイルを入力する

#39

投稿記事 by zeek » 5年前

DOG さん
参考までに eof() の使用例を提示しておきます。
ファイル読み込み処理では eof() or exceptions() を使用しないと正しく読み込めたかの判断は難しいと思います。
while (getline(ifs, line)) の繰り返しを終了するのはエラー終了の場合もあるためです。

コード:

#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>
#include <cstdlib>

using std::vector;
using std::string;
using std::ifstream;
using std::stringstream;
using std::cout;
using std::endl;

bool ReadCsv(vector<vector<string> > &svv, const char *pfname);
void PrintCsv(const vector<vector<string> > &svv);

int main(void)
{
    vector< vector<string> > svv;
    
    if (!ReadCsv(svv, "sample.csv")) {
        cout << "Error Read file!" << endl;
        return EXIT_FAILURE;
    }
    PrintCsv(svv);
    return EXIT_SUCCESS;
}

// svv[0][0] == "2" の TYPE
bool ReadCsv(vector<vector<string> > &svv, const char *pfname)
{
    if (pfname) {
        ifstream ifs(pfname);
        if (ifs) {
            string line, item;
            while (getline(ifs, line)) {
                stringstream iss(line);
                svv.push_back(vector<string>());
                while (getline(iss, item, iss.widen(','))) {
                    svv.rbegin()->push_back(item);
                }
            }
            return ifs.eof();
        }
    }
    return false;
}

// svv[0][0] == "2,3,4" の TYPE
bool ReadCsv(vector<vector<string> > &svv, const char *pfname)
{
    if (pfname) {
        ifstream ifs(pfname);
        if (ifs) {
            string line;
            while (getline(ifs, line)) {
                svv.push_back(vector<string>());
                svv.rbegin()->push_back(line);
            }
            return ifs.eof();
        }
    }
    return false;
}

void PrintCsv(const vector<vector<string> > &svv)
{
    for (size_t ui = 0; ui < svv.size(); ui++) {
        for (size_t uj = 0; uj < svv[ui].size(); uj++) {
            cout << " [" << svv[ui][uj] << "]";
        }
        cout << endl;
    }
}
P.S.
ISLe さんへ
こちらにコメントをされても回答させていただくとは限りません。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: csvファイルを入力する

#40

投稿記事 by softya(ソフト屋) » 5年前

>そもそもこれが真摯な回答なのでしょうか。
>掲示板の総意としてそうだというのであれば、わたしはこの掲示板を見限るだけですが。

申し訳ありません。
最初の方の回答に乗っかって全体を見ずにコメントしてしまいました。
後の展開は、どんどん進んでいったため内容に付いて行けなくなったので回答を控えておりました。
※ これはISLeさんへの個人的な謝罪です。掲示板を代表するものではないと書き添えさせていただきます。今後間違いのない回答を皆さんに要求するものでもありません。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

N.R

Re: csvファイルを入力する

#41

投稿記事 by N.R » 5年前

申し訳ありません
No:16 でうかつな書き込みをしてしまったためISLeさんに何か誤解を与えてしまったようで。

このままでは見ている人がISLeさんが「ろくに確認もせずに書き込んだら実は自分がよく確認していなかった」のを指摘されて怒ったように
誤解してしまうと思ってしまう可能性(持論の展開は自由ですが自分がやっているというカミングアウトは必要ないですからね)があると思ったので何とか誤解を解こうと思ったのですが
反論として飛んでくるものが後から書き加えた内容の物ばかりだったので
これは更にまずいと問題点を絞り、どういう確認をすればよかったのかを最終的な問いとしました。
実際知りたい所ですからね

大抵の場合、人は旗色が悪くなると関係ない話を始めるか意味が分からないと言いだすものですがたまたま忙しかっただけだと思いますので回答を待ちましょう
また私の日本語が通じなくとも一般的な確認なのであれば他の人が教えてくれるでしょう。

>>動的確保は別の人に任せて今取り組んでいる問題にだけ手助けする事は全く問題ではありませんね
としているように
>最初の方の回答に乗っかって全体を見ずにコメントしてしまいました
では不足と言われても釈然としないですね

>掲示板の総意としてそうだというのであれば、わたしはこの掲示板を見限るだけですが
もちろんそれは自由であってISLeさんの行動を束縛する権利は誰にもありません
他の掲示板で回答される事と思いますので私も困ったら質問に行きますよ


以降は単なる持論になりますが
私は確認を怠ったり間違ったりして後で気がついても、自分の体裁を守るために間違った事を押しつけるという行為は絶対に許しません。
それは間違いの度合いではなく姿勢そのものがです。
自分に権力が、力があると思うと「見限るぞ」とか脅しにも似た言葉で仲裁する立場の者を味方につけようとし始めたりするものです。
インターネットは特にこの掲示板は皆が平等です

アバター
nullptr
記事: 239
登録日時: 7年前

Re: csvファイルを入力する

#42

投稿記事 by nullptr » 5年前

オフトピック
別に私はこの流れがどう転んでも構いませんし、誰と誰がいがみ合おうが構いません。ですので話に横槍を入れたくもないですし、関わりたくもないのですが、少し書き込ませていただきます。
No:16を始めとして、書き込みに皮肉や煽り、挑発が多いと感じます。トピックが荒れているのは明白ですが、あまりに見るに耐えません。
以降は単なる持論になりますが
私は確認を怠ったり間違ったりして後で気がついても、自分の体裁を守るために間違った事を押しつけるという行為は絶対に許しません。
それは間違いの度合いではなく姿勢そのものがです。
自分に権力が、力があると思うと「見限るぞ」とか脅しにも似た言葉で仲裁する立場の者を味方につけようとし始めたりするものです。
インターネットは特にこの掲示板は皆が平等です
あくまで例として最近であるN.Rさんの書き込みを挙げさせてもらいますが、このように個人の持論をここで展開する必要はありません。ここでそれを書き込む必要は無いですよね。ここにそれを書き込むのは第三者から見たらただの煽りです。

回答者同士で、解決の流れに納得がいかないなら他所で話し合って頂けますか。自分が許せない行為があるならTwitterででも意見を述べてはいかがでしょうか。
最初に解答した人の流れで解決しなければならないルールもありません。最初に解答した人の流れに納得出来ないなら当人とPMなりで話し合うのが筋ではないでしょうか。質問者の前で回答者たちが「こう教えるべきだ」と喧嘩していても質問が埋もれるだけです。ISLeさんとN.Rさんの議論のことです。

どちらが正しいかどうかに私は興味はありません。喧嘩は見ているだけで不快に感じる人も居ます。ここで終わりにするか、続けるなら他所でお願いします。

ISLeさんが自ら身を引いて掲示板を去ってくださって、終わるかと思ったのに続けられても不快です。

最近ここのチャットでもこのトピックは話題になりましたが、そちらでも不快に感じた人しか居ませんでした。第三者に対し不快な行為だと自覚してください。
ここは第三者も見ているトピックであり、第三者は問題の解決を知りたいだけです。解決方法の荒れた議論を見たいわけではありません。ここは自由に持論を展開していい場所ではありません。
その話はここでやめる事を要求します。

本当はN.Rさんに直接送りたいのですが、連絡手段が無いため、オフトピックとして投稿させていただきます。
もし私に文句があれば時間のあるときに返事しますので、lowe4649+mixcpp♪gmail.comまでメールでお伝え下さい。♪は@に変えてください。
長文失礼いたしました。
 
 
✜ で C ご ✜
: す + 注 :
¦ か + 文 ¦
?
Is the は :
order C++? ✜
     糸冬   
  ――――――――
  制作・著作 NHK
 
 

アバター
Tatu
記事: 445
登録日時: 9年前
住所: 北海道

Re: csvファイルを入力する

#43

投稿記事 by Tatu » 5年前

>>DOGさん
見ていらっしゃるかわかりませんが
vssの要素であるvss[]の要素の動的確保はしようとしているのに
vssの要素の動的確保をしていないように見えます。



>>N.Rさん

確認不足は「質問者が何を求めているのか」の確認が不足している
という意味ではないでしょうか?

N.R

Re: csvファイルを入力する

#44

投稿記事 by N.R » 5年前

そうですね。他の人には迷惑ですからね
このくらいにしておきます。

過去の事ではありますが「実力を行使する」などと言い放った人がおりましてね
その言葉をそっくり返させて頂きました

私の方が去りますのでご安心を

Milla

Re: csvファイルを入力する

#45

投稿記事 by Milla » 5年前

結局、この問題はいつ解決するの?

アバター
usao
記事: 1565
登録日時: 6年前

Re: csvファイルを入力する

#46

投稿記事 by usao » 5年前

>結局、この問題はいつ解決するの?

ちょっと雰囲気的に質問者様が書き込みにくいのかもしれませんね.
とりあえず質問内容への回答や指摘などを拾い集めてみました.

[hr]
(1)質問者様の提示された最初のコードにおいてresize()が無い場合
 vector vssがサイズ0である状態.
 →読込時にいきなり存在していないi番目の要素vssにアクセスしている.
  コレがエラーの原因.
  vectorにはメモリを必要に応じてやりくりしてくれるメンバ関数群があるが,
  逆に言えば,「それ以外の触り方」ではメモリを自動的にやりくりしてくれるわけではない,ということ
  →これに関しては動的にサイズを拡張してくれるメンバ関数であるpush_back()を使う方法が回答されている.

(2)最初のコードにおいてresize()がある場合
 vssのサイズが100である状態.
 →(動作確認時には)読み込みのwhileループ内ではエラーが起きなかった.
  これは今回テストに用いられたファイル内容が数行しかないので,
  これを読み込んだ内容を格納するのに100個も要素があれば事足りたため.
  →ただし,この方法では,たとえばファイルが150行とかあったら
   やはり(1)と同じエラーになってしまう.
   resize()で一定量のサイズを確保するという手段は根本的な解決策とはならない旨が指摘されている.

 →それとは別に,vssの内容を表示しようとしてる箇所でも領域外参照エラーが出る.
  →for()のところが間違っていて,領域外を参照しているから
   →このことについては,少なくともエラーが出ない形に修正された
   →ただし,プログラムの表示を見るだけではわからない問題点として
    読み込めた要素(行)数とvssのサイズ(resizeにより100になっている)は別物であるのに
    forではvssのサイズ回数ループが回っているという点も指摘されている.

(3)eofのチェック箇所について
 getlineの成否に関わらずpush_backが走る状態になっている.
 →eofを使わない,より良い方法が回答されている

(4)その他
 ・全体的なコード案がいくつか示されている
 ・今とりあえずやろうとしていること に対して言えば
  vector<vector<string>>でなく vector<string>で良い,という指摘
  (「2次元」という言葉に惑わされるのなら,まずは1次元から段階を踏んで把握していくべし,
   といった旨の指摘かと思います)
 ・数値として読みたいなら vector<vector<int>> だろうという指摘
[hr]
だいたいこんな感じでしょうか.

玉井

Re: csvファイルを入力する

#47

投稿記事 by 玉井 » 5年前

ISLeさんもN.Rさんもkaienさんも、どなたも誰も去らないでほしいです。

知識や技術、そして教え方、人によって様々かと思いますが
それでも、初心者で迷える子羊である質問者に対して
なんとか力になってあげようとする心意気は皆さん同じなはずです。

アドバイスしている側の人たちが争って、しかも結果誰かが去るだなんて、
普段からこの掲示板のレスをくださる皆さんに感謝の気持ちを感じてる
こちら側の人間からしたらあまりに悲しすぎます。

極端な例えですが、生徒同士や生徒と先生がもめるのは
まだ仕方ないかもしれませんが、
先生同士がもめて片方がいなくなるなんて
生徒からしたらやるせなさすぎです。

アフリカは難民からしたら、ボランティアでやってきた人たちが
ケンカをし始め、両方とも帰ってしまうようなもんです。
残された難民が悲しすぎます。

無理に仲直りしてくださいとは言いませんが、
ただでさえ若いモノたちが敬遠して廃れ気味のC言語です。
今後もその迷えるプログラマたちの力になってやってほしいです。
お願いします。

アバター
usao
記事: 1565
登録日時: 6年前

Re: csvファイルを入力する

#48

投稿記事 by usao » 5年前

ところで
データがいくつあるかわからないファイルを読み込むときに
vector<vector<X>>にpush_backしていくという方法は
コピーが頻繁に行われそうなのが気になるのですが,その辺ってどうなんでしょう?
例えば読込時は list<list<X>> みたいなのに追加していき,
読込終了後に,実際に持ちたいデータ形式である vector<vector<X>> をそこから作るような形を取ったら
データコピーは最後に全体を一度だけになるので
そこらへんの効率が良いような気がするのですが,実際どうなのでしょう?
(なんか便乗質問みたいになってしまいますが…)


>玉井さん
うっかりミスかと思いますが,勝手に[解決]を付けてしまうのは良くないのではないかと.

閉鎖

“C言語何でも質問掲示板” へ戻る