Writing to a different file depending on input value (ofstream)

Is there any way to write to a different file each time I change my input.

My piece of code is as follows:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
#include <stdio.h> 
#include <string.h>
#include <math.h>
#include <iostream>
#include <iomanip>
#include <fstream>
#include <time.h>
#include <stdlib.h>

using namespace std;

int main()
{

  int a,f,i,j,k,m,n,s;
  double p,Energy,energy,Distance,Length,DotProdForce,Forcemagnitude,ForceMagnitude[101],
         Force[101][4],E[10001],x[101][4],y[101][4];

  clock_t t1,t2;
  t1=clock();

  /*  set the number of points */
  n=100;

  /* check that there are no more than 100 points */
  if(n>100){
    cout << n << " is too many points for me :-( \n";
    exit(0);
  }
  
/* reset the random number generator */
  srand((unsigned)time(0));  
  
  for (i=1;i<=n;i++){
    x[i][1]=((rand()*1.0)/(1.0*RAND_MAX)-0.5)*2.0;
    x[i][2]=((rand()*1.0)/(1.0*RAND_MAX)-0.5)*2.0;
    x[i][3]=((rand()*1.0)/(1.0*RAND_MAX)-0.5)*2.0;
    
    Length=sqrt(pow(x[i][1],2)+pow(x[i][2],2)+pow(x[i][3],2));
    
    for (k=1;k<=3;k++){
      x[i][k]=x[i][k]/Length;
    }
  }

  /* calculate the energy */
  Energy=0.0;
  
  for(i=1;i<=n;i++){
    for(j=i+1;j<=n;j++){
      Distance=sqrt(pow(x[i][1]-x[j][1],2)+pow(x[i][2]-x[j][2],2)
		            +pow(x[i][3]-x[j][3],2));
      
      Energy=Energy+1.0/Distance;
    }
  }
  
  /* Save Original Points */
  for(i=1;i<=n;i++){
    y[i][1]=x[i][1];
    y[i][2]=x[i][2];
    y[i][3]=x[i][3];
  }
  
  /* Loop for random points m times*/
  m=10;
  
  if (m>100){
    cout << "The m="<< m << " loop is inefficient...lessen m \n";
    exit(0);
  }
  
  a=1;
  
  while(a<m){

    /* assign random points */
    for (i=1;i<=n;i++){
      x[i][1]=((rand()*1.0)/(1.0*RAND_MAX)-0.5)*2.0;
      x[i][2]=((rand()*1.0)/(1.0*RAND_MAX)-0.5)*2.0;
      x[i][3]=((rand()*1.0)/(1.0*RAND_MAX)-0.5)*2.0;
      
      Length=sqrt(pow(x[i][1],2)+pow(x[i][2],2)+pow(x[i][3],2));
    
      for (k=1;k<=3;k++){
        x[i][k]=x[i][k]/Length;
      }
    }

    /* calculate the energy */
    energy=0.0;
  
    for(i=1;i<=n;i++){
      for(j=i+1;j<=n;j++){
        Distance=sqrt(pow(x[i][1]-x[j][1],2)+pow(x[i][2]-x[j][2],2)
		              +pow(x[i][3]-x[j][3],2));
        
        energy=energy+1.0/Distance;
      }
    }
    
    if(energy<Energy)
      for(i=1;i<=n;i++){
        for(j=1;j<=3;j++){
          Energy=energy;
          y[i][j]=x[i][j];
        }
      }
    else
      for(i=1;i<=n;i++){
        for(j=1;j<=3;j++){
          energy=Energy;
          x[i][j]=y[i][j];
        }
      }
      
    a=a+1;
  }

  /* Output these points */
  ofstream Bestrandompoints ("Bestrandompoints");
  Bestrandompoints << "Energy=" << Energy << "\n";
  for(i=1;i<=n;i++){
    Bestrandompoints << x[i][1] << " " <<   x[i][2] << " " << x[i][3] << "\n";
  }
  Bestrandompoints.close(); 

  /* Start doing gradient flow approach */
  a=1;
  s=0;
  f=0;
  Forcemagnitude=1.0;

  if(n>80)
    p=0.005;
  else if(n>60)
    p=0.01;
  else if(n>40)
    p=0.02;
  else
    p=0.05;

  while(Forcemagnitude>0.00005){

    /* Reset initial force and energy change */

    for(i=1;i<=n;i++){ 
      Force[i][1]=0.0; 
      Force[i][2]=0.0; 
      Force[i][3]=0.0; 
    } 
    /* Calculate force on each particle */

    for(i=1;i<=n;i++){ 
      for(j=1;j<i;j++){
        
        Distance=sqrt(pow(x[i][1]-x[j][1],2)+pow(x[i][2]-x[j][2],2)
                      +pow(x[i][3]-x[j][3],2));
        Force[i][1]=Force[i][1]+((x[i][1]-x[j][1])/(pow((Distance),3))); 
        Force[i][2]=Force[i][2]+((x[i][2]-x[j][2])/(pow((Distance),3))); 
        Force[i][3]=Force[i][3]+((x[i][3]-x[j][3])/(pow((Distance),3))); 
      } 

      for (j=i+1;j<=n;j++){ 

        Distance=sqrt(pow(x[i][1]-x[j][1],2)+pow(x[i][2]-x[j][2],2)
                      +pow(x[i][3]-x[j][3],2));
        Force[i][1]=Force[i][1]+((x[i][1]-x[j][1])/(pow((Distance),3))); 
        Force[i][2]=Force[i][2]+((x[i][2]-x[j][2])/(pow((Distance),3))); 
        Force[i][3]=Force[i][3]+((x[i][3]-x[j][3])/(pow((Distance),3)));
      }
    }

    /* Add the force to my points */
    for(i=1;i<=n;i++){

      DotProdForce=Force[i][1]*x[i][1]+Force[i][2]*x[i][2]+Force[i][3]*x[i][3];
      
      y[i][1]=x[i][1];
      y[i][2]=x[i][2];
      y[i][3]=x[i][3];
    
      Force[i][1]=Force[i][1]-DotProdForce*y[i][1];
      Force[i][2]=Force[i][2]-DotProdForce*y[i][2];
      Force[i][3]=Force[i][3]-DotProdForce*y[i][3];

      x[i][1] = y[i][1]+p*(Force[i][1]);
      x[i][2] = y[i][2]+p*(Force[i][2]);
      x[i][3] = y[i][3]+p*(Force[i][3]);

      /* Bring it back onto sphere */
      
      Length=sqrt(pow(x[i][1],2)+pow(x[i][2],2)+pow(x[i][3],2));

      for (j=1;j<=3;j++){
        x[i][j]=x[i][j]/Length;
      }
    }
      
    /* Calculate the new energy */
    
    E[a]=0.0;
  
    for(i=1;i<=n;i++){
      for(j=i+1;j<=n;j++){
      
        Distance=sqrt(pow(x[i][1]-x[j][1],2)+pow(x[i][2]-x[j][2],2)
                      +pow(x[i][3]-x[j][3],2));
        E[a]=E[a]+1.0/Distance;
      }
    }

    energy=E[a];

    /* Choose best energy and therefore best points */
    if (energy<Energy)
      Energy=energy,s=s+1;
    else
      energy=Energy,f=f+1,p=(9.5*p)/10;
 
    cout << fixed << setprecision(10) << "p=" << p << "\n";
 
    for(i=1;i<=n;i++){
      ForceMagnitude[i]=pow((pow(Force[i][1],2)+pow(Force[i][2],2)
                             +pow(Force[i][3],2)),0.5);
    }

    for(i=1;i<=n-1;i++){
      if(ForceMagnitude[i]<ForceMagnitude[i+1])
        ForceMagnitude[i]=ForceMagnitude[i+1];
      else
        ForceMagnitude[i+1]=ForceMagnitude[i];
    }

    Forcemagnitude=ForceMagnitude[n];
    
    cout << setprecision(10) << "FM=" << Forcemagnitude << "\n";
    
    a=a+1;
  }

  /* Output new energy */
  cout << "Successes=" << s << " Failures=" << f <<"\n";
  cout << fixed << setprecision (20) << "Energy=" << Energy << "\n";
  cout << "Iterations=" << a-1 << "\n";

  ofstream mypoints ("mypoints");
  for(i=1;i<=n;i++){
    mypoints << x[i][1] << " " <<   x[i][2] << " " << x[i][3] << "\n";
  }
  mypoints.close(); 

  t2=clock();
    float diff ((float)t2-(float)t1);
    float seconds = diff / CLOCKS_PER_SEC;
    cout << setprecision(2) << "Run time: " << seconds << "(s)" << "\n";
    return 0;

}


I want to change it slightly around lines 121-126 and 247-251 so that every time I change n on line 23 I get a new file being made. Currently if I were to run this for n=10, it would do what I want it to, but as soon as I run it again those files would be replaced. Can I write something along the lines of:

1
2
3
4
5
ofstream mypoints[n] ("mypoints[n]");
  for(i=1;i<=n;i++){
    mypoints[n] << x[i][1] << " " <<   x[i][2] << " " << x[i][3] << "\n";
  }
  mypoints[n].close();


To give me a new file (different name, so the name changes every time n does) every time I manually change n instead of having to manually change n and the name of the files every time I want to run the code for a new n?

Note: I realise the code above with mypoints[n] in it isn't the answer, it was just to explain what I meant.

Is there a way to do this using ofstream or something else?

Thanks, A.
Hi there,

I think what you suggested is actually more or less possible, using some tweaking.
Create a stringstream that holds the name, add the number to it and pass the underlying string to the ofstream constructor:

1
2
3
4
5
6
#include <sstream>

std::isstringstream iss("mypoints_"); //create stringstream
iss << n;  //add number

std::ofstream ofs(iss.str());  //pass unerlying string to the ofstream constructor 


Hope that helps.

All the best,
NwN
I am sorry NwN but I just don't know how to include that in my code. I have a very basic knowledge of C++ and don't really understand what you have said here. Could you explain what you have done a bit so I can try and implement it.

What I get so far is:
I must use a stringstream as this is used to let strings be treated as streams.
I don't know what the command isstringstream does but am currently reading about it trying to figure it out.

Thanks, A.

Edit: Sorry, I guess this was a typo? did you mean istringstream?
If so I have gotten something like this so far (bear in my I suck at coding so don't judge me) but I don't really know what is going on and I am definitely doing something really wrong:

1
2
3
4
5
6
7
8
9
10
   /* Output these points by creating string stream */
  istringstream iss("Bestrandompoints_");
  iss << n;  //add number

  ofstream Bestrandompoints ("iss.str()");
  Bestrandompoints << "Energy=" << Energy << "\n";
  for(i=1;i<=n;i++){
    Bestrandompoints << x[i][1] << " " <<   x[i][2] << " " << x[i][3] << "\n";
  }
  Bestrandompoints.close(); 


or something like this?:
1
2
3
4
5
6
7
8
9
10
11
/* Create string stream 1 */
  istringstream Stream1("Bestrandompoints_");
  Stream1 << n;  //add number

  /* Output points to first file, named "Bestrandompoints_n */
  ofstream File1 ("Bestrandompoints");
  File1 << "Energy=" << Energy << "\n";
  for(i=1;i<=n;i++){
    File1 << x[i][1] << " " <<   x[i][2] << " " << x[i][3] << "\n";
  }
  File1.close(); 
Last edited on
He should have used std::ostringstream instead of std::istringstream. If you set some string content with the constructor you will have to seek to the end of the stream, otherwise you will overwrite the string in future write operations.
1
2
std::ostringstream oss("mypoints_", std::ios::ate);
oss << n;

If you set the string with operator<< you don't need to seek.
1
2
std::ostringstream oss;
oss << "mypoints_" << n;


Last edited on
So how do I put this into my code?? Do I swap out lines 120-126 for these:

1
2
3
4
5
6
7
8
9
10
11
 /* Create string stream 1 */
  ostringstream oss;
  iss << "Bestrandonpoints_" << n;  //add number

  /* Output these points */
  ofstream File1 ("Bestrandompoints");
  File1 << "Energy=" << Energy << "\n";
  for(i=1;i<=n;i++){
    File1 << x[i][1] << " " <<   x[i][2] << " " << x[i][3] << "\n";
  }
  File1.close(); 


or something like that?? I don't really get what I am doing here as you can probably tell. A little more explanation would go a long way if you are willing to spare the time.

Thanks, A.
std::ostringstream is used to build strings. On line 2 you have created a std::ostringstream object named oss. On line 3 you should use this object so replace iss with oss. std::ostringstream works much the same way as std::ofstream and std::cout. The difference is where the output goes to. To get the content that you have written to it, as a string, you use the str() member function. This will pass the string directly to the std::ofstream constructor: ofstream File1(oss.str());
Thanks for the explanation. From what you have said I think this is what I should be doing:

1
2
3
4
5
6
7
8
9
10
11
/* Create string stream 1 */
  ostringstream oss;
  oss << "Bestrandonpoints_" << n;  //add number

  /* Output these points */
  ofstream File1 (oss.str());
  File1 << "Energy=" << Energy << "\n";
  for(i=1;i<=n;i++){
    File1 << x[i][1] << " " <<   x[i][2] << " " << x[i][3] << "\n";
  }
  File1.close(); 


However when I do this it says:

no matching function for call to ‘std::basic_ofstream<char, std::char_traits<char> >::basic_ofstream(std::basic_string<char, std::char_traits<char>, std::allocator<char> >)’
/usr/include/c++/4.2.1/fstream:596: note: candidates are: std::basic_ofstream<_CharT, _Traits>::basic_ofstream(const char*, std::_Ios_Openmode) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/include/c++/4.2.1/fstream:580: note: std::basic_ofstream<_CharT, _Traits>::basic_ofstream() [with _CharT = char, _Traits = std::char_traits<char>]
/usr/include/c++/4.2.1/iosfwd:92: note: std::basic_ofstream<char, std::char_traits<char> >::basic_ofstream(const std::basic_ofstream<char, std::char_traits<char> >&)

which I would take as either the oss string has not been built, or when trying to output the file, oss is not being recognised as the string to call upon?? (Just guessing here). Do you know what the issue is or how I fix it??

Thanks, A.
The problem is that older compilers doesn't allow you pass a std::string to the std::ofstream constructor. You can use the c_str() member function to get a C string (const char*) from the std::string.
ofstream File1(oss.str().c_str());
Awesome, thank you!

So in the end I have this:

1
2
3
4
5
6
7
8
9
10
11
 /* Create string stream 1 */
  ostringstream oss;
  oss << "Bestrandonpoints_" << n;  //add number

  /* Output these points */
  ofstream File1 (oss.str().c_str());
  File1 << "Energy=" << Energy << "\n";
  for(i=1;i<=n;i++){
    File1 << x[i][1] << " " <<   x[i][2] << " " << x[i][3] << "\n";
  }
  File1.close(); 


Which works perfectly!
Topic archived. No new replies allowed.