-2

任意のサイズの問題に対してアルゴリズムを一般化しようとして問題が発生しています。コードは私が使用したテスト問題に対して機能していますが、いくつかの配列の長さを手動で挿入する必要がありました。次に、入力ファイルの長さを 2 つの変数で読み取ろうとしましたが、すべてのコードでそれらを使用することはできず、いくつかの部分でしか使用できません。ばかげていると思いますが、私は C++ にまったく慣れていないので、助けてもらいたいと思っています。コードの一部は次のとおりです。

#include <fstream>
#include <iostream>
#include <time.h>



using namespace std;

struct node{
int     last_prod;
int     last_slot;
float   ZL;
float   ZU;
float   g;
bool fathomed;
node *next;
node *padre;
node *primofiglio;
};

clock_t start, end;
double cpu_time_used;


int l=0;
int cont_slot=0;
int cont_prod=0;
float temp_cont;

float   distanze[360];                                // dichiarazione variabili
int     slot[111];
int     slot_cum[111];
float   COIp[111];
int     domanda[111];
float   Zb=9999999999999999;                            
float   LowerBound(struct node *n);
float   UpperBound(struct node *n);
float   h(struct node *l,struct node *n);
void    creasottolivello(struct node *n);
void    fathRule2(struct node *n);
void    fathRule3(struct node *n);
void    stampaRisultati(struct node *n, ofstream &f);
int     unFathomedNodes(struct node *n);
void    append(struct node* temp, struct node* n);
void    ricercaOttimo(struct node *n, ofstream &f);
void    calcoloBounds(struct node *n);

int main(){

start = clock();

ifstream contdist_file ( "/Users/MarcoBi/Desktop/TESI di LAUREA/Xcode/dati/distanze.txt"     );  // conteggio dati input


if ( !contdist_file.is_open() ) {                   //conta righe file slot
}
else {
    for(int i=0; !contdist_file.eof(); i++){
        contdist_file >> temp_cont;
        cont_slot++;
    }
}

ifstream contslot_file ( "/Users/MarcoBi/Desktop/TESI di LAUREA/Xcode/dati/slot.txt" );

if ( !contslot_file.is_open() ) {                  //conta righe file prodotti
}
else {
    for(int i=0; !contslot_file.eof(); i++){
        contslot_file >> temp_cont;
        cont_prod++;
    }
}
....

ご覧のとおり、main() では、入力ファイルの長さを cont_prod 変数と cont_slot 変数にカウントしていますが、変数宣言ではそれらを使用できません。必要な可変長配列はグローバル変数でなければなりません。他の関数でもそれらが必要だからです。また、cont_prod と cont_slot は、一部の関数のローカル変数宣言で必要になるため、グローバルである必要があります。これらを使用する必要がある関数の 1 つを次に示します。

float LowerBound(struct node *n){                //funzione LowerBound
int S[111];
int Sp=0;
float d[111];
float dmin[111];
float D;
float LB;

for(int i=n->last_prod;i<111;i++){
    Sp=Sp+slot[i];
}
for(int i=0;i<111;i++){                     //Calcolo S_pigreco
    S[i]=0;
}

if(n->last_prod==0){                         //condizione necessaria per nodo radice
    S[0]=slot[0];    
    for(int i=n->last_prod +2;i<111;i++){
        for(int j=n->last_prod +1;j<=i;j++){
            S[j]=S[j-1]+slot[j];
        }
    }
}
else{
    for(int i=n->last_prod +1;i<111;i++){
        for(int j=n->last_prod;j<=i;j++){
            S[j]=S[j-1]+slot[j];

        }
    }  
}
S[110]=S[109] + slot[110];

//calcolo somma distanze da slot j+1 a q
for(int i=0;i<111;i++){
    d[i]=0;
}

for(int j=n->last_prod;j<111;j++){
    for(int i=n->last_slot; i < n->last_slot +S[j]; i++){
        d[j]=d[j]+distanze[i];
    }
}

//calcolo dmin_pigreco
for(int i=n->last_prod; i<111; i++){
    dmin[i]= d[i]/S[i];
}

D=0;
for(int i=n->last_prod; i<111; i++){
    D=D+dmin[i]*domanda[i];
}
LB=n->g+2*D;                                           
return LB;                                 
}

111 は cont_prod で、360 は cont_slot です。私は Xcode で Mac でプログラミングしていますが、可変長配列はファイル スコープで宣言できないと書かれています。これは、グローバル変数を意味していると思います。どうすればそれを管理できますか?

4

4 に答える 4

2

ここで実際の質問に焦点を当てます: C++ では、次のように を使用して可変長配列を作成しますstd::vector

std::vector<char> myCharArray( n * 1000 );

その後、式を使用できます

&myCharArray[0]

通常は生の C 配列を渡すすべてのケースで vector オブジェクトを使用します。

于 2012-04-02T10:44:18.860 に答える
1

免責事項:質問全体を読んだわけではありませんが、動的に割り当てられた配列が必要なようです:

float* distanze = new float[length];

または、さらに良いことに、 a std::vector:

std::vector<float> distanze; // <-- this is the proper C++ way

を介してベクトルに値を挿入しdistanze.push_back(float)、配列のように繰り返し処理できますoperator []

于 2012-04-02T10:43:52.743 に答える
1

おそらく、ファイルスコープでポインターを宣言し、値がわかっているときにメモリを動的に割り当てます...

宣言する

   int     *slot

そしてメモリを次のように割り当てます

slot = new int[cont_slot];

使用後は「[]スロットを削除」することを忘れないでください.. :)

于 2012-04-02T10:47:31.097 に答える
0

手始めに、コードのフォーマットを学ぶ必要があります。

次に、C++ では、配列は通常次のように宣言されます。

std::vector<float> anArray;

a を使用する宣言[]は C からの残り物であり、非常に特殊な場合にのみ使用されます (完全に習得した場合std::vector)。push_backを使用して値を挿入すると、ベクトルは自動的に拡張されます。そして、std::vectorそのサイズを持ち運ぶので、次を使用してイテレータを実行できます。

for ( int i = 0; i != v.size(); ++ i ) {
    //  use `v[i]` here...
}

イテレータを使用して反復することもできますが、これは一般的により慣用的です (ただし、数値計算を行っている場合はおそらくそうではありません)。

最後に、std::istream::eof()入力が失敗した場合にのみ実際に役立ちます (失敗がファイルの終わりによるものか、それ以外によるものかを知るため)。通常のイディオムは次のようになります。

float value;
while ( contdist_file >> value ) {
    distanze.push_back( value );
}

(これが最初のループで実際に必要なものだと思います。投稿したコードでは、一時変数に読み取り、毎回上書きしますが、それ以外の場合は、読み取った値で何もしません。)

最後に、ベクトルが非常に大きくない限り、通常 doublefloat. (ただし、これは、処理する必要があるデータの総量と、必要な精度によって異なります。) 次のようなループにも注意してください。

Sp += slot[i];

slotの値で幸運でない限り、 のサイズが大きい場合、非常に悪い結果が得られる可能性がありますslot。値が の範囲内にある場合0.5...1、たとえば、数千の値の後、 を使用すると float、小数点以下 3 桁または 4 桁の精度しかありません。最初の値がたまたま 10000000 である場合、1 未満の後続の値はすべてゼロとして扱われます。通常、浮動小数点数列を合計するには特別なアルゴリズムが必要です。(使用doubleすると改善されますが、問題がなくなるわけではありません。)

于 2012-04-02T11:24:07.083 に答える