STLのvectorコンテナを使ったプログラムで質問があります

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

STLのvectorコンテナを使ったプログラムで質問があります

#1

投稿記事 by taketoshi » 13年前

エクセルのような5行×5列のデータを処理したくて
構造体の内部にstring型のポインタを宣言し、vectorコンテナに順次構造体を放り込んで
後から登録したデータをvectorコンテナ経由で呼び出すプログラムを書いています。

本来ならば、太郎~、次郎~と順にデータが出てくるのを狙っているのですが
vectorコンテナ内がすべて花子で埋め尽くされてしまいました。

構造体の領域は一つしか用意していないのですが、vectorコンテナに構造体を登録する場合は
元の構造体の領域を保存しておかねばならないのでしょうか・・・・?

プログラムのミスも含めてご指導いただけると助かります。
また、このようなデータを処理する場合こうしたほうが良いというアドバイスもいただけると助かります。

コード:


#include "stdafx.h"

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

using namespace std;


//エクセルのように分割して文字列を保持したいので
//string型へのポインタを構造体内に宣言しておく
//保持するデータの列数の分だけ後でnewする
typedef struct{
	string *str;
}DATA;

////////////////////////////////////////
//例:格納するデータ項目
//名前-年齢-出身地-性別-趣味
//
//今回はこれを5名分格納する領域を動的に確保する
//string型、構造体、vectorコンテナを使って実装する
////////////////////////////////////////


int _tmain(int argc, _TCHAR* argv[])
{

	//カウンタ変数
	int i,nCount;

	//テスト用データ
	char *lpHoge[] = {"太郎","32","日本","男","釣り",
					"次郎","29","アメリカ","男","読書",
					"三郎","25","オランダ","男","エリートヤンキー",
					"五郎","22","イスラエル","男","三歩",
					"花子","26","japan","女","料理"};

	//コンテナの宣言
	vector<DATA> vData;

	//構造体の宣言
	DATA memData;

	//今回は5項目のデータを保持するとする
	int nCol = 5;

	//5名分の行数を確保
	int nRow = 5;

	//項目の列数を確保
	memData.str = new string[nCol];

	//構造体にデータを書いてvectorコンテナに代入していく
	for(i = 0,nCount = 0;i < sizeof(lpHoge) / sizeof(lpHoge[0]) ;++i){
		memData.str[nCount] = lpHoge[i];
		//趣味まで格納したらカウンタをリセットしてコンテナに登録する
		//nCow - 1で要素数以上にアクセスさせない
		if(nCount == nCol -1){
			nCount = 0;
			vData.push_back(memData);
		}else{
			++nCount;
		}
	}

	//格納データの確認
	//イテレータの宣言
	vector<DATA>::iterator pv;
	//要素の先頭を代入
	pv = vData.begin();

	for(pv,nCount = 0;pv != vData.end();){
		printf("%s , ",(*pv).str[nCount].c_str());
		if(nCount == nCol -1){
			cout <<endl;
			nCount = 0;
			pv++;
		}else{
			nCount++;
		}

	}

	//要素の削除
	delete[] memData.str;

	return 0;
}

出力結果
花子 , 26 , japan , 女 , 料理 ,
花子 , 26 , japan , 女 , 料理 ,
花子 , 26 , japan , 女 , 料理 ,
花子 , 26 , japan , 女 , 料理 ,
花子 , 26 , japan , 女 , 料理 ,
続行するには何かキーを押してください . . .

アバター
h2so5
副管理人
記事: 2212
登録日時: 15年前
住所: 東京
連絡を取る:

Re: STLのvectorコンテナを使ったプログラムで質問があります

#2

投稿記事 by h2so5 » 13年前

二次配列を使いたいということなら、vector<vector<DATA>>を使うべきだと思います。

YuO
記事: 947
登録日時: 15年前
住所: 東京都世田谷区

Re: STLのvectorコンテナを使ったプログラムで質問があります

#3

投稿記事 by YuO » 13年前

ポインタコピーしても元になるポインタが指し示すオブジェクトはコピーされませんよ。

----

2012-06-30T19:23+09:00 表現がおかしいと思ったので修正

へにっくす

Re: STLのvectorコンテナを使ったプログラムで質問があります

#4

投稿記事 by へにっくす » 13年前

h2so5さんとかぶりますけど、
std::vector<std::vector<std::string> >
でいい気がしますねえ。。

コード:

#include "stdafx.h"

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

int _tmain(int argc, _TCHAR* argv[])
{
	//カウンタ変数
	int i, j;

	//テスト用データ
	char *lpHoge[] = {"太郎","32","日本","男","釣り",
		"次郎","29","アメリカ","男","読書",
		"三郎","25","オランダ","男","エリートヤンキー",
		"五郎","22","イスラエル","男","三歩",
		"花子","26","japan","女","料理"};

	std::vector<std::vector<std::string> > vec;

	for ( i = 0; i < 5; i++ )
	{
		std::vector<std::string> vline;
		for ( j = 0; j < 5; j++ )
		{
			std::string sz = lpHoge[i * 5 + j];
			vline.push_back(sz);
		}
		vec.push_back(vline);
	}

	std::vector<std::vector<std::string> >::iterator it;
	for ( it = vec.begin(); it != vec.end(); it++ )
	{
		std::vector<std::string> vline = *it;
		std::vector<std::string>::iterator vit;
		for ( vit = vline.begin(); vit != vline.end(); vit++ )
		{
			std::string sz = *vit;
			printf("%s\n", sz.c_str());
		}
	}
	return 0;
}

アバター
MoNoQLoREATOR
記事: 284
登録日時: 15年前
住所: 東京

Re: STLのvectorコンテナを使ったプログラムで質問があります

#5

投稿記事 by MoNoQLoREATOR » 13年前

せっかくvectorという便利な物があるというのにnewを使うのはナンセンスだと思います。
vectorは内容をヒープ領域に保存します。(代入の際に内容をコピーします)
つまり、自動でnewとdeleteをやってくれるのです。
だから、vector<vector<string> >
として”値”を直接代入するべきだと思います。

例を挙げますと、こうです。

コード:

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

int main(){

	typedef std::vector<std::vector<std::string> > vstring;
	typedef unsigned int uint;

	const uint width = 5;
	const uint height = 5;



	class ForSet{
		std::vector<std::string> * target;

	public:

		void init(std::vector<std::string> & target, uint width){
			this->target = &target;
			this->target->reserve(width);
		}

		ForSet & operator() (const std::string & str){
			target->push_back(str);
			return *this;
		}
	}set;





	vstring vData;

	vData.resize(height);

	set.init(vData[0], width);
	set("太郎")("32")("日本")("男")("釣り");

	set.init(vData[1], width);
	set("次郎")("29")("アメリカ")("男")("読書");

	set.init(vData[2], width);
	set("三郎")("25")("オランダ")("男")("エリートヤンキー");

	set.init(vData[3], width);
	set("五郎")("22")("イスラエル")("男")("三歩");

	set.init(vData[4], width);
	set("花子")("26")("japan")("女")("料理");



	for(uint i=0;i<height;++i){
		const std::vector<std::string> & data = vData[i];
		std::cout<<data[0]<<" , "<<data[1]<<" , "<<data[2]<<" , "<<data[3]<<" , "<<data[4]<<std::endl;
	}




}

かずま

Re: STLのvectorコンテナを使ったプログラムで質問があります

#6

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

taketoshi さんが書きました:プログラムのミスも含めてご指導いただけると助かります。
memData.str = new string[nCol]; を
if (nCount == 0) memData.str = new string[nCol]; に変更し、
for 文の中の先頭に移す。

delete[] memData.str; を
for (int i = 0; i < nRow; i++) delete[] vData.str; に変更する。
taketoshi さんが書きました:また、このようなデータを処理する場合こうしたほうが良いというアドバイスもいただけると助かります。

コード:

#include <vector>
#include <string>
#include <iostream>
 
int main()
{
    char *lpHoge[] = {
        "太郎", "32", "日本",       "男", "釣り",
        "次郎", "29", "アメリカ",   "男", "読書",
        "三郎", "25", "オランダ",   "男", "エリートヤンキー",
        "五郎", "22", "イスラエル", "男", "三歩",
        "花子", "26", "japan",      "女", "料理",
    };
    const int nCol = 5, nRow = 5;
    using namespace std;
    vector<vector<string> > vData(nRow);
 
    for (int i = 0; i < nRow; i++) {
        vector<string> v(nCol);
        for (int j = 0; j < nCol; j++)
            v[j] = lpHoge[i*nCol + j];
        vData[i].swap(v);
    }
    for (int i = 0; i < nRow; i++) {
        for (int j = 0; j < nCol; j++)
            cout << vData[i][j] << " , ";
        endl(cout);
    }
}

taketoshi
記事: 222
登録日時: 15年前
住所: 日本国

Re: STLのvectorコンテナを使ったプログラムで質問があります

#7

投稿記事 by taketoshi » 13年前

皆さんご指導ありがとうございます。
vectorの二次元配列って出来るのですね、知りませんでした。
ただ、理解するのにもう少し時間がかかりそうです。
vectorの二次元配列の勉強をしてそちらを使っていきます。

>かずまさん
提示されたところを改変したところ、プログラムが正常に動きました。
毎回newすることによってポインタの指し示している位置を変更しているようですね。
YuOさんの仰っていることと合わせて理解できました。

皆様ありがとうございました。解決とさせていただきます。

閉鎖

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