• ベストアンサー

配列の配列をmemcpyやmemcmpしたいです

【環境】WindowsXP(SP2)、VisualStudio2005++(MFC) タイトルの通りなんですが、配列の配列を比較したりコピーしたいのですが、以下に質問を3つ記載させていただきますので、どなたかご教授お願いいたしますm(__)m 1.宣言と初期化について char **buf; buf = new char*[3200]; for(int i=0; i < 3200; i++) { buf[i] = new char[4]; } これで、buf[1]、buf[2]、buf[3]、buf[4]に、それぞれ3200のchar型の配列が宣言された事になりますでしょうか? ※buf[4][3200] なのか buf[3200][4]なのかよく分からないです。 2.上記の方法で定義した2つの配列(bufとtmp)の比較 for(int i =0; i < 4; i++) { memcmp (buf[i], tmp[i], sizeof(tmp[i])); } これで比較出来ますでしょうか? 3.上記の方法で定義した2つの配列(bufとtmp)のコピー for(int i =0; i < 4; i++) { memcpy_s(buf[i], sizeof(buf[i]), tmp[i], 3200 * sizeof(char)); } これではバッファオーバーランエラーが発生してしまうのですが、どこがおかしいでしょうか? 以上3点、初心者の質問なので意味が分からないような箇所があるとは思いますが、どうかご教授お願いいたしますm(__)m  

質問者が選んだベストアンサー

  • ベストアンサー
  • BLK314
  • ベストアンサー率55% (84/152)
回答No.6

string 動的確保のサンプルです。 STLの情報はネットに沢山あります STL vectorとか STL stringで検索してみてください。 分かりやすいサイトも沢山ありますよ!!! //////////////////// 以下 ソース /////////////////////////// #include <string> #include <vector> // vector用 #include <iostream> // vectorもstringも同一の名前空間[std]にある // したがって「おまじない」は1つでよい using namespace std; int main(int argc, char* argv[]) { // stringを動的に確保します // new で確保することもできます int n = 5; string* s = new string[n]; // 通常のクラス同様にアクセスできます s[0] = "ABC"; s[1] = "DEF"; printf("最初の文字列は %s です。\n", s[0].c_str()); printf("2番目の文字列は %s です。\n", s[1].c_str()); // どうせSTLを使うならvectorでやりましょう // vectorは動的にサイズ変更される配列です vector<string> v; // stringのvectorを生成します // vectorに追加します v.push_back(s[0]); v.push_back(s[1]); // 文字列を直接指定してもかまいません v.push_back("GHI"); // 個数を確認します n = v.size(); cout << "vectorに" << n << "個入ってます" << endl; // vectorは配列同様 [] でアクセスできます // (ただし、範囲内でなければなりません。 // [] の場合は動的に拡張されません for (int i = 0 ; i < n; ++i) { cout << i << "番目の文字列 : " << v[i] << endl; } // newで確保したら自分で削除しなければなりません delete[] s; return 0; }

ya-cha
質問者

お礼

ご回答ありがとうございます!! 本当に丁寧に分かりやすくご説明いただき感謝感謝です♪ 参考にさせていただき、無事に行いたい事が実現できました!

その他の回答 (5)

  • BLK314
  • ベストアンサー率55% (84/152)
回答No.5

stringの簡単なサンプルです // string用ヘッダをインクルード // .hが付かないことに注意!! #include <string> #include <iostream> #include <stdio.h> // stringは名前空間stdで宣言されている // 「名前空間」がよくわからない場合は // stringを使うための「おまじない」 // と考えてください using namespace std; int main(int argc, char* argv[]) { // stringオブジェクトを宣言する // コンストラクタで初期化する string s1("ABC"); // 文字列を表示する cout << s1 << endl; // Cスタイルで取り出す例 // c_str()メソッドを使用する printf("Cスタイルでも %s と表示できる\n", s1.c_str()); // 比較してみよう // 今度は代入を使ってみます string s2; s2 = "DEF"; cout << "s2に代入" << endl; if (s1 == s2) { cout << "s1とs2は同じです" << endl; } else { cout << "s1とs2は異なります" << endl; } // コピーしてみる s1 = s2; cout << "s1にコピー" << endl; if (s1 != s2) { cout << "s1とs2は異なります" << endl; } else { cout << "s1とs2は同じです" << endl; } return 0; }

ya-cha
質問者

お礼

ご丁寧にありがとうございますm(__)m 配列[4][3200]のうち、[3200]を意識する必要がなくなる事は理解できました。 ただ、問題がございまして・・・ 配列要素は変数なので、動的に配列を作成する必要があります(記載してなくてすいませんでした)。 その場合、宣言はどのように行えば良いのでしょうか? 単純に string buf[変数名A][変数名B]; では、「error C2057: 定数式が必要です」とのエラーが 発生してしまいます・・・。

  • BLK314
  • ベストアンサー率55% (84/152)
回答No.4

newを使っているのでC++ですね。 C++でしたらSTLを使いましょう。 「標準」ですから・・・ STLには文字列を扱うstringが含まれます。 http://www.paw.hi-ho.ne.jp/takadayouhei/technic/28.html stringであれば長さを気に掛ける必要はないので 単にstring[4]を利用すれば済みます。 この程度だったらスタック上に確保しても良いと思うので newは不要になります。 文字列の比較も==や!=が使えます。 頭を悩ます問題を 根本から解決可能と考えますが・・・・ 如何でしょうか?

ya-cha
質問者

お礼

ご回答ありがとうございます。 すいません、Stringを使うと、宣言・比較・コピー処理はそれぞれどのような形になるのでしょうか?

回答No.3

1. > これで、buf[1]、buf[2]、buf[3]、buf[4]に、それぞれ3200のchar型の配列が宣言された事になりますでしょうか? なりません。長さ4のcharが32000個分メモリ確保されています。 buf[3200][4]です。 2. >これで比較出来ますでしょうか? できません。 質問1が間違っているので2も間違っています。 また別件でsizeof(tmp[i]); はtmpがbufと同じ作られ方をしているのであれば、 ポインタのサイズが返ってきます。配列のサイズは返ってきません。 3. 1が間違っているので当然間違いです。

ya-cha
質問者

補足

回答ありがとうございます。 >長さ4のcharが32000個分メモリ確保されています。 これは「3200」という事ですよね? また、 1.宣言と初期化について char **buf; buf = new char*[4]; for(int i=0; i < 4; i++) { buf[i] = new char[3200]; } という風に宣言すれば、buf[4][3200]になるのでしょうか? 「おかしい、間違っている」だけではなく、どこをどう修正すべきかを合わせてご回答いただきたいです・・・。

回答No.2

   こういうことかな?   #include <iostream> #include <cstring> int main() { char (*a)[4] = new char[10][4], (*b)[4] = new char[10][4]; for(int i = 0; i < 10; ++ i){ for(int j = 0; j < 4; ++ j){ a[i][j] = '0' + i; std::cout << a[i][j]; } std::cout << std::endl; } for(int i = 0; i < 10; ++ i) std::memcpy(b[i], a[i], sizeof a[i]); for(int i = 0; i < 10; ++ i){ for(int j = 0; j < 4; ++ j) std::cout << b[i][j]; std::cout << ' ' << std::memcmp(a[i], b[i], sizeof a[i]) << std::endl; } delete(a); delete(b); return 0; }

ya-cha
質問者

補足

ご回答ありがとうございます。 えっと・・・・どういう事なんでしょうか??? [4][3200]の配列の比較方法とコピーの方法、またそれを行うにあたり、必要な宣言の仕方をご教授していただきたいのですが、 yaemon_2006様の例では[10][4]の配列を要素ごとに比較・コピーしておられるのでしょうか??? 読み解けなくてすいません・・・

  • anicicle
  • ベストアンサー率36% (129/356)
回答No.1

Q1. いいえ。 char型の要素4の配列を3200確保している。 Q2. いいえ。 上記の通り。 Q3. いいえ。 上記の通り。 buf[]に格納される値は、newで確保したメモリの「先頭のアドレス」であり実体ではないからそのまま比較もコピーもできない。 また、newで確保しているメモリ領域は確保したサイズ分しか連続しない。

ya-cha
質問者

補足

ご回答ありがとうございます。 ただ、全て「いいえ」という事は「何もおかしくない」という事でしょうか? 比較したり中身を入れ替えたい場合は、宣言そのものの方法がおかしいという事なのでしょうか? 以上、よろしくお願いいたしますm(__)m

関連するQ&A