I am facing a strange issue with my application, and although I have tried several solutions, none have solved my problem.
My c++ application generates a set of files with custom data. So far, the code seems to work fine, and the files are generated correctly, except the first one. The expected format of the files is the following:
#Header
#Line1E1,Line1E2,Line1E3
#Line2E1,Line2E2,Line1E3
However, I have noticed a strange empty space on the first line of the first generated file (and only the first one):
#Header
#Line1E1,Line1E2,Line1E3
#Line2E1,Line2E2,Line1E3
Since the code is the same for all the files, I am wondering what dit it go wrong, but so far I have not been able to detect the root of my problem.
The following is a simplified version of my code:
/* Variables */
std::ofstream Fil;
std::stringstream ss;
ss.precision (10);
ss.width (10);
ss.setf (ios::fixed);
for (int Inx = 0; Inx < MaxInx; Inx++) {
sprintf (FilNam, "%i-ExportFile.txt", Inx);
Fil.open(std::string (FilNam).c_str (), std::ofstream::out);
SavSta = Fil.is_open ();
if (SavSta) {
ss << "#Header" << "\n";
ss << "#Matrix name: " << MtxName << "\n";
ss << /* Matrix data goes here */ << "\n";
Fil << ss.rdbuf ();
ss.str(std::string ());
ss.clear ();
}
Fil.close ();
}
It is coming from :
ss.width(10);
From cplusplus.com
If the standard width of the representation is shorter than the field width, the representation is padded with fill characters
Just remove it and you'll be OK.
Related
I'm making an OpenGL game in C++. I'm fairly inexperinced in C++ as opposed to other languages. Anyway, I create a stringstream with the "base" directory for some images. I then pass this stringstream as a function parameter to a constructor. The constructor appends an image file name, then attempts to load the resulting path. However...
D:\CodeBlocks Projects\SnakeRoid\bin\Debug\Texts\ <-- before appending the filename
Ship01.tgacks Projects\SnakeRoid\bin\Debug\Texts\ <-- After.
Obviously not correct! The result should be D:\CodeBlocks Projects\SnakeRoid\bin\Debug\Texts\Ship01.tga
The relevant parts of my code:
std::stringstream concat;
std::string txtFullPath = "Path here";
...
concat.str(""); //Reset value (because it was changed in ...)
concat << texFullPath; //Restore the base path
PS = new PlayerShip(&TexMan, concat); //Call the constructor
The constructor's code
PlayerShip::PlayerShip(TextureManager * TexMan, std::stringstream &path)
{
texId = 2;
std::cout << path.str(); //First path above
path << "Ship01.tga";
std::cout << path.str(); //Second - this is the messed up one
//Do more fun stuff
}
Anyone have any idea why its "overwriting" what's already in the stringstream?
why its "overwriting" what's already in the stringstream
Because output places characters at the "put pointer" position in the output buffer. A freshly-constructed stream has the put pointer set to zero (except for file output streams opened in append mode), thus your output overwrites the characters already in the buffer.
If you really need to append strings this way, you need to move the put pointer to the end of the buffer:
std::cout << p.str(); //First path above
std::stringstream path;
path.str(p.str());
path.seekp(0, std::ios_base::end); // <-- add this
path << "Ship01.tga";
std::cout << "Loading player ship from " << path.str();
EDIT: The question has been edited and the code after the edit works, because it no longer uses path.str(p.str()); to create the output buffer without using an output operation (and without advancing the put pointer): see ideone for differences.
In any case, strings themselves can be concatenated, which would make the code easier to follow:
std::string p = path.str() + "Ship01.tga";
std::cout << p;
Not to mention that for dealing with files and pathnames, we have boost.filesystem.
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();
As part of a bigger application I am working on a class for reading input from a text file for use in the initialization of the program. Now I am myself fairly new to programming, and I only started to learn C++ in December, so I would be very grateful for some hints and ideas on how to get started! I apologise in advance for a rather long wall of text.
The text file format is "keyword-driven" in the following way:
There are a rather small number of main/section keywords (currently 8) that need to be written in a given order. Some of them are optional, but if they are included they should adhere to the given ordering.
Example:
Suppose there are 3 potential keywords ordered like as follows:
"KEY1" (required)
"KEY2" (optional)
"KEY3" (required)
If the input file only includes the required ones, the ordering should be:
"KEY1"
"KEY3"
Otherwise it should be:
"KEY1"
"KEY2"
"KEY3"
If all the required keywords are present, and the total ordering is ok, the program should proceed by reading each section in the sequence given by the ordering.
Each section will include a (possibly large) amount of subkeywords, some of which are optional and some of which are not, but here the order does NOT matter.
Lines starting with characters '*' or '--' signify commented lines, and they should be ignored (as well as empty lines).
A line containing a keyword should (preferably) include nothing else than the keyword. At the very least, the keyword must be the first word appearing there.
I have already implemented parts of the framework, but I feel my approach so far has been rather ad-hoc. Currently I have manually created one method per section/main keyword , and the first task of the program is to scan the file for to locate these keywords and pass the necessary information on to the methods.
I first scan through the file using an std::ifstream object, removing empty and/or commented lines and storing the remaining lines in an object of type std::vector<std::string>.
Do you think this is an ok approach?
Moreover, I store the indices where each of the keywords start and stop (in two integer arrays) in this vector. This is the input to the above-mentioned methods, and it would look something like this:
bool readMAINKEY(int start, int stop);
Now I have already done this, and even though I do not find it very elegant, I guess I can keep it for the time being.
However, I feel that I need a better approach for handling the reading inside of each section, and my main issue is how should I store the keywords here? Should they be stored as arrays within a local namespace in the input class or maybe as static variables in the class? Or should they be defined locally inside relevant functions? Should I use enums? The questions are many!
Now I've started by defining the sub-keywords locally inside each readMAINKEY() method, but I found this to be less than optimal. Ideally I want to reuse as much code as possible inside each of these methods, calling upon a common readSECTION() method, and my current approach seems to lead to much code duplication and potential for error in programming. I guess the smartest thing to do would simply be to remove all the (currently 8) different readMAINKEY() methods, and use the same function for handling all kinds of keywords. There is also the possibility for having sub-sub-keywords etc. as well (i.e. a more general nested approach), so I think maybe this is the way to go, but I am unsure on how it would be best to implement it?
Once I've processed a keyword at the "bottom level", the program will expect a particular format of the following lines depending on the actual keyword. In principle each keyword will be handled differently, but here there is also potential for some code reuse by defining different "types" of keywords depending on what the program expects to do after triggering the reading of it. Common task include e.g. parsing an integer or a double array, but in principle it could be anything!
If a keyword for some reason cannot be correctly processed, the program should attempt as far as possible to use default values instead of terminating the program (if reasonable), but an error message should be written to a logfile. For optional keywords, default values will of course also be used.
In order to summarise, therefore, my main questions are the following:
1. Do you think think my approach of storing the relevant lines in a std::vector<std::string> to be reasonable?
This will of course require me to do a lot of "indexing work" to keep track of where in the vector the different keywords are located. Or should I work more "directly" with the original std::ifstream object? Or something else?
2. Given such a vector storing the lines of the text file, how I can I best go about detecting the keywords and start reading the information following them?
Here I will need to take account of possible ordering and whether a keyword is required or not. Also, I need to check if the lines following each "bottom level" keyword is in the format expected in each case.
One idea I've had is to store the keywords in different containers depending on whether they are optional or not (or maybe use object(s) of type std::map<std::string,bool>), and then remove them from the container(s) if correctly processed, but I am not sure exactly how I should go about it..
I guess there is really a thousand different ways one could answer these questions, but I would be grateful if someone more experienced could share some ideas on how to proceed. Is there e.g. a "standard" way of doing such things? Of course, a lot of details will also depend on the concrete application, but I think the general format indicated here can be used in a lot of different applications without a lot of tinkering if programmed in a good way!
UPDATE
Ok, so let my try to be more concrete. My current application is supposed to be a reservoir simulator, so as part of the input I need information about the grid/mesh, about rock and fluid properties, about wells/boundary conditions throughout the simulation and so on. At the moment I've been thinking about using (almost) the same set-up as the commercial Eclipse simulator when it comes to input, for details see
http://petrofaq.org/wiki/Eclipse_Input_Data.
However, I will probably change things a bit, so nothing is set in stone. Also, I am interested in making a more general "KeywordReader" class that with slight modifications can be adapted for use in other applications as well, at least it can be done in a reasonable amount of time.
As an example, I can post the current code that does the initial scan of the text file and locates the positions of the main keywords. As I said, I don't really like my solution very much, but it seems to work for what it needs to do.
At the top of the .cpp file I have the following namespace:
//Keywords used for reading input:
namespace KEYWORDS{
/*
* Main keywords and corresponding boolean values to signify whether or not they are required as input.
*/
enum MKEY{RUNSPEC = 0, GRID = 1, EDIT = 2, PROPS = 3, REGIONS = 4, SOLUTION = 5, SUMMARY =6, SCHEDULE = 7};
std::string mainKeywords[] = {std::string("RUNSPEC"), std::string("GRID"), std::string("EDIT"), std::string("PROPS"),
std::string("REGIONS"), std::string("SOLUTION"), std::string("SUMMARY"), std::string("SCHEDULE")};
bool required[] = {true,true,false,true,false,true,false,true};
const int n_key = 8;
}//end KEYWORDS namespace
Then further down I have the following function. I am not sure how understandable it is though..
bool InputReader::scanForMainKeywords(){
logfile << "Opening file.." << std::endl;
std::ifstream infile(filename);
//Test if file was opened. If not, write error message:
if(!infile.is_open()){
logfile << "ERROR: Could not open file! Unable to proceed!" << std::endl;
std::cout << "ERROR: Could not open file! Unable to proceed!" << std::endl;
return false;
}
else{
logfile << "Scanning for main keywords..." << std::endl;
int nkey = KEYWORDS::n_key;
//Initially no keywords have been found:
startIndex = std::vector<int>(nkey, -1);
stopIndex = std::vector<int>(nkey, -1);
//Variable used to control that the keywords are written in the correct order:
int foundIndex = -1;
//STATISTICS:
int lineCount = 0;//number of non-comment lines in text file
int commentCount = 0;//number of commented lines in text file
int emptyCount = 0;//number of empty lines in text file
//Create lines vector:
lines = std::vector<std::string>();
//Remove comments and empty lines from text file and store the result in the variable file_lines:
std::string str;
while(std::getline(infile,str)){
if(str.size()>=1 && str.at(0)=='*'){
commentCount++;
}
else if(str.size()>=2 && str.at(0)=='-' && str.at(1)=='-'){
commentCount++;
}
else if(str.size()==0){
emptyCount++;
}
else{
//Found a non-empty, non-comment line.
lines.push_back(str);//store in std::vector
//Start by checking if the first word of the line is one of the main keywords. If so, store the location of the keyword:
std::string fw = IO::getFirstWord(str);
for(int i=0;i<nkey;i++){
if(fw.compare(KEYWORDS::mainKeywords[i])==0){
if(i > foundIndex){
//Found a valid keyword!
foundIndex = i;
startIndex[i] = lineCount;//store where the keyword was found!
//logfile << "Keyword " << fw << " found at line " << lineCount << " in lines array!" << std::endl;
//std::cout << "Keyword " << fw << " found at line " << lineCount << " in lines array!" << std::endl;
break;//fw cannot equal several different keywords at the same time!
}
else{
//we have found a keyword, but in the wrong order... Terminate program:
std::cout << "ERROR: Keywords have been entered in the wrong order or been repeated! Cannot continue initialisation!" << std::endl;
logfile << "ERROR: Keywords have been entered in the wrong order or been repeated! Cannot continue initialisation!" << std::endl;
return false;
}
}
}//end for loop
lineCount++;
}//end else (found non-comment, non-empty line)
}//end while (reading ifstream)
logfile << "\n";
logfile << "FILE STATISTICS:" << std::endl;
logfile << "Number of commented lines: " << commentCount << std::endl;
logfile << "Number of non-commented lines: " << lineCount << std::endl;
logfile << "Number of empty lines: " << emptyCount << std::endl;
logfile << "\n";
/*
Print lines vector to screen:
for(int i=0;i<lines.size();i++){
std:: cout << "Line nr. " << i << " : " << lines[i] << std::endl;
}*/
/*
* So far, no keywords have been entered in the wrong order, but have all the necessary ones been found?
* Otherwise return false.
*/
for(int i=0;i<nkey;i++){
if(KEYWORDS::required[i] && startIndex[i] == -1){
logfile << "ERROR: Incorrect input of required keywords! At least " << KEYWORDS::mainKeywords[i] << " is missing!" << std::endl;;
logfile << "Cannot proceed with initialisation!" << std::endl;
std::cout << "ERROR: Incorrect input of required keywords! At least " << KEYWORDS::mainKeywords[i] << " is missing!" << std::endl;
std::cout << "Cannot proceed with initialisation!" << std::endl;
return false;
}
}
//If everything is in order, we also initialise the stopIndex array correctly:
int counter = 0;
//Find first existing keyword:
while(counter < nkey && startIndex[counter] == -1){
//Keyword doesn't exist. Leave stopindex at -1!
counter++;
}
//Store stop index of each keyword:
while(counter<nkey){
int offset = 1;
//Find next existing keyword:
while(counter+offset < nkey && startIndex[counter+offset] == -1){
offset++;
}
if(counter+offset < nkey){
stopIndex[counter] = startIndex[counter+offset]-1;
}
else{
//reached the end of array!
stopIndex[counter] = lines.size()-1;
}
counter += offset;
}//end while
/*
//Print out start/stop-index arrays to screen:
for(int i=0;i<nkey;i++){
std::cout << "Start index of " << KEYWORDS::mainKeywords[i] << " is : " << startIndex[i] << std::endl;
std::cout << "Stop index of " << KEYWORDS::mainKeywords[i] << " is : " << stopIndex[i] << std::endl;
}
*/
return true;
}//end else (file opened properly)
}//end scanForMainKeywords()
You say your purpose is to read initialization data from a text file.
Seems you need to parse (syntax analyze) this file and store the data under the right keys.
If the syntax is fixed and each construction starts with a keyword, you could write a recursive descent (LL1) parser creating a tree (each node is a stl vector of sub-branches) to store your data.
If the syntax is free, you might pick JSON or XML and use an existing parsing library.
I'm making an OpenGL game in C++. I'm fairly inexperinced in C++ as opposed to other languages. Anyway, I create a stringstream with the "base" directory for some images. I then pass this stringstream as a function parameter to a constructor. The constructor appends an image file name, then attempts to load the resulting path. However...
D:\CodeBlocks Projects\SnakeRoid\bin\Debug\Texts\ <-- before appending the filename
Ship01.tgacks Projects\SnakeRoid\bin\Debug\Texts\ <-- After.
Obviously not correct! The result should be D:\CodeBlocks Projects\SnakeRoid\bin\Debug\Texts\Ship01.tga
The relevant parts of my code:
std::stringstream concat;
std::string txtFullPath = "Path here";
...
concat.str(""); //Reset value (because it was changed in ...)
concat << texFullPath; //Restore the base path
PS = new PlayerShip(&TexMan, concat); //Call the constructor
The constructor's code
PlayerShip::PlayerShip(TextureManager * TexMan, std::stringstream &path)
{
texId = 2;
std::cout << path.str(); //First path above
path << "Ship01.tga";
std::cout << path.str(); //Second - this is the messed up one
//Do more fun stuff
}
Anyone have any idea why its "overwriting" what's already in the stringstream?
why its "overwriting" what's already in the stringstream
Because output places characters at the "put pointer" position in the output buffer. A freshly-constructed stream has the put pointer set to zero (except for file output streams opened in append mode), thus your output overwrites the characters already in the buffer.
If you really need to append strings this way, you need to move the put pointer to the end of the buffer:
std::cout << p.str(); //First path above
std::stringstream path;
path.str(p.str());
path.seekp(0, std::ios_base::end); // <-- add this
path << "Ship01.tga";
std::cout << "Loading player ship from " << path.str();
EDIT: The question has been edited and the code after the edit works, because it no longer uses path.str(p.str()); to create the output buffer without using an output operation (and without advancing the put pointer): see ideone for differences.
In any case, strings themselves can be concatenated, which would make the code easier to follow:
std::string p = path.str() + "Ship01.tga";
std::cout << p;
Not to mention that for dealing with files and pathnames, we have boost.filesystem.
I am trying to get a double to be a string through stringstream, but it is not working.
std::string MatlabPlotter::getTimeVector( unsigned int xvector_size, double ts ){
std::string tv;
ostringstream ss;
ss << "0:" << ts << ":" << xvector_size;
std::cout << ss.str() << std::endl;
return ss.str();
}
It outputs only "0:" on my console...
I'm working on two projects, both with the same problem. I'm posting a different one, which runs into the same problem. It is posted here:
http://pastebin.com/m2dd76a63
I have three classes PolyClass.h and .cpp, and the main. The function with the problem is PrintPoly. Can someone help me out? Thanks a bunch!!
You're printing correctly, however your logic in the order of printing is incorrect.
I modified it to work they way I think you wanted it to, let me know if this helps.
http://pastebin.com/d3e6e8263
Old answer:
Your code works, though ostringstream is in the std namespace. The problem is in your file printing code.
Can I see your call to the function?
I made a test case:
// #include necessary headers
int main(void)
{
std::string s;
s = MatlabPlotter::getTimeVector(1,1.0);
}
The output I get is 0:1:1
The following code is 100% correct:
#include <iostream>
#include <sstream>
#include <string>
// removed MatlabPlotter namespace, should have no effect
std::string getTimeVector(unsigned int xvector_size, double ts)
{
// std::string tv; // not needed
std::ostringstream ss;
ss << "0:" << ts << ":" << xvector_size;
std::cout << ss.str() << std::endl;
return ss.str();
}
int main(void)
{
// all work
// 1:
getTimeVector(0, 3.1415);
// 2: (note, prints twice, once in the function, once outside)
std::cout << getTimeVector(0, 3.1415) << std::endl;
// 3: (note, prints twice, once in the function, once outside)
std::string r = getTimeVector(0, 3.1415);
std::cout << r << std::endl;
}
Find where we differ, that's likely your source of error. Because it stops at your double, I'm guessing the double you're trying to print is infinity, NaN (not a number), or some other error state.
I can't really help with the "no output" part of this, as you didn't show your code that tries to output this. As a guess, did you perhaps not put an EOL in there somehow? Some systems won't give any text output until they hit a newline. You can do this by tacking a << std::endl onto your line, or a '\n' to your string.
Since you didn't put down a using for it, you need to use the type std::ostringstream. This is similar to how you had to use "std:string" instead of just "string".
Also, were it me, I'd get rid of that temp variable and just return ss.str(); It is less code (to possibly get wrong), and probabaly less work for the program.
Well, I tried the code you linked to and it outputs
B 4
A 5
B 4
C 3
x^ + 5x^ + 3
for me before crashing although the crash happens after PrintPoly. From looking at the code this is what I'd expect it to print. Are you saying you get no integers appearing after the letters?
Thanks all for your input! Not sure of the exact error, but it must be some setting in XCode which is messing it up. I made a CMakeLists.txt file and compiled it from the terminal using
cmake -G XCode ..
and produced an XCode project. I ran it, and now it works fine...now would anyone happen to know what might cause XCode to do this? I'm running version 3.2 with the following:
64-bit
Component versions
Xcode IDE: 1610.0
Xcode Core: 1608.0
ToolSupport: 1591.0