How do you add a new line to a c++ string? I'm trying to read a file but when I try to append '\n' it doesn't work.
std::string m_strFileData;
while( DataBegin != DataEnd ) {
m_strFileData += *DataBegin;
m_strFileData += '\n';
DataBegin++;
}
If you have a lot of lines to process, using stringstream could be more efficient.
ostringstream lines;
lines << "Line 1" << endl;
lines << "Line 2" << endl;
cout << lines.str(); // .str() is a string
Output:
Line 1
Line 2
Sorry about the late answer, but I had a similar problem until I realised that the Visual Studio 2010 char* visualiser ignores \r and \n characters. They are completely ommitted from it.
Note: By visualiser I mean what you see when you hover over a char* (or string).
Just a guess, but perhaps you should change the character to a string:
m_strFileData += '\n';
to be this:
m_strFileData += "\n";
This would append a newline after each character, or string depending on what type DataBegin actually is. Your problem does not lie in you given code example. It would be more useful if you give your expected and actual results, and the datatypes of the variables use.
Try this:
ifstream inFile;
inFile.open(filename);
std::string entireString = "";
std::string line;
while (getline(inFile,line))
{
entireString.append(line);
entireString.append("\n");
}
Related
My problem in a larger project is that std::getline() returns an empty string. Here's my code snippet:
int main() {
std::ifstream reading_file;
reading_file.open("smalldata-n.txt", std::ios::in);
std::string line;
std::getline(reading_file, line);
std::cout << "1. first line is: " << line << std::endl;
return 0;
}
The first line has very important information for the rest of the code.
At first, I thought maybe the problem is from the data format but when using another simple text file I encounter the same problem again.
I can't see what I have missed and it looks fine according to other samples on the web.
I have made a little program that loops line by line through file. Everything worked fine with UNIX line endings :
std::ifstream file(filename);
while (std::getline(file, str))
{
std::sort(str.begin(), str.end());
std::cout << str << ""; ----- WORKS as expected
}
When using DOS line endings, the std::getline does not return a line. So more trial end error got me thinking, that I should, probably, delimit at " ". And that works:
std::ifstream file(filename);
while (std::getline(file, str, ' '))
{
std::cout << str << ""; -- returns a line
std::sort(str.begin(), str.end());
std::cout << str << ""; ----- does not work like the first time
}
The second try prints out a line normally but when inputing that line to sort it works unexpectedly. So my question is why is std::sort working differently at the second time? My first idea was that maybe variable type is different but that led to nowhere. What am I missing? Is it possible to get it working like in the first code block?
Instead of
std::cout << str << "";
you should try
std::cout << str << std::endl;
to get a new line in a proper way on all operating systems.
This code always prints the last line of the file. I expected it to print all the text, one line at a time, from the file. Any idea why it doesn't work?
string filename;
cout << "File to read: ";
cin >> filename;
ifstream afile;
afile.open(filename.c_str());
string line;
while(!afile.eof()) {
getline(afile, line);
cout << line;
}
afile.close();
Trying it this way does the same thing:
for (string line; getline(afile, line);) {
cout << line;
}
Maybe this is an issue with my terminal? This works...
for (string line; getline(afile, line);) {
cout << line << endl;
}
The problem is that only the last line is printed. Correct?
I suggest that you add std::endl in your while loop. It can make the issue more clear. Sometimes the output can be confusing.
You can also check the line-delimiting character in your input file. '\n' is the default delimiter for getline. If a different character is used, specify it as getline's 3rd parameter.
From cplusplus.com:
If the delimiter is found, it is extracted and discarded, i.e. it is
not stored and the next input operation will begin after it.
Since your original code snippet doesn't insert any extra newlines itself, there is nothing making the output to the terminal go to the next line. When the output runs out of horizontal space what happens next is up to the terminal. I'm not sure what terminal you're using but in your case, it just wraps the cursor back to the first character on that line without a linefeed. On a windows command shell, it just wraps around to the next line.
Also note that:
while(!afile.eof()) {
getline(afile, line);
cout << line;
}
is a common antipattern. As already pointed out, more appropriate would be:
while(getline(afile, line)) {
cout << line << '\n';
}
The file stream only becomes false after you've reached eof and try to read from it.
I am using boost::split to parse a data file. The data file contains lines such as the following.
data.txt
1:1~15 ASTKGPSVFPLAPSS SVFPLAPSS -12.6 98.3
The white space between the items are tabs. The code I have to split the above line is as follows.
std::string buf;
/*Assign the line from the file to buf*/
std::vector<std::string> dataLine;
boost::split( dataLine, buf , boost::is_any_of("\t "), boost::token_compress_on); //Split data line
cout << dataLine.size() << endl;
For the above line of code I should get a print out of 5, but I get 6. I have tried to read through the documentation and this solution seems as though it should do what I want, clearly I am missing something. Thanks!
Edit:
Running a forloop as follows on dataLine you get the following.
cout << "****" << endl;
for(int i = 0 ; i < dataLine.size() ; i ++) cout << dataLine[i] << endl;
cout << "****" << endl;
****
1:1~15
ASTKGPSVFPLAPSS
SVFPLAPSS
-12.6
98.3
****
Even though "adjacent separators are merged together", it seems like the trailing delimeters make the problem, since even when they are treated as one, it still is one delimeter.
So your problem cannot be solved with split() alone. But luckily Boost String Algo has trim() and trim_if(), which strip whitespace or delimeters from beginning and end of a string. So just call trim() on buf, like this:
std::string buf = "1:1~15 ASTKGPSVFPLAPSS SVFPLAPSS -12.6 98.3 ";
std::vector<std::string> dataLine;
boost::trim_if(buf, boost::is_any_of("\t ")); // could also use plain boost::trim
boost::split(dataLine, buf, boost::is_any_of("\t "), boost::token_compress_on);
std::cout << out.size() << std::endl;
This question was already asked: boost::split leaves empty tokens at the beginning and end of string - is this desired behaviour?
I would recommend using C++ String Toolkit Library. This library is much faster than Boost in my opinion. I used to use Boost to split (aka tokenize) a line of text but found this library to be much more in line with what I want.
One of the great things about strtk::parse is its conversion of tokens into their final value and checking the number of elements.
you could use it as so:
std::vector<std::string> tokens;
// multiple delimiters should be treated as one
if( !strtk::parse( dataLine, "\t", tokens ) )
{
std::cout << "failed" << std::endl;
}
--- another version
std::string token1;
std::string token2;
std::string token3:
float value1;
float value2;
if( !strtk::parse( dataLine, "\t", token1, token2, token3, value1, value2) )
{
std::cout << "failed" << std::endl;
// fails if the number of elements is not what you want
}
Online documentation for the library: String Tokenizer Documentation
Link to the source code: C++ String Toolkit Library
Leading and trailing whitespace is intentionally left alone by boost::split because it does not know if it is significant or not. The solution is to use boost::trim before calling boost::split.
#include <boost/algorithm/string/trim.hpp>
....
boost::trim(buf);
I'm opening a file, and getting lines from it.
The first line should say how many variables there are, and what their names are.
The second line should be a logic equation using these variables.
The assignment is to have it print out a truth table for the variables and equation.
The first line the program is taking in is not printing without me inserting a new line character. I tried converting to a string and using both printf and cout.
Main file that inputs everything:
#include "truthTable2.h"
int main(int argc, const char* argv[]){
ifstream inFile;
if(argc != 2){
cout << "Enter an input file name: ";
char *inFileName = "";
cin >> inFileName;
inFile.open(inFileName);
}
else
inFile.open(argv[1]);
TruthTable tTable;
while(!inFile.eof()){
char variableLine[256];
inFile.getline(variableLine, 256);
printf("%s ", variableLine);
string variable(variableLine);
tTable.setVariables(variable);
char formulaLine[256];
inFile.getline(formulaLine, 256);
cout << formulaLine << "\n";
string formula(formulaLine);
tTable.setFormula(formula);
tTable.printTable();
}
inFile.close();
return 0;
}
Sample input:
2 x y
( \wedge x ( \not y ) )
Output from this:
( \wedge x ( \not y ) )
I think whatever is causing this is giving me problems throughout the rest of the program as well. After I tokenize the variableLine it does not print without a new line character and it does not find the second variable when evaluating the formula.
An std::ostream's output needs to be flushed. It is normally flushed automatically when a line-feed \n is written. If you want to force the stream to flush, you can use the std::flush manipulator like so:
std::cout << "foo" << std::flush;
Edit: Although my post clearly answers the question "Why does my line not show up unless I output a \n character?" You said this does not answer your question, so I will attempt some mind reading to try and answer your real question.
Since I have no idea what you really want know, I'll point out several things here that are wrong with your code and it might help you find your problem or clarify your question.
First, if you are using the file name input from std::cin, when argc<2, you will, a 100% guaranteed, cause a failure in your application. The reason is that the character buffer pointed to by inFileName contains a single byte, reserved for the terminating null character. If someone enters any text whatsoever, you will get a buffer overrun. If someone enters an empty string, your program will open no file and inFile.open(...); will return an error code that you don't check, so your program won't crash, but still won't work.
Second, the other line inputs are needlessly limited to 256 characters and are just as dangerous (i.e. lines longer that 256 characters will cause a bufer overrun). Since you eventually create std::string instances out of the content, you should just plainly use std::getline(). It is shorter to type, more general and safer.
Third, the description of your problem is that no output is generated unless you add a \n character. As I explained, this is perfectly normal. From re-reading your post, I can understand that you don't unhderstand why you should have to add one given that there was already one in the input file. The reason you need to add it is because the getline() functions discard the \n character. It is not inserted into your line's buffer.
I've cleaned up some of your code to show you some clear improvements. From this code you will be able to understand the structure of your program, which should also reflect the structure of your input.
#include "truthTable2.h"
int main(int argc, const char* argv[]){
std::ifstream inFile;
if(argc != 2){
cout << "Enter an input file name: ";
std::string inFileName;
std::getline(std::cin, inFileName);
inFile.open(inFileName.c_str());
}
else {
inFile.open(argv[1]);
}
if ( !inFile.is_open() ) {
// Did not successfully open a file. Print error message and exit!
}
TruthTable tTable;
for (std::string variables; std::getline(inFile,variables); )
{
std::cout << variables << std::endl;
tTable.setVariables(variable);
std::string formula std::getline(formula);
std::cout << formula << std::endl;
tTable.setFormula(formula);
tTable.printTable();
}
return 0;
}
From this, I have a question:how is your input structured? Is your input file only consisted of 2 lines? Are there multiple sets of these line pairs? Is there a single line with variables and a bunch of equations? These three cases will lead me to re-structure the program in one of the following fashions:
2 lines only:
ThruthTable table;
std::string variables, equation;
std::getline(file, variables);
std::getline(file, equation);
// ...
Multiple sets:
while ( !inFile.eof() )
{
ThruthTable table;
std::string variables, equation;
std::getline(file, variables);
std::getline(file, equation);
// ...
}
Multiple equations:
ThruthTable table;
std::string variables;
std::getline(variables);
for ( std::string equation; std::getline(file, equation); )
{
std::getline(file, equation);
// ...
}
If what I am seeing is right, the output from printf is the one that is not showing. In that case, either use
fflush(stdout);
Or better, just go with a std::cout for that line since you're writing it in C++ (using the std::flush technique, of course.)