C++ stringstream returning extra character? - c++

I've been attempting to use the C++ stringstream class to do some relatively simple string manipulations, but I'm having a problem with the get() method. For some reason whenever I extract the output character by character it appends a second copy of the final letter.
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
int main() {
stringstream ss("hello");
char c;
while(!ss.eof()) {
ss.get(c);
cout << "char: " << c << endl;
}
return 0;
}
The output from the program is:
char: h
char: e
char: l
char: l
char: o
char: o
Any help you can give me on this would be appreciated.

At the end of the stream ss.eof() doesn't know yet that the end of the stream will be reached soon, but the following extraction of a character fails. Since the extraction failed because the end of the stream was reached, c is not changed. Your program doesn't recognize that ss.get(c) failed and prints that old value of c again.
A better way to check if there still is a character that can be read from the stream would be a loop like this:
while (ss.get(c)) {
cout << "char: " << c << endl;
}

its because of the order of the loop. Your reading the \0 and EOF.
reorder your code like this
int main() {
stringstream ss("hello");
char c;
ss.get(c);
while(!ss.eof()) {
cout << "char: " << c << endl;
ss.get(c);
}
return 0;
}

The EOF flag is only set if you attempt to read PAST the end of the file. The following code fixes the problem by testing for EOF after the get() instead of before it:
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
int main() {
stringstream ss("hello");
char c;
while(1) {
ss.get(c);
if(ss.eof())
break;
cout << "char: " << c << endl;
}
return 0;
}

Related

First character of cstring removed during ifstream c++

The first character of cstring keeps being removed upon the second execution of getline in ifstream:
#include <iostream>
#include <fstream>
using namespace std;
int main(){
char input[102];
ifstream keyTextFile("key.txt");
while (keyTextFile.getline(input, 102, '\n')) {
cout << input[0] << input[1] << endl;
cout << input << endl;
}
cout << input[0] << input[1] << endl;
keyTextFile.close();
return 0;
}
Currently, key.txt is one line:
0x0ffa331cc8765ddd
The code outputs:
0x
0x0ffa331cc8765ddd
x
The debugger shows input[0] changing from '0' to '\0' on the second execution of getline. How can I avoid this while allowing getline to scan a potentially large document?
please keep the answer to c-string implementation.

Cannot Print All Integer Values

I would like to print integer values in a file by reading it.
The code:
int temp;
char* trainname;
trainname="dfg.txt";
ifstream trainfile;
trainfile.open(trainname);
if(!trainfile){
cout<<"Cannot open file!"<<'\n';
exit(1);
}
while(trainfile >> temp)
cout << temp << " ";
trainfile.close();
dfg.txt: 1 2 we er rf 5
output: 1 2
The problem is that it does not print 5.
Read to a temporary string first and then use std::stoi to try to parse an integer from it, and if it succeeds, output it:
std::string temp;
while(trainfile >> temp) {
try {
std::cout << std::stoi(temp) << " ";
}
catch(const std::invalid_argument&) {
// not a valid number
}
}
while(trainfile >> temp)
cout << temp << " ";
The above sets the failbit on trainfile on encountering any character that isn't whitespace or a digit. That terminates the loop. This is one reason I tend not to use formatted I/O that can fail on a input stream. I find it better to read text as text (not numbers) and then process the string that was just read. For example, see zenith's answer.
If you insist on doing everything from the input stream, you'll need an outer loop that clears the stream's failbit. For example,
while (! std::cin.eof())
{
while (std::cin >> temp)
{
std::cout << temp << " ";
}
std::cin.clear();
std::cin.ignore();
}
Given an input file containing 1 2 we er rf 5, the above will print 1 2 5. If the input file contains 1 2 abc345def 6, the above will print 1 2 345 6. Note that zenith's approach will print 1 2 6. Whether that 345 sandwiched between abc and def counts as an integer is up to you.
I'd recommend using zenith's solution over mine.
Update:
The above interprets abc345def as representing the integer 345. Both Zenith's solution and the above interpret 345def as representing the integer 345. To me, both abc345def and 345def should be rejected as representing an integer. So should 6.1 , but there's nothing wrong with 0x abc345def. There's nice tool in the C standard library, strtol, that nicely parses integers. It also indicates what made the parse stop. For a valid integer, it should stop at the end of the input string. With that,
#include <iostream>
#include < fstream>
#include <string>
#include <cstdlib>
int main ()
{
std::ifstream trainfile("dfg.txt");
if (!trainfile)
{
std::cerr << "Cannot open file!\n";
exit(1);
}
std::string s;
while(trainfile >> s)
{
char* end;
long num = std::strtol (s.data(), &end, 0);
if (!*end)
{
std::cout << num << " ";
}
}
trainfile.close();
std::cout << "\n";
}
string temp;
if( '0' <= temp[0] && temp[0]<='9' )
cout << temp << " ";
it will work i suppose.
Here is another way you can consider-
#include <iostream>
#include <sstream>
#include <fstream>
using namespace std;
int main()
{
ifstream trainname("dfg.txt",ios::in);
string temp;
getline(trainname,temp);
stringstream str;
str<<temp;
int extract_int;
while(getline(str, temp,' '))
{
if(stringstream(temp)>>extract_int)
cout<<extract_int<<" ";
}
return 0;
}
Or according to David Hammen's answer, you can solve it the following way-
#include <iostream>
#include <sstream>
#include <fstream>
using namespace std;
int main()
{
int temp;
char* trainname;
trainname="dfg.txt";
ifstream trainfile;
trainfile.open(trainname);
if(!trainfile){
cout<<"Cannot open file!"<<'\n';
exit(1);
}
while (!trainfile.eof())
{
while (trainfile>>temp)
cout<<temp<< " ";
trainfile.clear();
trainfile.ignore();
}
return 0;
}

Convert string to char for ascii

I want to ask for word from the user and then convert the word from string to char using 'strcpy'. Then I want to determine the sum of the ascii codes for all of the letters in the word.
However, I am having difficulties. I don't understand exactly how I can do that. This is what I have been able to do so far.
#include <iostream>
#include <time.h>
#include <stdlib.h>
#include <string.h>
using namespace std;
int main()
{
string word;
cout << "Enter word: ";
getline(cin, word);
/*
char w[word];
strcpy(w,word.c_str());
int ('A');
cout<<char(65);
*/
return 0;
}
The commented part is where I have been trying to do the converting. I copied the code from a worksheet. Even if it did work, I don't know how, and what it all means.
Thanks for your help.
char w[word];
strcpy(w, word.c_str());
char w[word] is incorrect. The square brackets is for the size, which must be a constant integral expression. word is of type std::string, so this makes neither logical nor practical sense. Maybe you meant it as:
char w = word;
But that still won't work because word is a string, not a character. The correct code in this case is:
char* w = new char[word.size() + 1];
That is, you allocate the memory for w using a char*. Then you use word.size() + 1 to initialize heap-allocated memory amounting to those bytes. Don't forget for the obligatory delete[] when you're finished using w:
delete[] w;
However, note that using raw pointers and explicit new is not needed in this case. Your code can easily be cleaned up into the following:
#include <numeric>
int main ()
{
std::string word;
std::getline(std::cin, word);
int sum = std::accumulate(word.begin(), word.end(), 0); /*
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ */
std::cout << "The sum is: " << sum << std::endl;
}
You don't need to use strcpy() (or use a char * at all, for that matter), but this'll do your counting using a char pointer:
#include <iostream>
#include <string>
int main() {
std::string word;
std::cout << "Enter word: ";
std::cin >> word;
const char * cword = word.c_str();
int ascii_total = 0;
while ( *cword ) {
ascii_total += *cword++;
}
std::cout << "Sum of ASCII values of characters is: ";
std::cout << ascii_total << std::endl;
return 0;
}
Output:
paul#local:~/src/cpp/scratch$ ./asccount
Enter word: ABC
Sum of ASCII values of characters is: 198
paul#local:~/src/cpp/scratch$
If you really do want to use strcpy(), I'll leave it as an exercise to you to modify the above code.
Here's a better way to do it, just using std::string (and C++11, and obviously presuming your system uses the ASCII character set in the first place):
#include <iostream>
#include <string>
int main() {
std::string word;
std::cout << "Enter word: ";
std::cin >> word;
int ascii_total = 0;
for ( auto s : word ) {
ascii_total += s;
}
std::cout << "Sum of ASCII values of characters is: ";
std::cout << ascii_total << std::endl;
return 0;
}

In what practical case bool(std::ifstream) != std::ifstream::good()?

I would like to know in what case we can have :
bool(std::ifstream) != std::ifstream::good()
The difference is that bool(std::ifstream) does not test the eof bit whereas std::ifstream::good() tests it. But practically, the eof bit is raised if one try to read something after the end of the file. But as soon as you try to do this I think that either fail or bad bit is also set.
Consequently in what case you can only raise the eof bit ?
Simply put, whenever you encounter the end of a file without attempting to read behind it. Consider a file "one.txt" which contains exactly one single '1' character.
Example for unformatted input:
#include <iostream>
#include <fstream>
int main()
{
using namespace std;
char chars[255] = {0};
ifstream f("one.txt");
f.getline(chars, 250, 'x');
cout << f.good() << " != " << bool(f) << endl;
return 0;
}
0 != 1
Press any key to continue . . .
Example for formatted input:
#include <iostream>
#include <fstream>
int main()
{
using namespace std;
ifstream f("one.txt");
int i; f >> i;
cout << f.good() << " != " << bool(f) << endl;
return 0;
}
0 != 1
Press any key to continue . . .

Is it possible to "prepare" input from cin?

In his answer, specifically in the linked Ideone example, #Nawaz shows how you can change the buffer object of cout to write to something else. This made me think of utilizing that to prepare input from cin, by filling its streambuf:
#include <iostream>
#include <sstream>
using namespace std;
int main(){
streambuf *coutbuf = cout.rdbuf(cin.rdbuf());
cout << "this goes to the input stream" << endl;
string s;
cin >> s;
cout.rdbuf(coutbuf);
cout << "after cour.rdbuf : " << s;
return 0;
}
But this doesn't quite work as expected, or in other words, it fails. :| cin still expects user input, instead of reading from the provided streambuf. Is there a way to make this work?
#include <iostream>
#include <sstream>
int main()
{
std::stringstream s("32 7.4");
std::cin.rdbuf(s.rdbuf());
int i;
double d;
if (std::cin >> i >> d)
std::cout << i << ' ' << d << '\n';
}
Disregard that question, while further investigating it, I made it work. What I did was actually the other way around than planned; I provided cin a streambuf to read from instead of filling its own.
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
int main(){
stringstream ss;
ss << "Here be prepared input for cin";
streambuf* cin_buf = cin.rdbuf(ss.rdbuf());
string s;
while(cin >> s){
cout << s << " ";
}
cin.rdbuf(cin_buf);
}
Though it would still be nice to see if it's possible to provide prepared input without having to change the cin streambuf directly, aka writing to its buffer directly instead of having it read from a different one.