Stringstream don't copy new lines - c++

Special characters disappear when I pass a string into a stringstream.
I tried this code which can directly be tested:
#include <iostream>
#include <sstream>
using namespace std;
int main(int argc, char* argv[]) {
string txt("hehehaha\n\t hehe\n\n<New>\n\ttest:\t130\n\ttest_end:\n<New_end>\n");
cout << txt << endl; // No problem with new lines and tabs
stringstream stream;
stream << txt;
string s;
while(stream >> s) {
cout << s; // Here special characters like '\n' and '\t' don't exist anymore.
}
cout << "\n\n";
return 0;
}
What can I do to overcome this?
Edit: I tried this:
stream << txt.c_str();
and it worked. But I don't know why...

basically, you are just printing it wrong, it should be:
cout << stream.str() << endl;
Some details. You are calling operator<<(string) which
overloads operator<< to behave as described in ostream::operator<<
for c-strings
The referred to behaviour is explained here:
(2) character sequence Inserts the C-string s into os. The terminating
null character is not inserted into os. The length of the c-string is
determined beforehand (as if calling strlen).
Strlen documentation says that the result is affected by nothing but
the terminating null-character
Indeed, strlen(tmp) in your examples outputs 55.
The stream, hence, gets "assigned" everything which comes up to the 55th character in your input string.
cout << stream.str() << endl;
will show you that this is indeed what happens.
A parenthesis: you can modify the behaviour of the stream << txt line by means of setting/unsetting flags, as in
stream.unsetf ( std::ios::skipws );
which you should try out.

The statement
while(stream >> s)
Is the problem, it gives you one token on each call, using white spaces for splitting and therefor ignoring them.

Related

C++ c_str() doesn't return complete string

I'm doing a C++ assignment that requires taking user input of an expression (eg: 2 * (6-1) + 2 ) and outputting the result. Everything works correctly unless a space is encountered in the user input.
It is a requirement to pass the user input to the following method;
double Calculate(char* expr);
I'm aware the issue is caused by c_str() where the space characters act as a terminating null byte, though I'm not sure how to overcome this problem.
Ideally I'd like to preserve the space characters but I'd settle for simply removing them, as a space serves no purpose in the expression. I get the same result when using string::data instead of c_str.
int main(int argc, char **argv)
{
string inputExpr;
Calc myCalc;
while(true) {
cin >> inputExpr;
if(inputExpr == "q") break;
cout << "You wrote:" << (char*)inputExpr.c_str() << endl; // debug
printf("Result: %.3f \n\n", myCalc.Calculate( (char*)temp.c_str() ) );
}
return 0;
}
c_str works just fine. Your problem is cin >> inputExpr. The >> operator only reads until the next space, so you do not read your equation fully.
What you want to use is std::getline:
std::getline (std::cin,inputExpression);
which will read until it reaches a newline character. See the function description if you need a specific delimiter.
Problem is not with inputExpr.c_str() and c_str as such, c_str() returns pointer to a character array that contains a null-terminated sequence. While reading through cin, you get space or tab etc separating as multiple strings. Check with the content of the string that way to solve the intended operation
First, I think your Calculate() method should take as input a const char* string, since expr should be an input (read-only) parameter:
double Calculate(const char* expr);
Note that if you use const char*, you can simply call std::string::c_str() without any ugly cast to remove const-ness.
And, since this is C++ and not C, using std::string would be nice:
double Calculate(const std::string& expr);
On the particular issue of reading also whitespaces, this is not a problem of terminating NUL byte: a space is not a NUL.
You should just change the way you read the string, using std::getline() instead of simple std::cin >> overload:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string line;
getline(cin, line);
cout << "'" << line << "'" << endl;
}
If you compile and run this code, and enter something like Hello World, you get the whole string as output (including the space separating the two words).

C++/ ofstream with only a string type

Here is my code:
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
int main() {
string nom_fich("data.dat");
ofstream fichier(nom_fich.c_str());
string name;
cout <<"The name is: "<< name ;
cin>>ws;
if (getline(cin, name)){
fichier << name <<endl;
} else {
cerr <<"Error!";
}
fichier.close();
return 0;
}
Question: why if I enter a number instead of a string my program doesn't say me "Error!" ?
EDIT: how can I attempt to my purpose ? I want that get an "Error!" when I enter a type that isn't a type string.
Because a number is a valid string.
Numbers can be represented as strings, i.e. strings can contain digit characters. For example:
std::string my_string("42");
std::cout << my_string[0]; // prints 4
std::cout << my_string[1]; // prints 2
You can't enter a number. You can enter a sequence of characters that can be interpreted as a number, but that sequence is still characters. Those characters arw what getline reads.
A number can be represented as a string, so std::ifstream::operator >> takes the intuitive approach: it treats any sequence of non-blank characters as a string. This includes decimal digits as well.
Unrelated, but instead of creating a superfluous nom_fich temporary variable for the name, you could just write ofstream fichier("data.dat");.
Because the string "123" is just as valid as the string "abc", or the string "def999".
As for "how can I attempt to my purpose?", you'd have to explain to us what your purpose is because, by your own admission, your own code does not describe that purpose and therefore we cannot extract your purpose from it.
Reading a number as a string will certainly work: the number is just represented as a sequence of characters. If you want the stream to attempt reading a number and fail if it doesn't get one, you'd use a different type to read, e.g.:
int number;
if (std::cin >> number) {
std::cout << "ERROR: read a number: " << number << '\n';
}
else if (std::cin.clear(), std::getline(std::cin, name)) {
std::cout << "read a name: " << name << '\n';
}
After the unsuccessful read of a number the stream's state is clear()ed and, instead, it is attempted to read a name. There is a subtle issue as the formatted input for an int will skip leading whitespace while std::getline() doesn't skip whitespace. If skipping leading whitespace is a problem just use the manipulator std::noskipws before trying to read an int.

Getting input from file troubles C++

I've been trying to read some information in from a .txt file in C++ but it's not all working like I expect. Here is some example code:
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
char words[255];
int value = 0;
ifstream input_stream("test.txt");
input_stream >> value;
input_stream.getline(words, 256);
cout << value << endl;
cout << words << endl;
}
And test.txt contains:
1234
WordOne WordTwo
What I expect is for the code to print the two lines contained in the text file, but instead I just get:
1234
I've been reading about getline and istream but can't seem to find any solutions so any help would be appreciated.
Thanks
The newline character remains in the input stream after the read of the integer:
// Always check result to ensure variables correctly assigned a value.
if (input_stream >> value)
{
}
Then, the call to getline() reads the newline character and stops, producing an empty string. To correct, consume the newline character before calling getline() (options include using getline() or ignore()).
Note there is a version std::getline() that accepts a std::string as its argument to avoid using a fixed sized array of char, which is used incorrectly in the posted code.
ifstream's getline method gathers input until one of two options is hit. Either a terminating character or the size passed in is reached. In your case, the newline terminator is encountered before the size is reached.
Use another getline to retrieve the second line of text.
Reference
The problem you are seeing is that the first newline after 1234 is not consumed by input_stream>>(int); so the next getline only reads to the end of that file.
This is a very constructed scenario, commonly found in schoolwork. The more common scenario when reading a textfile is to consider the entire file as linebased text.
In this case the more convenient
string line;
while( std::getline( input_stream, line ) ){
}
is appropriate, and way less error prone.
The textfile would commonly have a predefined format. Perhaps name = value lines, and are parsed as such after the line is read from the file.
Here is a somewhat corrected version of your original code:
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
char words[256]; // was 255
int value = 0;
ifstream input_stream("test.txt");
input_stream >> value;
input_stream.ignore(); // skip '\n'
input_stream.getline(words, 256);
cout << value << endl;
cout << words << endl;
}
Also, I would advise you to use a string instead of a char[] and use the other getline function.

C++ Fstream Only Prints One Word

This is a very strange issue. I'm trying to print a large text file, it's a Wikipedia entry. It happens to be the page on Velocity. So, when I tell it to print the file, it prints "In", when it should print "In physics, velocity is etc, etc etc".
Here's the code I'm using to print out:
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
ifstream wiki;
wiki.open("./wiki/velocity.txt");
char* wikiRead;
wiki >> wikiRead;
cout << wikiRead << endl;
wiki.close();
}
Please help.
wiki >> wikiRead;
The default delimiter for stream is space, so when the stream encounters a space, it simply stops reading, that is why it reads only one word.
If you want the stream to read all words, the you've to use a loop as:
char* wikiRead = new char[1024]; //must allocate some memory!
while(wiki >> wikiRead)
{
cout << wikiRead << endl;
}
wiki.close();
delete []wikiRead; //must deallocate the memory
This will print all the words in the file, each on a new line. Note if any of the word in the file is more than 1024 character long, then this program would invoke undefined behavior, and the program might crash. In that case, you've to allocate a bigger chunk of memory.
But why use char* in the first place? In C++, you've better choice: Use std::string.
#include<string>
std::string word;
while(wiki >> word)
{
cout << word << endl;
}
wiki.close();
Its better now.
If you want to read line-by-line, instead of word-by-word, then use std::getline as:
std::string line;
while(std::getline(wiki, line))
{
cout << line << endl;
}
wiki.close();
This will read a complete line, even if the line contains spaces between the words, and will print each line a newline.
You ask the stream to read the (binary) value of a pointer (probably 4 bytes, depending on your machine architecture), then you ask it to print the text pointed to by those 4 bytes!
I wonder why you ignored the compiler warning (most of the modern compiler warns you about using uninitialized variables). How about this?
ifstream wiki;
wiki.open("./wiki/velocity.txt");
char wikiRead[255];
wiki >> wikiRead;
cout << wikiRead << endl;
wiki.close();
Alternatively I'd suggest you to use string object with getline to get a single line of text.
string str;
getline(wiki, str);
The >> operator applied to a char * reads only one word. Moreover, you're reading into an uninitialized pointer, which is not valid. Usually std::string, not char *, is used for string processing in C++.
If you only want to print the file's contents, you can hook the file's buffer directly to std::cout:
int main() {
std::ifstream wiki("./wiki/velocity.txt");
std::cout << wiki.rdbuf() << '\n';
}
If you want to put the contents into an automatically-allocated string, use std::getline with the delimiter disabled.
int main() {
std::ifstream wiki("./wiki/velocity.txt");
std::string wiki_contents;
getline( wiki, wiki_contents, '\0' /* do not stop at newline */ );
std::cout << wiki_contents << '\n'; // do something with the string
}
Since you want to read a large file, reading it block by block is a better way.
ifstream wiki;
wiki.open("./wiki/velocity.txt");
const int buf_size = 1024;
char* wikiRead = 0;
int cnt = 1;
do
{
wikiRead = realloc( wikiRead, bufsize*cnt );
wiki.Read( wikiRead + (bufSize*(cnt-1)), buf_size ); //appends to reallocated memory
cnt++;
}while( !wiki.eof())
wikiRead[(bufSize*(cnt-2)) + wiki.gcount() + 1] = '\0'; // null termination.
wiki.Close();
cout << wikiRead;
delete[] wikiRead;
The operator>> is designed to only read one word at a time. If you want to read lines, use getline.
#include <iostream>
#include <fstream>
#include<string>
using namespace std;
int main()
{
ifstream wiki;
wiki.open("./wiki/velocity.txt");
string wikiRead;
while (getline(wiki, wikiRead))
{
cout << wikiRead << endl;
}
wiki.close();
}

How to read the string into a file C++

i have a little problem on writing the string into a file,
How can i write the string into the file and able to view it as ascii text?
because i am able to do that when i set the default value for str but not when i enter a str data
Thanks.
#include <iostream>
#include <fstream>
#include <cstring>
using namespace std;
int main()
{
fstream out("G://Test.txt");
if(!out) {
cout << "Cannot open output file.\n";
return 1;
}
char str[200];
cout << "Enter Customers data seperate by tab\n";
cin >> str;
cin.ignore();
out.write(str, strlen(str));
out.seekp(0 ,ios::end);
out.close();
return 0;
}
Please use std::string:
#include <string>
std::string str;
std::getline(cin, str);
cout << str;
I'm not sure what the exact problem in your case was, but >> only reads up to the first separator (which is whitespace); getline will read the entire line.
Just note that >> operator will read 1 word.
std::string word;
std::cin >> word; // reads one space seporated word.
// Ignores any initial space. Then read
// into 'word' all character upto (but not including)
// the first space character (the space is gone.
// Note. Space => White Space (' ', '\t', '\v' etc...)
You're working at the wrong level of abstraction. Also, there is no need to seekp to the end of the file before closing the file.
You want to read a string and write a string. As Pavel Minaev has said, this is directly supported via std::string and std::fstream:
#include <iostream>
#include <fstream>
#include <string>
int main()
{
std::ofstream out("G:\\Test.txt");
if(!out) {
std::cout << "Cannot open output file.\n";
return 1;
}
std::cout << "Enter Customer's data seperated by tab\n";
std::string buffer;
std::getline(std::cin, buffer);
out << buffer;
return 0;
}
If you want to write C, use C. Otherwise, take advantage of the language you're using.
I can't believe no one found the problem. The problem was that you were using strlen on a string that wasn't terminated with a null character. strlen will keep iterating until it finds a zero-byte, and an incorrect string length might be returned (or the program might crash - it's Undefined Behavior, who knows?).
The answer is to zero-initialize your string:
char str[200] = {0};
Supplying your own string as the value of str works because those in-memory strings are null-terminated.