Variable length arrays depending on length of file C++
-
28-05-2021 - |
Вопрос
I'm encountering a problem trying to generalize my algorithm for any-size problems. The code is working for the test problem I used, but I had to insert manually the lenght of some arrays. Next, I've tried reading the lenght of input files in two variables, but then I'm not able to use them in all of my code, but just in some pieces. I think it's quite a stupid thing, but I'm really new to C++ and I'd like to get help. Here's the piece of code:
#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++;
}
}
....
As you can see, in the main() I count the lenght of input files into cont_prod and cont_slot variables, but then I can't use them in variable declaration. The variable lenght arrays I need have to be global variables 'cuz I need them also in other functions. And also cont_prod and cont_slot need to be global, as I need them in local variable declarations in some functions. Here is one of the functions I need to use them in:
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 is cont_prod and 360 is cont_slot. I'm programming on a Mac in Xcode and it says that variable lenght arrays cannot be declared at file scope, which I think it means as global variables. How can I manage that?
Решение
Perhaps declare pointers at file scope and allocate memory dynamically as and when you know the values...
Declare
int *slot
and allocate memory as
slot = new int[cont_slot];
and after using dont forget to "delete [] slot" it .. :)
Другие советы
Just focusing on your actual question here: in C++, you create variable length-arrays using std::vector
, like this:
std::vector<char> myCharArray( n * 1000 );
You can then use the expression
&myCharArray[0]
to use the vector object in all cases where you'd normally pass a raw C array.
Disclaimer: I didn't read the whole question, but it seems to me like you need either a dynamically allocated array:
float* distanze = new float[length];
or, better yet, a std::vector
:
std::vector<float> distanze; // <-- this is the proper C++ way
You can insert values in the vector via distanze.push_back(float)
and iterate through it just like it was an array, with operator []
.
For starters, you should learn to format your code.
Secondly, in C++, an array is normally declared with something like:
std::vector<float> anArray;
The declaraion using a []
is a left-over from C, and is only used in
very special cases (once you've fully mastered std::vector
). And a
vector will extend itself automatically if you use push_back
to insert
values. And an std::vector
carries its size around with it, so you
can iterator using:
for ( int i = 0; i != v.size(); ++ i ) {
// use `v[i]` here...
}
You can also iterate using iterators, which is more idiomatic in general (but perhaps not in the case where you are doing numerical work).
Finally, std::istream::eof()
is really only useful once input has
failed (to know whether the failure is due to end of file, or something
else). The usual idiom to read would be something like:
float value;
while ( contdist_file >> value ) {
distanze.push_back( value );
}
(I'm supposing that this is what you actually want in the first loop. In the code you've posted, you just read into a temporary variable, overwriting each time, but not otherwise doing anything with the value you read.)
Finally, unless your vectors may be very large, it's usual to use
double
in C++, rather than float
. (But this depends on the
total amount of data you need to handle, as well as the precision you
need.) Note too that a loop with:
Sp += slot[i];
will likely give very poor results if the size of slot
is large,
unless you're lucky with the values in slot
. If the values are in the
range of 0.5...1
, for example, after a couple of thousand values, with
float
, you only have about 3 or 4 decimal digits of precision, and if
the first value happens to be 10000000, any following values less than 1
are treated as zero. Typically, you need special algorithms to sum up
floating point sequences. (Using double
will improve things, but not
eliminate the problem.)