Write output to new files at every nth iteration - c++

A fragment of my code is :
for (int iter = 0; iter < flags.total_iterations_; ++iter) {
if (iter%20==0) {
std::ofstream mf(flags.model_file_.c_str());
accum_model.AppendAsString(word_index_map, mf); }
else {
std::cout << "Model not created for "; }
std::cout << "Iteration " << iter << " ...\n";
So, I am trying to generate outputs from method accum_model at every 20th iteration. But, the problem is I have to write the output in new file everytime the 20th iteration is reached. Now, my output is being overwritten.
I execute this code with the help of a executible, which is as:
./lda --num_topics 15 --alpha 0.1 --beta 0.01 --training_data_file testdata/test_data.txt --model_file MF/lda_model.txt --burn_in_iterations 120 --total_iterations 150
The MF/lda_model.txt is the output file given. I am not understanding how to link the file that contains the code and this executible command as I would need 5 different new files (for 100 iterations - as data is written into a new file every 20th iteration).
I am new to coding and so far, I was coding in python. I tried till this loop, I am confused about how to create new files and get corresponding outputs. Please help! Thanks in advance.

Use std::stringstream, and build a new file name to open each time.
std::string uniquePathFileNamePostFix (int i) {
std::stringstream ss;
ss << '-' << i ;
return (ss.str());
}
The idea is to use the stringstream to create (or append or prepend) a unique modifier based on i. (or anything else convenient - I have used time stamps).

If I understand your question correctly, you are overwriting the ofstream instead of appending to it.
You'll want to specify the 'app' flag in the mode of the ofstream constructor:
std::ofstream mf(flags.model_file_.c_str(), std::ios_base::app);
If you need to start the output with an new, "empty" file, just leave out the mode (ofstream defaults to std::ios_base:out, whether you specify it or not): std::ofstream::ofstream
...and if you need a new output file (according to your OP), you need to change the file name in flags.model_file_.

I'm not sure that I understand your question correctly, but I think you want to output every 20th iteration in a new file. To do so, you just need to append the value of theiter to the name of the file or otherwise add a "dynamic" element to it.
The way to do it using only standard C++ is using stringstream:
std::stringstream file_name;
file_name << flags.model_file_ << iter;
result = file_name.str();

Related

ofstream keeps giving me the last line of the function instead of showng everything

so I have been trying to figure out a way to have a function enter whatever is written in a file and to output into a Sha-256 function. maybe why do I want to do that? Simple enough I am trying to just teach myself how things work in c++, however it displays the last line for the function ofstream. this is my main function
ifstream input ("/home/findme/Desktop/text.txt"); // opens text.txt file.
string s;
while (getline (input, s))
{
// loop to read every line one by one of the file.
string c = s; // enters function to be converted.
string output1 = sha256(c); // gives back the value of the string.
cout << "sha256('"<< c << "'):" << output1 << endl; //displays the results.
ofstream outfile ("/home/findme/Desktop/result.txt");
outfile << "sha256('"<< c << "'):" << output1 << endl;
outfile.close();
}
ok so just an insight of what happens, it reads the context of the file named text.txt in this file there is 3 lines which are (test, test2, test3). so it reads one line and sends it to the function and it returns then it does it for the second line and so on. Once it hits the last line the cout function reads this
sha256('test'):9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08
sha256('test2'):60303ae22b998861bce3b28f33eec1be758a213c86c93c076dbe9f558c11c752
sha256('test3'):fd61a03af4f77d870fc21e05e7e80678095c92d808cfb3b5c279ee04c74aca13
and that's correct. there is no problem whatsoever with the cout function but when I try to put it in an external file named result.txt it displays
sha256('test3'):fd61a03af4f77d870fc21e05e7e80678095c92d808cfb3b5c279ee04c74aca13
That's is the problem, it seems like all it does is writes the last function. I tried to change the placing of the ofstream as in outside the loop or before the cout function and it gives the same issue, I also tried with a loop and it gives the same issue. It just repeats the sha256('test3').
Now I know that its obviously something really easy to fix but im not seeing, therefore can someone please help me? I want it to display exactlty what the cout displays. (there are no error messages and it compiles without a problem). Thank you
You are creating your ofstream outfile in the loop. Meaning it's recreated each iteration through the loop. If you move this line to the top of your sample code it should work:
ofstream outfile ("/home/findme/Desktop/result.txt");

C++ copying parts of a file to a new file

I am trying to create a new file with data from two different existing files. I need to copy the first existing file in it's entirety, which I have done successfully. For the second existing file I need to copy just the last two columns and append it to the first file at the end of each row.
Ex:
Info from first file already copied into my new file:
20424297 1092 CSCI 13500 B 3
20424297 1092 CSCI 13600 A- 3.7
Now I need to copy the last two columns of each line in this file and then append them to the appropriate row in the file above:
17 250 3.00 RNL
17 381 3.00 RLA
i.e. I need "3.00" and "RNL" appended to the end of the first row, "3.0" and "RLA" appended to the end of the second row, etc.
This is what I have so far:
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <cstdlib>
using namespace std;
int main() {
//Creates new file and StudentData.tsv
ofstream myFile;
ifstream studentData;
ifstream hunterCourseData;
//StudentData.tsv is opened and checked to make sure it didn't fail
studentData.open("StudentData.tsv");
if(studentData.fail()){
cout << "Student data file failed to open" << endl;
exit(1);
}
//My new file is opened and checked to make sure it didn't fail
myFile.open("file.txt");
if(myFile.fail()){
cout << "MyFile file failed to open" << endl;
exit(1);
}
//HunterCourse file is opened and checked to make sure if didn't fail
hunterCourseData.open("HunterCourse.tsv");
if(myFile.fail()){
cout << "Hunter data file failed to open" << endl;
exit(1);
}
// Copies data from StudentData.tsv to myFile
char next = '\0';
int n = 1;
while(! studentData.eof()){
myFile << next;
if(next == '\n'){
n++;
myFile << n << ' ';
}
studentData.get(next);
}
return 0;
}
I am going bananas trying to figure this out. I'm sure it's a simple fix but I can't find anything online that works. I've looked into using ostream and a while loop to assign each row into a variable but I can't get that to work.
Another approach that has crossed my mind is just to remove all integers from the second file because I only need the last two columns and neither of those columns include integers.
If you take a look at the seekg method of a file-stream, you'll note the second version allows you to implement the location to set an offset from (such as ios_base::end which sets the offset compared to the end of the file. With this you can effectively read backwards from the end of the a file.
Consider the following
int Pos=0;
while(hunterCourseData.peek()!= '\n')
{
Pos--;
hunterCourseData.seekg(Pos, ios_base::end);
}
//this line will execute when you have found the first newline-character from the end of the file.
Much better code is available at this Very Similar question
Another possibility is simply to find how many lines are in the file beforehand. (less fast, but workable), in this case one would simply loop though the file calling getline and increment a count variable, reset to the start, then repeat until reaching the count - 2. Though I wouldn't use this technique myself.

Reading and writing to files isn't working in C++

I am basically trying to reverse the contents of a text file. When I run this code, nothing happens. Code:
getArguments();
stringstream ss;
ss << argument;
string fileName;
ss >> fileName;
fstream fileToReverse(fileName);
if (fileToReverse.is_open()) {
send(sock, "[*] Contents is being written to string ... ", strlen("\n[*] Contents is being written to string ... "), 0);
string line;
string contentsOfFile;
while (getline(fileToReverse, line)) {
contentsOfFile.append(line);
line = "\0";
}
send(sock, "done\n[*] File is being reversed ... ", strlen("done\n[*] File is being reversed ... "), 0);
string reversedText(contentsOfFile.length(), ' ');
int i;
int j;
for(i=0,j=contentsOfFile.length()-1;i<contentsOfFile.length();i++,j--) {
reversedText[i] = contentsOfFile[j];
}
contentsOfFile = "\0";
fileToReverse << reversedText;
fileToReverse.close();
send(sock, "done\n", strlen("done\n"), 0);
}
fileName is created from user input, and I know that the file exists. It just doesn't do anything to the file. If anyone has any ideas that they would like to share that would be great.
UPDATE:
I now can write reversedText to the file but how can I delete all of the files contents?
In this particular case, when you have read all the input content, your file is in an "error state" (eof and fail bits set in the status).
You need to clear that with fileToReverse.clear();. Your file position will also be at the end of the file, so you need to use fileToReverse.seekp(0, ios_base::beg) to set the position to the beginning.
But I, just as g-makulik, prefer to have two files, one for input and one for output. Saves a large amount of messing about.
When you need to debug something like this - saying "all the functions are being run and all the variables are being created, and it compiled without any warnings" isn't really debugging.
Debugging - this doesn't work. Remove bits until you find what doesn't work. Like you said - all variables are what you expect them. So... try and see if, for example, the way you read and write from a file works. Just write a small program that opens a file like you open it, reads from it like you do and then writes... whatever back into it in the same way you do. See if that works.
In other words, try and find the smallest program that reproduces what you see.

How to read same file twice in a row

I read through a file once to find the number of lines it contains then read through it again so I can store some data of each line in an array. Is there a better way to read through the file twice than closing and opening it again? Here is what I got but am afraid it's inefficient.
int numOfMappings = 0;
ifstream settingsFile("settings.txt");
string setting;
while(getline(settingsFile, setting))
{
numOfMappings++;
}
char* mapping = new char[numOfMappings];
settingsFile.close();
cout << "numOfMappings: " << numOfMappings << endl;
settingsFile.open("settings.txt");
while(getline(settingsFile, setting))
{
cout << "line: " << setting << endl;
}
settingsFile.clear();
settingsFile.seekg(0, settingsFile.beg);
To rewind the file back to its beginning (e.g. to read it again) you can use ifstream::seekg() to change the position of the cursor and ifstream::clear() to reset all internal error flags (otherwise it will appear you are still at the end of the file).
Secondly, you might want to consider reading the file only once and storing what you need to know in a temporary std::deque or std::list while you parse the file. You can then construct an array (or std::vector) from the temporary container, if you would need that specific container later.
It's inefficient, use a std::vector and read through the file once only.
vector<string> settings;
ifstream settingsFile("settings.txt");
string setting;
while (getline(settingsFile, setting))
{
settings.push_back(setting);
}
Just use:
settingsFile.seekg(0, settingsFile.beg);
This will rewind file pointer to the very beginning, so you can read it again without closing and reopening.

read in values and store in list in c++

i have a text file with data like the following:
name
weight
groupcode
name
weight
groupcode
name
weight
groupcode
now i want write the data of all persons into a output file till the maximum weight of 10000 kg is reached.
currently i have this:
void loadData(){
ifstream readFile( "inFile.txt" );
if( !readFile.is_open() )
{
cout << "Cannot open file" << endl;
}
else
{
cout << "Open file" << endl;
}
char row[30]; // max length of a value
while(readFile.getline (row, 50))
{
cout << row << endl;
// how can i store the data into a list and also calculating the total weight?
}
readFile.close();
}
i work with visual studio 2010 professional!
because i am a c++ beginner there could be is a better way! i am open for any idea's and suggestions
thanks in advance!
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <limits>
struct entry
{
entry()
: weight()
{ }
std::string name;
int weight; // kg
std::string group_code;
};
// content of data.txt
// (without leading space)
//
// John
// 80
// Wrestler
//
// Joe
// 75
// Cowboy
int main()
{
std::ifstream stream("data.txt");
if (stream)
{
std::vector<entry> entries;
const int limit_total_weight = 10000; // kg
int total_weight = 0; // kg
entry current;
while (std::getline(stream, current.name) &&
stream >> current.weight &&
stream.ignore(std::numeric_limits<std::streamsize>::max(), '\n') && // skip the rest of the line containing the weight
std::getline(stream, current.group_code))
{
entries.push_back(current);
total_weight += current.weight;
if (total_weight > limit_total_weight)
{
break;
}
// ignore empty line
stream.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
}
else
{
std::cerr << "could not open the file" << std::endl;
}
}
Edit: Since you wannt to write the entries to a file, just stream out the entries instead of storing them in the vector. And of course you could overload the operator >> and operator << for the entry type.
Well here's a clue. Do you see the mismatch between your code and your problem description? In your problem description you have the data in groups of four lines, name, weight, groupcode, and a blank line. But in your code you only read one line each time round your loop, you should read four lines each time round your loop. So something like this
char name[30];
char weight[30];
char groupcode[30];
char blank[30];
while (readFile.getline (name, 30) &&
readFile.getline (weight, 30) &&
readFile.getline (groupcode, 30) &&
readFile.getline (blank, 30))
{
// now do something with name, weight and groupcode
}
Not perfect by a long way, but hopefully will get you started on the right track. Remember the structure of your code should match the structure of your problem description.
Have two file pointers, try reading input file and keep writing to o/p file. Meanwhile have a counter and keep incrementing with weight. When weight >= 10k, break the loop. By then you will have required data in o/p file.
Use this link for list of I/O APIs:
http://msdn.microsoft.com/en-us/library/aa364232(v=VS.85).aspx
If you want to struggle through things to build a working program on your own, read this. If you'd rather learn by example and study a strong example of C++ input/output, I'd definitely suggest poring over Simon's code.
First things first: You created a row buffer with 30 characters when you wrote, "char row[30];"
In the next line, you should change the readFile.getline(row, 50) call to readFile.getline(row, 30). Otherwise, it will try to read in 50 characters, and if someone has a name longer than 30, the memory past the buffer will become corrupted. So, that's a no-no. ;)
If you want to learn C++, I would strongly suggest that you use the standard library for I/O rather than the Microsoft-specific libraries that rplusg suggested. You're on the right track with ifstream and getline. If you want to learn pure C++, Simon has the right idea in his comment about switching out the character array for an std::string.
Anyway, john gave good advice about structuring your program around the problem description. As he said, you will want to read four lines with every iteration of the loop. When you read the weight line, you will want to find a way to get numerical output from it (if you're sticking with the character array, try http://www.cplusplus.com/reference/clibrary/cstdlib/atoi/, or try http://www.cplusplus.com/reference/clibrary/cstdlib/atof/ for non-whole numbers). Then you can add that to a running weight total. Each iteration, output data to a file as required, and once your weight total >= 10000, that's when you know to break out of the loop.
However, you might not want to use getline inside of your while condition at all: Since you have to use getline four times each loop iteration, you would either have to use something similar to Simon's code or store your results in four separate buffers if you did it that way (otherwise, you won't have time to read the weight and print out the line before the next line is read in!).
Instead, you can also structure the loop to be while(total <= 10000) or something similar. In that case, you can use four sets of if(readFile.getline(row, 30)) inside of the loop, and you'll be able to read in the weight and print things out in between each set. The loop will end automatically after the iteration that pushes the total weight over 10000...but you should also break out of it if you reach the end of the file, or you'll be stuck in a loop for all eternity. :p
Good luck!