2011-07-26 9 views
0

いくつかの名前を多次元配列にコピーし、配列の内容を出力してから、メモリの割り当てを解除して終了するスクリプトを作成しています。私が抱えている問題は、スクリプトを実行すると入力した姓だけが表示されることです。ここに私がしたことがあります。どんな助けも素晴らしいだろう!前もって感謝します!セグメンテーションフォルトを生成するC++多次元配列?

#include <iostream> 
#include <string.h> 

using namespace std; 

void createArray(int n); 
void addDetail(char*& name, char*& surname); 
void printArray(); 
void clear(); 

char ***details; 
int used; 
int size; 

int main() 
{ 
    createArray(3); 

    char* tmpName = new char[20]; 
    char* tmpSurName = new char[120]; 

    strcpy(tmpName, "nameA"); 
    strcpy(tmpSurName, "surnameA"); 
    addDetail(tmpName,tmpSurName); 

    strcpy(tmpName, "nameB"); 
    strcpy(tmpSurName, "surnameB"); 
    addDetail(tmpName,tmpSurName); 

    strcpy(tmpName, "nameC"); 
    strcpy(tmpSurName, "surnameC"); 
    addDetail(tmpName,tmpSurName); 

    clear(); 
    return 0; 
} 

void createArray(int n) 
{ 
    details= new char**[n]; 
    for(int i=0; i<n; i++) 
     details[i] = new char*[2]; 
    size = n; 
    used = 0; 
} 

void addDetail(char*& name, char*& surname) 
{ 
    if(occupation < size) 
    { 
     details[used][0] = name; 
     details[used][1] = surname; 
     used++; 
    }else{ 
     cout << "Array Full " << endl; 
    } 
} 

void printArray() 
{ 
    for(int i=0; i<used; i++) 
     cout << details[i][0] << " " << details[i][1] << endl; 
} 

void clear() 
{ 
    for(int i=0; i<size; i++) 
    { 
     delete [] details[i]; 
     details[i] = 0; 
    } 
    delete [] details; 
    details=0; 
} 
+0

なぜあなたは**文字列**を使用していませんか? – DumbCoder

+1

もしあなたがC++を使っているのであれば、* old skool * Cスタイルのイディオムの代わりに 'string'と' vector'を使ってみてはどうでしょうか? –

答えて

1

あなたはdetails[used][0]details[used][1]用のメモリを割り当てることができませんでしたので、ランダムなアドレスがこれらの場所にあったものは何でも使用しています。

これはC++なので、おそらく代わりに文字列を使用できますか? std::string **details;。これはメモリがリークすることを除いて、既存のコードで動作するはずです。

さらに良いことに、ベクターのベクターを使用することです。

ような何か: std::vector<std::vector<std::string> > details;

その後createArray機能は完全に離れて行くことができるとaddDetailが簡単になる:

std::vector<string> newName; 
newName.push_back(name); 
newName.push_back(surname); 
details.push_back(newName); 
+0

クイック返信ありがとう:)私はそれが動作すると確信しています...しかし、それは我々がここにすべての機能を持っているという要件です。 char ***の詳細を使用しています。 XD。私は自分の持っているものを使ってこの作品を作ることができますか?私は詳細についてのメモリの割り当て方法を完全に理解していません[0] ...私はcreateArray()でこれをしたと思いますか? – Tim

0

たびに、あなたが効果的にポインタtmpNameを格納し、tmpSurNameでいるので、それがあります配列details。次の反復では、tmpNametmpSurNameが指し示すメモリの内容を上書きするので、最後に姓/姓n回のリストがあります。

解決するには、の前にtmpNameとtmpSurNameを再割り当てし、それぞれ addDetailを呼び出す必要があります。

Btw、なぜあなたは(ewww)char***を使用する必要がありますか。 STL?

0

これは、配列に文字列を追加していないということです。名前と姓のポインタを追加しています。すべてのインスタンスがその変数を指しているので、配列に何が含まれているのかを尋ねると、最後の値のみを含む名前と姓が要求されます。

また、この配列は、動作させたいと思っていますか?配列は...具体的なものです。あなたが本質的に言っているのは、「私はこれらの5つを望んでいる、彼らはあなたが入れたタイプに基づいてこの大きなものになります」と、コンピュータは静かに「うーん、私はここにそれらのためのスペースを置いておきます。 "あなたのコードがそれらの名前をそこに置くとき、どこにそれらを格納するかに関する準備は本当にありません。あなたがそのスペースをいっぱいにして、あなたを越えれば、悪い場所に行きます。それで、あなたがしなければならないのは、最後の* char *をchar [120]へのポインタにして、あなたが(少なくともあなたの目的のために)決して満たされないことを知ることです。外部配列を作成した後は、createArray関数でそれを行います。

+0

ああ、私は見る!さて、それはクールだが、今私はどのように修正するのですか?私が名前/名字を逆参照すると、それは私にエラーを与える? – Tim

+0

@Tim私は少しでもC++をやっていないので、私のポインタのスキルは少し錆びています。しかし、行 "void addDetail(char *&name、char *&surname)"では、これらのアンパサンドが参照変数を作成しています。あなたはそれらを削除しようとする可能性がありますが、私は100%ではないので、配列がまだ関与している(配列はポインタです)。私はchar *を管理する必要があったので、それは長い時間でした。また、あなたがエラーを投稿した場合に私たちが(将来的に)役立つので、何が起こっているのか正確に知ることができます。私は、Reference Variablesを重要であると研究することを提案し、私が参照した行が何を意味するのかを知っておくべきです。 – StephenT

+0

私の更新された答えをチェックしてください。 – StephenT

0

アレイ内の各エントリに対して新しいバッファを作成するのではなく、一時バッファを上書きし続けます。その結果、バッファに書き込まれた最後のデータだけが存続します。

このサンプルにはいくつかの問題があるかもしれませんが、これを修正するための方法の大まかなガイドがあります。私はこれをコンパイルまたはテストしようとしませんでした。

メインのこの部分は、addDetailに属します:

char* tmpName = new char[20]; 
char* tmpSurName = new char[120]; 

strcpy(tmpName, "nameA"); 
strcpy(tmpSurName, "surnameA"); 

だから、あなたの新しいaddDetailは次のようになります。

void addDetail(char*& name, char*& surname) 
{ 
    if(occupation < size) 
    { 
     details[used][0] = new char[20]; 
     details[used][1] = new char[120]; 
     strcpy(details[used][0], name); 
     strcpy(details[used][1], surname); 
     used++; 
    }else{ 
     cout << "Array Full " << endl; 
    } 
} 

そして、それは、メイン等から呼び出されます:

addDetail("nameA", "surnameA"); 

addDetailで行われた割り当てを適切にクリーンアップするには、clearを更新する必要があります。