Write vector values into multiple files at once in C++ - c++

I have the data in my vector. I am trying to write each vector value, say vector_name[0] into "examplezero.h" , vector_name[1] into "exampleone.h" and so on. The below code shows how I have created the files.
int co = 80;
string name ="example";
std::ofstream output_file[80];
for (int i = 0; i < co; i++)
{
output_file[i].open(name + std::to_string(i) + ".h");
output_file[i].close();
}
I am trying to iterate over my vector and trying to write to my files.
std::vector<string> rowname; //This has all the values
for (auto i = rowname.begin(); i != rowname.end(); ++i)
{
std::ostream_iterator<std::string> \
output_iterator(output_file[80], "\n");
std::copy(rowname.begin(), rowname.end(), output_iterator);
}
When I am trying to write to the files it is crashing. Can you let me know what's wrong? I know the basics of C++ and trying to learn the advanced concepts.
Thanks

Your program is likely crashing because you wrote this code:
std::ostream_iterator<std::string> \
output_iterator(output_file[80], "\n");
...and output_file[80] is one element past the end of the array. You declared it as:
std::ofstream output_file[80];
The first element of that array is output_file[0] and the last element of that array is output_file[79].
There are more things wrong
As #walnut pointed out, if your code is really as you posted it, then it appears to close each file immediately after opening it, without writing anything to the file.
for (int i = 0; i < co; i++)
{
output_file[i].open(name + std::to_string(i) + ".h");
output_file[i].close(); // Leaving so soon?
}
Writing to an ofstream that has been closed does not crash the program, but sets an error condition on the ofstream (badbit). So this will appear to be a silent failure to you.
To fix
To fix your problem you'll have to write to your file after you open it, but before you close it.
You'll also have to decide exactly which output_file you actually want to write to and provide the correct array index. It's not obviously clear from your sample code what your intent was. You'll have to decide which file(s) (of the 80 that you opened) you want to write each element of your rowname vector into.
The std::copy as you have written it will write all strings in the rowname vector to the same stream. If your intent was to write each element to its own file, then you'll have to set it up substantially differently.
Something more along the lines of:
#include <fstream>
#include <vector>
#include <string>
int main() {
std::vector<std::string> rowname = { "alpha", "bravo", "charlie" }; // example data
std::string name = "example"; // base filename
for (size_t i = 0; i < rowname.size(); ++i) {
std::ofstream output_file;
std::string filename = name + std::to_string(i) + ".h"; // e.g.: "example0.h"
output_file.open(filename);
output_file << rowname[i]; // write the string to the file
output_file.close(); // if you want
}
}
This writes the text alpha into example0.h, bravo into example1.h, and charlie into example2.h.

Related

ifstream read every files that start with

I have multiple files that start with employee_
Examples :
employee_2053.txt
employee_1284.txt
employee_4302.txt
etc...
What I want is to read the content of every file. I tried something like this:
string fname, lname;
ifstream file("employee_" + *);
while(file>>fname>>lname) {
// Do something here that is gonna be repeated for every file
}
I have an error at "employee_" + *. When I think about it, it makes sense that it doesn't work. I guess I will need a loop or something, I just don't know how to do it.
Enumerate the available files using the OS specific API and store the names inside a container such as vector of strings std::vector<std::string> v;. Iterate over a container:
for (auto el : v) {
std::ifstream file(el);
// the code
}
If you know for sure there are existing files with range based hard coded values you can utilize the std::to_string function inside a for loop:
for (size_t i = 0; i < 4000; i++) {
std::ifstream file("employee_" + std::to_string(i) + ".txt");
// the code
}
Update:
As pointed out in the comments the alternative to OS API is a file system support in the C++17 standard and the Boost Filesystem Library.

C++: How can I output data as CSV to a specific set of cells in an existing file?

So I am looping over data files in order to make a calculation based on each data file (the calculation is done for 20 bins in each file, so 20 results per file). I then want to get each calculation into a csv file so that I am able to average the calculations from each file.
Each time I loop over a file, I am obtaining a csv file with 20 results in cells A1 to A20.
However, what I want is a csv file with 20 results in cells A1 to A20, another 20 results in cells B1 to B20 etc. up to 20 results in cells CV1 to CV20.
My code in each loop looks like this for outputting the data:
ofstream ofs (path2 + "tanShears.csv", ofstream::out);
for (int j = 0; j < r.size(); j++) {
ofs << tShears[j] << endl;
Obviously when I do this I just end up with 20 results in cells A1 to A20 corresponding to the final data set in the loop, since each loop just overwrites the previous one.
Any ideas how I can target specific cells in the csv file, so that I can output the results from each loop to a different part of the same csv file?
A CSV file is structured like this:
[A1];[B1];[C1];...\n
[A2];[B2];...\n
[A3];[B3];...\n
If you don't want to write the whole data at once, you will have to read the whole file, parse it, make changes accordingly and then writing it. Which I would avoid at almost any cost.
Now to some example code: (I am assuming you are printing some int value)
void writeToCSV(std::vector<std::vector<int>> const& tShears)
{
ofstream ofs (path2 + "tanShears.csv", ofstream::out);
for (std::vector<std::vector<int>>::iterator j = tShears.begin();
j != tShears.end(); j++)
{
for(std::vector<int>::iterator i = j->begin(); i < j->end(); j++)
{
ofs << i << ";";
}
ofs << std::endl;
}
ofs.close();
}
In this example the inner vector contains the n-th values of all calculations you made. So it might contain A1, B1, C1...
You could keep the results in a vector (one block of 20 after another, or use different vectors).
Then write all data at once. The first value of each block on the first line in your csv, then the second, and so on.
Did I understand correctly your question?
You have 20 data sources with csv data, 20 results in each one. And you need to operate with these data with later writing each data set to the file?
#include <map>
#include <vector>
#include <string>
struct privateData {
map<string,vector<vector<string>>> allData;
void addDataUnit(const string& block, const vector<string>& unit)
{
// I consider that you already parsed csv data into separated elements
allData[block].push_back(unit);
}
string getDataRow(const string& block, int position) {
string ret;
if (allData[block].size() >= position) return ret;
for (unsigned int i = 0; i < allData[block][position].size(); i++) {
ret+=allData[block][position][i];
ret+="SomeDelim";
}
return ret;
}
vector<string> getDataBlock(const string& block) {
vector<string> ret;
for (unsigned int i = 0; i < allData[block].size(); i++)
ret.push_back(getDataRow(block,i));
return ret;
}
}
I didn't compile - so, probably some syntax errors.
So, each dataBlock will be named array for a cell set.
Then you can iterate the map to get all names and write them to separate files or to separate data set.
Hope it helps
Check this : http://www.cplusplus.com/reference/fstream/ofstream/ofstream/#parameters
You should write sth like this:
ofstream ofs (path2 + "tanShears.csv", ofstream::out|ofstream::app);
You can store your all results in vector, but if calculation is a long process (it takes a hours), there is possibility of loss this data (when sth go wrong), and in this case better is write your results to file after each part of calculation.
However, writing to file full data seems be faster then many writings partial data.

writing content of vector to file c++

I've tried to write my vector content into a file. To do that I've written a piece of code like:
int main()
{
ofstream outputfile("test.txt");
vector<int>temp;
temp.push_back(1);
temp.push_back(2);
temp.push_back(3);
for(int i=0;i<temp.size();i++)
outputfile<<temp[i]<<"\n";
}
When I write this I can easly do what I wanted. the content of file is:
1
2
3
However, when I want to write my vector to file from reverse(like below).I get nothing.Just empty file.Is there anyone to help me ? Thanks in advance.
for(int i=temp.size()-1;i>=0;i--)
outputfile<<temp[i]<<"\n";
You may use
std::copy(temp.rbegin(), temp.rend(),
std::ostream_iterator<int>(outputfile, "\n"));
And this code:
for(int i=temp.size()-1;i>=0;i--)
outputfile<<temp[i]<<"\n";
works fine on my windows with vs12.
You can do it all in 1 line:
std::copy(temp.rbegin(), temp.rend(), std::ostream_iterator<int>(outputFile, "\n"));
use a reverse iterator:
for (std::vector<int>::reverse_iterator it = myvector.rbegin(); it != myvector.rend(); ++it)
or in your code, start the for loop from size() - 1 :
for(int i=temp.size()-1;i>=0;i--)
instead of
for(int i=temp.size();i>=0;i--)
std::copy(head_buff.rbegin(), head_buff.rend(),
std::ostream_iterator<std::string>(data_pack, "\n"));
but use #include<fstram>#include<iterator> #include<osstream>
second method is traverse entire vector and copy the contents to a string
then write the string into ofstream
ie
std::string somthing;
for(std::vector<std::string>::const_iterator i = temp.begin();i!=temp.end(); ++i)
{
something+=*i;
}
then write string (something) to ofstream ie
std::ofstram output;
output.open("test.txt",std::ios_base::trunc)
if(output.fail())
std::cerr<<"unable to open the file"std::endl;
output << something;
//after writing close file
output.close();

Very large look up table C++ - can I avoid typing the whole thing out?

I am not a programmer, but am an engineer who needs to use C++ coding on this occasion, so sorry if this question is a little basic.
I need to use a look up table as I have some highly non-linear dynamics going on that I need to model. It consists of literally 1000 paired values, from a pair of (0.022815, 0.7) up to (6.9453, 21.85).
I don't want to have to type all these values out in my C code. The values are currently stored in Matlab. Can I read them from a .dat file or something similar?
I will have calculated a value and simply want the program to kick out the paired value.
Thanks,
Adam
You can't read something stored in Matlab directly, unless you want to
write a parser for whatever format Matlab stores its data in. I'm not
familiar with Matlab, but I would be very surprised if it didn't have a
function to output this data to a file, in some text format, which you
could read and parse.
Assuming this is constant data, if it could output something along the
lines of:
{ 0.022815, 0.7 },
...
{ 6.9453, 21.85 },
you could include it as the initializer of a table in C++. (It may look
strange to have a #include in the middle of a variable definition, but
it's perfectly legal, and in such cases, perfectly justified.) Or just
copy/paste it into your C++ program.
If you can't get exactly this format directly, it should be trivial to
write a small script that would convert whatever format you get into
this format.
this program defines a map, then reading from a.txt file, inserting to a map, iterating on map for any purposes you have, and finally writing the map into a file.
just a simple practice:
#include <fstream>
#include <iostream>
#include <map>
using namespace std;
int main(){
ifstream inFile("a.txt", ios::in);
if (! inFile ){
cout<<"unabl to open";
return 0;
}
//reading a file and inserting in a map
map<double,double> mymap;
double a,b;
while( ! inFile.eof() ){
inFile>>a>>b;
mymap.insert ( a,b );
}
inFile.close(); //be sure to close the file
//iterating on map
map<double,double>::iterator it;
for ( it=mymap.begin() ; it != mymap.end(); it++ ){
// (*it).first
// (*it).second
}
//writing the map into a file
ofstream outFile;
outFile.open ("a.txt", ios::out); // or ios::app if you want to append
for ( it=mymap.begin() ; it != mymap.end(); it++ ){
outFile << (*it).first << " - " << (*it).second << endl; //what ever!
}
outFile.close();
return 0;
}
What I would do for this is as follows as I think this is faster than file open and close. First of all create a header file which contains all the data in an array. You could you a "replace all" available in Notepad or so to replace the () braces to { } braces. Later on you could even write a script that makes the header file from the Matlab file
>> cat import_data.h
#define TBL_SIZE 4 // In your case it is 1000
const double table[TBL_SIZE][2] =
{
{ 0.022815, 0.7 },
{ 6.9453, 21.85 },
{ 4.666, 565.9},
{ 567.9, 34.6}
};
Now in the main program you include this header also for the data
>> cat lookup.c
#include <stdio.h>
#include "import_data.h"
double lookup(double key)
{
int i=0;
for(;i<TBL_SIZE; i++) {
if(table[i][0] == key)
return table[i][1];
}
return -1; //error
}
int main() {
printf("1. Value is %f\n", lookup(6.9453));
printf("2. Value is %f\n", lookup(4.666));
printf("3. Value is %f\n", lookup(4.6));
return 0;
}
Yes, you can read them from the dat file. The question is, what format is the dat file? Once you know that, you want to use:
fopen
fread
fclose
for C and
ifstream
for C++ (or something similar).
The program still has to get those pairs from the file and load them in memory. You can loop through the lines in the file, parse the pairs and shove them in a std::map.
Something like this:
#include<fstream>
#include<map>
...
ifstream infile("yourdatfile.dat");
std::string str;
std::map<double, double> m; //use appropriate type(s)
while(getline(infile, str)){
//split str by comma or some delimiter and get the key, value
//put key, value in m
}
//use m
For the signal processing toolbox you can export data to C header files
directly from Matlab(don't know if it's your particular case):
Matlab export to C header
Or maybe the following article could be of help:
Exporting/Importing Data To/From MATLAB
One of options is to generate the C++ lookup table in matlab. Just write to some text file (lookup.cpp), read table producing C++ source...

Reading multiple files

I want to alternate between reading multiple files. Below is a simplified version of my code.
ifstream* In_file1 = new ifstream("a.dat", ios::binary);
ifstream* In_file2 = new ifstream("b..dat", ios::binary);
ifstream* In_file;
int ID;
In_file = In_file1;
int ID = 0;
//LOOPING PORTION
if (In_file -> eof())
{
In_file -> seekg(0, ios_base::beg);
In_file->close();
switch (ID)
{
case 0:
In_file = In_file2; ID = 1; break;
case 1:
In_file = In_file1; ID = 0; break;
}
}
//some codes
:
:
In_file->read (data, sizeof(double));
//LOOPING PORTION
The code works well if I am reading the files one time and I thought that everything was cool. However, if the part termed 'looping portion' is within a loop, then the behaviour becomes weird and I start having a single repeating output. Please, can someone tell me what is wrong and how I can fix it? If you have a better method of tacking the problem, please suggest. I appreciate it.
//SOLVED
Thank you everybody for your comments, I appreciate it. Here is what I simple did:
Instead of the original
switch (ID)
{
case 0:
In_file = In_file2; ID = 1; break;
case 1:
In_file = In_file1; ID = 0; break;
}
I simply did
switch (ID)
{
case 0:
In_file = new ifstream("a.dat", ios::binary); ID = 1; break;
case 1:
In_file = new ifstream("b.dat", ios::binary); ID = 0; break;
}
Now it works like charm and I can loop as much as I want:-). I appreciate your comments, great to know big brother still helps.
Let's see: the code you posted works fine, and you want us to tell you
what's wrong with the code you didn't post. That's rather difficult.
Still, the code you posted probably doesn't work correctly either.
std::istream::eof can only be used reliably after an input (or some
other operation) has failed; in the code you've posted, it will almost
certainly be false, regardless.
In addition: there's no need to dynamically allocate ifstream; in
fact, there are almost no cases where dynamic allocation of ifstream
is appropriate. And you don't check that the opens have succeeded.
If you want to read two files, one after the other, the simplest way is
to use two loops, one after the other (calling a common function for
processing the data). If for some reason that's not appropriate, I'd
use a custom streambuf, which takes a list of filenames in the
constructor, and advances to the next whenever it reaches end of file on
one, only returning EOF when it has reached the end of all of the
files. (The only complication in doing this is what to do if one of the
opens fails. I do this often enough that it's part of my tool kit,
and I use a callback to handle failure. For a one time use, however,
you can just hard code in whatever is appropriate.)
As a quick example:
// We define our own streambuf, deriving from std::streambuf
// (All istream and ostream delegate to a streambuf for the
// actual data transfer; we'll use an instance of this to
// initialize the istream we're going to read from.)
class MultiFileInputStreambuf : public std::streambuf
{
// The list of files we will process
std::vector<std::string> m_filenames;
// And our current position in the list (actually
// one past the current position, since we increment
// it when we open the file).
std::vector<std::string>::const_iterator m_current;
// Rather than create a new filebuf for each file, we'll
// reuse this one, closing any previously open file, and
// opening a new file, as needed.
std::filebuf m_streambuf;
protected:
// This is part of the protocol for streambuf. The base
// class will call this function anytime it needs to
// get a character, and there aren't any in the buffer.
// This function can set up a buffer, if it wants, but
// in this case, the buffering is handled by the filebuf,
// so it's likely not worth the bother. (But this depends
// on the cost of virtual functions---without a buffer,
// each character read will require a virtual function call
// to get here.
//
// The protocol is to return the next character, or EOF if
// there isn't one.
virtual int underflow()
{
// Get one character from the current streambuf.
int result = m_streambuf.sgetc();
// As long as 1) the current streambuf is at end of file,
// and 2) there are more files to read, open the next file
// and try to get a character from it.
while ( result == EOF && m_current != m_filenames.eof() ) {
m_streambuf.close();
m_streambuf.open( m_current->c_str(), std::ios::in );
if ( !m_streambuf.is_open() )
// Error handling here...
++ m_current;
result = m_streambuf.sgetc();
}
// We've either gotten a character from the (now) current
// streambuf, or there are no more files, and we'll return
// the EOF from our last attempt at reading.
return result;
}
public:
// Use a template and two iterators to initialize the list
// of files from any STL sequence whose elements can be
// implicitly converted to std::string.
template<typename ForwardIterator>
MultiFileInputStreambuf(ForwardIterator begin, ForwardIterator end)
: m_filenames(begin, end)
, m_current(m_filenames.begin())
{
}
};
#include <iostream>
#include <fstream>
#include <string>
#define NO_OF_FILES 2
int main ()
{
std::ifstream in;
std::string line;
std::string files[NO_OF_FILES] =
{
"file1.txt",
"file2.txt",
};
// start our engine!
for (int i = 0; i < NO_OF_FILES; i++)
{
in.open(files[i].c_str(), std::fstream::in);
if (in.is_open())
{
std::cout << "reading... " << files[i] << endl;
while (in.good())
{
getline(in, line);
std::cout << line << std::endl;
}
in.close();
std::cout << "SUCCESS" << std::endl;
}
else
std::cout << "Error: unable to open " + files[i] << std::endl;
}
return 0;
}