Массивы переменной длины в зависимости от длины файла C ++ - PullRequest
0 голосов
/ 02 апреля 2012

Я столкнулся с проблемой, пытаясь обобщить мой алгоритм для задач любого размера.Код работает для тестовой задачи, которую я использовал, но мне пришлось вручную вставить длину некоторых массивов.Затем я попытался прочитать длину входных файлов в двух переменных, но затем я не смог использовать их во всем своем коде, но только в некоторых частях.Я думаю, что это довольно глупо, но я действительно плохо знаком с 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 должны быть глобальными, так как они нужны в объявлениях локальных переменных в некоторых функциях.Вот одна из функций, в которых я должен их использовать:

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.Я программирую на Mac в Xcode, и он говорит, что массивы переменной длины не могут быть объявлены в области видимости файла, что, я думаю, означает глобальные переменные.Как я могу справиться с этим?

Ответы [ 4 ]

1 голос
/ 02 апреля 2012

Сосредоточив внимание на вашем актуальном вопросе здесь: в C ++ вы создаете массивы переменной длины, используя std::vector, например:

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

Затем вы можете использовать выражение

&myCharArray[0]

для использования векторного объекта во всех случаях, когда вы обычно передаете необработанный массив C.

1 голос
/ 02 апреля 2012

Возможно, объявлять указатели в области видимости файла и динамически распределять память, как и когда вы знаете значения ...

Объявить

   int     *slot

и выделить память как

slot = new int[cont_slot];

и после использования не забудьте "удалить [] слот" это ..:)

1 голос
/ 02 апреля 2012

Отказ от ответственности: я не прочитал весь вопрос, но мне кажется, что вам нужен либо динамически распределенный массив:

float* distanze = new float[length];

или, еще лучше, std::vector:

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

Вы можете вставить значения в вектор с помощью distanze.push_back(float) и выполнить итерацию по нему так же, как это был массив, с operator [].

0 голосов
/ 02 апреля 2012

Для начала, вы должны научиться форматировать ваш код.

Во-вторых, в C ++ массив обычно объявляется примерно так:

std::vector<float> anArray;

Объявление с использованием []является остатком от 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 );
}

(я полагаю, это то, что вы на самом деле хотите в первом цикле. В опубликованном вами коде вы просто читаете во временныйпеременная, перезаписывается каждый раз, но никак иначе не делает ничего с прочитанным значением.)

Наконец, если ваши векторы могут быть очень большими, обычно в C ++ используется double вместо float.(Но это зависит от общего объема данных, которые вам нужно обработать, а также от точности, которая вам нужна.) Обратите внимание, что цикл с:

Sp += slot[i];

, вероятно, даст очень плохие результаты, если размерslot большое, если вам не повезло со значениями в slot.Если значения находятся в диапазоне 0.5...1, например, после пары тысяч значений с float, у вас будет только около 3 или 4 десятичных цифр точности, и если первое значение будет 10000000, любоеследующие значения меньше 1 рассматриваются как ноль.Как правило, вам нужны специальные алгоритмы для суммирования последовательностей с плавающей запятой.(Использование double улучшит ситуацию, но не устранит проблему.)

...