vectorで構造体配列を使うには?

解決


はやし  2007-12-08 06:17:39  No: 67142

はじめまして、はやしと申します。
先ず、開発環境ですがWinXPで、VC++6.0です。

CGIでwebアプリケーションの開発(ブラウザはIE6.0 SP2)
をしているのですが、VC++なのにほぼCで組んでいる為、VC++につきましては何もわかりません。

構造体の動的確保として、最初reallocを使っていたのですが、
色んなサイトを見たところ、c++ではvectorを使うのが普通だと
書いてあったので、これを使わない手はないと思い、使う事にしました。

やりたい事はこうです。
先ず構造体宣言して、
struct XXX{
    char name[10];
    char address[30];
}
vectorの型に構造体の型を指定して、
vector< XXX > v;
XXX st;
ファイルを1行ずつ読みながら、内容をchar型の変数に入れて、
cname = xxxxxx;
それをfor文でvectorの要素数分回しながらvectorの中身と照らし合わせて
同じ文字列が無ければ配列を追加して
v.push_back(st);
strcpy(v[iCnt].name, cname);
ってコピーしていき、
それをhtmlのプルダウンリストを作る時に、vectorに入れた中身を
入れていく。

って事がやりたいんですけど、この場合、初期化ってどうしたら
いいのでしょうか?
また、実際に試してみたのですが(初期化しないで)、
わけのわからない文字列が沢山表示されてしまいました。

何が間違っているのかさっぱりわかりません。
根本的に間違えているのでしょうか?
どうぞご教授お願いします。


通りすがり  2007-12-08 07:32:21  No: 67143

初期化っていうのはプルダウンリストに文字列を入れ込むこと?
cnameはcharじゃなくchar[10]とかなんですよね?

残業の息抜きに、VC2005で、標準入力したのを出力するのをちょっと作ってみました。
照らし合わせるのが面倒なんで、cnameはstringですけど。

ソース
********************************************
#include <iostream>
#include <vector>
#include <string>

struct XXX
{
  char name[10];
  char address[30];
};

int main( int argc, char* argv[] )
{
  std::vector< XXX > v;
  XXX st;

  std::string cname;

  std::cout <<  "入力" << std::endl;
  std::cout <<  "------------" << std::endl;

  while( true )
  {
    std::cin >> cname;

    if( !cname.compare( "0" ) )
      break;

    bool isAdd = true;
    for( size_t i = 0; i < v.size(); i++ )
    {
      if( !cname.compare( v[ i ].name ) )
        isAdd = false;
    }

    if( isAdd )
    {
      v.push_back(st);
      size_t iCnt = v.size() - 1;
      strcpy( v[iCnt].name, cname.c_str() );
    }

    cname.clear();
  }

  std::cout <<  "------------\n" << std::endl;
  std::cout <<  "チェック" << std::endl;
  std::cout <<  "------------" << std::endl;

  for( size_t i = 0; i < v.size(); i++ )
  {
    std::cout <<  v[ i ].name << std::endl;
  }

  std::cout <<  "------------" << std::endl;

  return 0;
}
********************************************

実行結果
********************************************
入力
------------
hoge
moge
hogehoge
hoge
gufu
0
------------

チェック
------------
hoge
moge
hogehoge
gufu
------------
********************************************

あと、要素数が不定なら、vectorに構造体そのまま入れるより、構造体のスマートポインタでも入れる方が、push_backのコピーコストをなくていい気もしますが。
もしくは別のコンテナ使うとか。


通りすがり  2007-12-08 07:34:25  No: 67144

cname.clear();  ←いりません。


cpp  2007-12-09 03:21:39  No: 67145

本題とは関係ないですが。

>c++ではvectorを使うのが普通だと
別にそうでもないですよ。C++とSTL(vector)は別物です。C++はサポートするけどSTLはサポートしないという環境もあります。

またVC++がいわゆるWindowsプログラミングを指しているならc++とVC++も別物です。c++はunixやMACでもあります。

とりあえずそこら辺から勉強した方がよいかと。


επιστημη  2007-12-09 06:41:46  No: 67146

>> c++ではvectorを使うのが普通だと
> 別にそうでもないですよ。C++とSTL(vector)は別物です。

標準C++であれば、STLはC++言語規格の一部です。
なので普通と言っても差支えないかと。


はやし  2007-12-10 19:53:20  No: 67147

通りすがりさん、cppさん、επιστημηさん、お返事ありがとうございます。
早速お返事を頂いたのにこちらのお返事が遅くなりましてすみません。

>初期化っていうのはプルダウンリストに文字列を入れ込むこと?
ごめんなさい、初期化はvectorでメモリを確保した時の初期化の事です。
charとかintとかだったら、puch_backする時に初期値を入れられるみたい
ですが、型がユーザ定義型の場合はどうしたらいいのでしょうか?
vectorの要素ひとつひとつに対して初期化を行わないといけないでしょうか?

>cnameはcharじゃなくchar[10]とかなんですよね?
そうです。cnameがcharなのは、ファイルを1行読んだ時に、他の
関数に渡してある部分を1行から抜き出してcharの変数に入れて返していて、その戻り値と、vectorの中身を比較したいので、charなのです。

>vectorに構造体そのまま入れるより、構造体のスマートポインタでも
>入れる方が、push_backのコピーコストをなくていい気もしますが。
>もしくは別のコンテナ使うとか。
なるほど。
因みに別のコンテナって具体的にどんなものがありますか?

>とりあえずそこら辺から勉強した方がよいかと。
本当に勉強不足ですみません。
これから最低限の事は勉強します。


通りすがりさん  2007-12-10 21:33:25  No: 67148

> charとかintとかだったら、puch_backする時に初期値を入れられるみたい
> ですが、型がユーザ定義型の場合はどうしたらいいのでしょうか?
> vectorの要素ひとつひとつに対して初期化を行わないといけないでしょうか?

charでもintでもユーザー定義型でもpush_backしたそのままの値が入ります。
push_backする前に初期化(処理を)してください。

-------------------------
std::vector< XXX > v;
XXX st;
st.name = '\0';
st.address = '\0';

v.push_back(st);
-------------------------

もちろん、c++なのでコンストラクタで初期化してもいいですが。

-------------------------
struct XXX
{
    char name[10];
    char address[30];

    XXX();  // コンストラクタ
};

XXX::XXX() : name( "\0" ), address( "\0" )
-------------------------


επιστημη  2007-12-11 00:13:01  No: 67149

> -------------------------
> struct XXX {
>     char name[10];
>     char address[30];
>     XXX();  // コンストラクタ
> };
>
> XXX::XXX() : name( "\0" ), address( "\0" )
> -------------------------

...これは無理っしょ。


通りすがり  2007-12-11 00:28:08  No: 67150

あ・・・配列でした・・・。orz
初期化できないのを忘れてました。
間違ったこと書いてすみません。


通りすがり  2007-12-11 00:44:47  No: 67151

>     st.name = '\0';
>     st.address = '\0';

も間違いでした・・・。orz
    *st.name = '\0';
    *st.address = '\0';

    st.name[0] = '\0';
    st.address[0] = '\0';
ですね。


はやし  2007-12-12 05:00:27  No: 67152

通りすがりさん、επιστημηさんお返事ありがとうございます。
なるほど!!
試してみます。というか、別の仕事で今後2週間ほど試す事が出来ないのですが、解決したら必ず報告します。
ありがとうございました。


はやし  2008-01-29 01:34:54  No: 67153

ご無沙汰しております、はやしです。

自分で2週間と言っておきながら、別件が長引いてしまい2ヶ月経って
しまいました・・・。ごめんなさい。

通りすがりさんに教えて頂いたようにpush_backする前に初期化をしました
ところ、上手くいきました。

本当に有難うございました。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加