Create loop to write multiple files in C++? - c++

Let's say I have a program that does the follow:
for (i=1; i<10; i++)
{
computeB(i);
}
where the computeB just outputs a list of values
computeB(int i)
{
char[6] out_fname="output";
//lines that compute `var` using say, Monte Carlo
string fname = out_fname + (string)".values";
ofstream fout(fname.c_str());
PrintValue(fout,"Total Values", var);
}
From another file:
template <class T>
void PrintValue(ofstream & fout, string s, T v) {
fout << s;
for(int i=0; i<48-s.size(); i++) {
fout << '.';
}
fout << " " << v << endl;
}
Before implementing that loop, computeB just outputted one file of values. I now want it to create multiple values. So if it originally created a file called "output.values", how can I write a loop so that it creates "output1.values", "output2.values", ..., "output9.values"?
EDIT: I forgot to mention that the original code used the PrintValue function to output the values. I originally tried to save space and exclude this, but I just caused confusion

Disregarding all the syntax errors in your code ...
Use the input value i to compute the output file name.
Use the file name to construct an ofstream.
Use the ofstream to write var to.
Here's what the function will look like:
void combuteB(int i)
{
char filename[100];
sprintf(filename, "output%d.values", i);
ofstream fout(filename);
fout << "total values";
fout << " " << var << endl; // Not sure where you get
// var from. But then, your
// posted code is not
// exactly clean.
}

You can use std::to_string() to convert from an int to a string:
void computeB(int i)
{
if (std::ofstream fout("output" + std::to_string(i) + ".values"))
fout << "total values" << " " << var << '\n';
else
throw std::runtime_error("unable to create output file");
}

Related

Iteratively accessing and writing to multiple files using ofstream

I have a pair of header files. Within IsingModel.h, publically I declare:
ofstream logfile1;
ofstream logfile2;
Then to open the relevant files (logfile1 and logfile 2 have different names) I use:
do {
name2.str(""); //reset name stringstream
n++; //increase n value
name2 << "output_" << gridSize << "_" << seed << "_" << n << "_eqmCalc.txt"; //stream created
} while (if_exist(name2.str())); //test if file already exists
logfile2.open(name2.str());
Which works in creating the file. Then, throughout the code I use the ofstreams to act on the files, for example:
logfile1 << counter << " " << calcM() << " " << calcE() << endl;
This is fine for actions that are independent for each file, however when I call the destructor I want to write the same standard information to each file. To that end, I am experimenting with iteratively writing to the files and it does not seem to work:
void IsingSystem::test() {
for (int i = 1; i = 2; i++) {
if (ofstream("logfile" + to_string(i)).is_open); {
ofstream("logfile" + to_string(i)) << "success" << endl;
}
}
}
This instead creates files called logfile1 and logfile2. As an alternative, I tried to create an array of ofstreams:
void createFileHandles() {
const int count = 2;
std::ofstream logfile[count];
}
But, I could not work out how to pass this between functions properly.
What is the proper way of handling ofstreams so that I can have multiple files open, writing different instructions to them simultaneously but also have some actions that happen to both?
You can have a vector of ofstream
vector<ofstream> ofstreams(2);
//fill vec
for (int i = 0; i < 2; i++)
{
if (ofstreams[i].is_open);
{
ofstreams[i]<< "success" << endl;
}
}
You can then pass ofstreams to functions.

Dynamic array of structs

I have such piece of code:
typedef struct reader
{
char name[50];
char card_num[50];
char title[100];
}reader_t;
int main()
{
vector<reader> vec;
ifstream input_file("D:\\lab.txt", ios::binary);
reader_t master[1];
input_file.read((char*)&master, sizeof(master));
for (size_t idx = 0; idx < 1; idx++)
{
reader temp;
strcpy(temp.name, master[idx].name);
strcpy(temp.card_num, master[idx].card_num);
strcpy(temp.title, master[idx].title);
vec.push_back(temp);
cout << "Name: " << master[idx].name << endl;
cout << "Card num: " << master[idx].card_num << endl;
cout << "Title: " << master[idx].title<<endl;
}
cout << vec.size();
getchar();
}
What is does: it reads structures from binary file into an array of structures,copies them into vector and displays structure.And yes, I do need to do like this - I need to store structures from file in vector and this is the only working way to do it I could find(if you can tell, how to read structures to vector directly from file - you are welcome).
So,everything works fine, but the problem is that I need to create a function which would be able to do the same, but with dynamic array.I wrote something like this:
void read_structs(int vec_size)
{
ifstream input_file("D:\\lab.txt", ios::binary);
//Here I commented 2 ways how I tried to create a dynamic array of structs
//reader* master = new reader[vec_size];
//reader* master = (reader*)malloc(sizeof(reader) * vec_size);
input_file.read((char*)&master, sizeof(master));
for (size_t idx = 0; idx < vec_size; idx++)
{
reader temp;
strcpy(temp.name, master[idx].name);
strcpy(temp.card_num, master[idx].card_num);
strcpy(temp.title, master[idx].title);
vec.push_back(temp);
cout << "Name: " << master[idx].name << endl;
cout << "Card num: " << master[idx].card_num << endl;
cout << "Title: " << master[idx].title<<endl;
}
}
And that worked fine too unless I tried to run it.VS wasn't higlighting error in my code, it just was throwing an exception right as the moment when the program tried to access master[0].name.
There is absolutely no point in the temp struct. See, the
vec.push_back(temp);
is already using copy constructor, so copy constructor must work and then the set of strcpy is not doing anything different from that, so just go with
vec.push_back(master[0]).
You can't read into vector directly. You do need to read into temporary. So that is correct. Except I suppose you want to read all entries from the file no matter how many of them there are, so you need to put the read itself also into the loop.
There is not much point in creating an array of one element.
reader_t master[1];
input_file.read((char*)master, sizeof(master));
// ^ you *don't* need & here, arrays degrade to pointers automatically
and
reader_t master;
input_file.read((char *)&master, sizeof(master));
// ^ but you do need & here.
are equivalent. I would go with the later.
So we are basically down to:
reader temp; // calling it temp; the master name makes no sense.
while (input_file.read((char*)&temp, sizeof(temp)))
// read returns input_file and input_file is false if last operation failed
{
vec.push_back(temp);
// verify the stored values by reading back vfrom vec.back().
cout << "Name: " << vec.back().name << endl;
cout << "Card num: " << vec.back().card_num << endl;
cout << "Title: " << vec.back().title<<endl;
}
In the second example, you didn't initialize master, so it obviously crashed.
There is a more C++ approach though. First, you define a read operator for the structure:
std::istream &operator>>(std::istream &in, reader &r) {
return in.read((char *)&r, sizeof(r));
}
and then you simply read the vector using the istream_iterator:
vec.assign(std::istream_iterator<reader>(input_file),
std::istream_iterator<reader>());
and the standard library will generate the above loop for you.

C++ How to create a function writing data in file for multiple use with different names

I have some data in an array which is manipulated in about five or six steps. After each step I want the program to write a file with the manipulated data. This is the working code for that:
ofstream mirroreddata("mirroreddata.dat", ios::out);
for (int i = 0; i < n_values; i++)
{
mirroreddata << datavector[i] << "\n";
}
mirroreddata << endl;
mirroreddata.close();
The problem is, that I don't want to write this thing multiple times. I want to create a function I just have to call with the name of the file (here: mirroreddata) and n_values and the datavector. Giving the function the datavector and n_values is no problem, but how to tell her writing the data in a new file? This is the code fragment for this but it is not right:
void CreateDataOutputFile(int n_values, double* datavector)
{
ofstream mirroreddata("mirroreddata.dat", ios::out);
for (int i = 0; i < n_values; i++)
{
mirroreddata << datavector[i] << "\n";
}
mirroreddata << endl;
}
So how to call this but writing data in a new file (for example the smoothed data in file "smoothed")?
Thanks for your answers
Easy: add another parameter for the filename:
#include <string>
void CreateDataOutputFile(int n_values, double* datavector, const std::string& fname)
{
ofstream mirroreddata(fname, ios::out);
for (int i = 0; i < n_values; i++)
{
mirroreddata << datavector[i] << "\n";
}
mirroreddata << endl;
}

how to access images in sequence using loop in openCV

Guys i ran into a problem regarding accessing images in sequential order. i have images whose names change with incrementing number i.e. cube_0.jpg, cube_1.jpg, .... and so on. Now i want to access each image one-by-one and show.
Following is my code that i am playing with since 2-days and don't know how to handle this situation or what is wrong with this problem.
ostringstream s;
for (int fileNumber = 0; fileNumber<=40; fileNumber++)
{
s<<"\"cube_"<<fileNumber<<"\.jpg\""<<endl;
string fullfileName(s.str());
images[i] = fullfileName;
}
stringstream ss;
cout<<"file name"<<images[0]<<endl;
for (int file = 0; file<41; file++)
{
string str = images[file];
cout<<"str "<<str<<endl;
img_raw = imread(ss.str(), 1); // load as color image Error
cout<<"Done"<<endl<<"size"<<img_raw.size();
system("pause");
}
This code runs fine till it gets reached to "img_raw = imread(ss.str())", now this line is basically hindering me from accessing file. Since imread requires "string& filename" therefore i performed stringstream operation but nothing is working!
Any help would be greatly appreciated!
There are a few errors.
Your stringstream ss is empty. You declared it but did not fill with any values. I am pretty sure you meant imread(str, 1); instead of imread(ss.str(), 1);
In the first for loop, you are continuously printing filenames to ostringstream, so it goes like this:
0: "cube_0.jpg\"
1: "cube_0.jpg\""cube_1.jpg\"
2: "cube_0.jpg\""cube_1.jpg\""cube_2.jpg\"
...
so the ostringstream just grows and grows. ostringstream needs to be declared in the loop to be cleared for every iteration.
Edited code:
string images[41];
Mat img_raw;
for (int fileNumber = 0; fileNumber < 41; fileNumber++)
{
stringstream ss;
ss << "\cube_" << fileNumber << "\.jpg" << endl;
string fullfileName;
ss >> fullfileName;
images[fileNumber] = fullfileName;
}
for (int file = 0; file < 41; file++)
{
cout << "Loading " << images[file] << endl;
img_raw = imread(images[file], 1);
if (!img_raw.empty())
{
cout << "Successfully loaded " << images[file] << " with size " << img_raw.size() << endl;
}
else
{
cout << "Error loading file " << images[file] << endl;
}
system("pause");
}

Accessing a pointer to a vector c++

Im having trouble accessing the following vector. Im new to vectors so this is probably a small syntactical thing i've done wrong. here is the code....
void spellCheck(vector<string> * fileRead)
{
string fileName = "/usr/dict/words";
vector<string> dict; // Stores file
// Open the words text file
cout << "Opening: "<< fileName << " for read" << endl;
ifstream fin;
fin.open(fileName.c_str());
if(!fin.good())
{
cerr << "Error: File could not be opened" << endl;
exit(1);
}
// Reads all words into a vector
while(!fin.eof())
{
string temp;
fin >> temp;
dict.push_back(temp);
}
cout << "Making comparisons…" << endl;
// Go through each word in vector
for(int i=0; i < fileRead->size(); i++)
{
bool found = false;
// Go through and match it with a dictionary word
for(int j= 0; j < dict.size(); j++)
{
if(WordCmp(fileRead[i]->c_str(), dict[j].c_str()) != 0)
{
found = true;
}
}
if(found == false)
{
cout << fileRead[i] << "Not found" << endl;
}
}
}
int WordCmp(char* Word1, char* Word2)
{
if(!strcmp(Word1,Word2))
return 0;
if(Word1[0] != Word2[0])
return 100;
float AveWordLen = ((strlen(Word1) + strlen(Word2)) / 2.0);
return int(NumUniqueChars(Word1,Word2)/ AveWordLen * 100);
}
The error is in the lines
if(WordCmp(fileRead[i]->c_str(), dict[j].c_str()) != 0)
and
cout << fileRead[i] << "Not found" << endl;
the problem seems to be, because its in the form of a pointer the current syntax im using to access it is made invalid.
Using [] on a pointer to a vector will not call std::vector::operator[]. To call std::vector::operator[] as you want, you must have a vector, not a vector pointer.
The syntax to access the n-th element of a vector with a pointer to the vector would be: (*fileRead)[n].c_str().
However, you should just pass a reference to the vector:
void spellCheck(vector<string>& fileRead)
Then it's just:
fileRead[n].c_str()
You can use the unary * to get a vector& from a vector*:
cout << (*fileRead)[i] << "Not found" << endl;
Two options to access:
(*fileRead)[i]
fileRead->operator[](i)
One option to improve the method
pass by reference
You can either pass fileRead by reference like this:
void spellCheck(vector<string> & fileRead)
Or add a dereferece when you use it like this:
if(WordCmp( (*fileRead)[i]->c_str(), dict[j].c_str()) != 0)