Variables Not Updating From istringstream - c++

So, I've got code like the following:
#include <iostream>
#include <string>
#include <sstream>
#include <fstream>
#include <cctype>
using namespace std;
int main(int argc, char *argv[])
{
char c;
ifstream f("test.txt");
char n;
char z;
char o;
int output;
istringstream in;
string line;
while (getline(f, line))
{
in.str(line);
do
{
c = in.get();
}
while (isspace(c));
in.unget();
in >> n >> c >> z >> c >> o >> c >> output;
cout << n << z << o << output << endl;
in.str(string());
}
f.close();
return 0;
}
and the file test.txt contains:
A,B,C,1
B,D,F,1
C,F,E,0
D,B,G,1
E,F,C,0
F,E,D,0
G,F,G,0
The format of each line in the text file is "char,char,char,bool" (I'm ignoring the fact that there may be whitespace in the middle of the line, for now).
When I compile and run this code ((using Visual Studio 2010), I get:
ABC1
ABC1
ABC1
ABC1
ABC1
ABC1
ABC1
Obviously, this isn't what I want. Does anyone have an answer as to what's going on here?

A quick fix, put istringstream inside the loop to reset the input indicator:
//istringstream in; ----------+
string line; |
while (getline(f, line)) |
{ |
istringstream in; <--------+
in.str(line);
do
{
c = in.get();
}
while (isspace(c));
in.unget();
in >> n >> c >> z >> c >> o >> c >> output;
cout << n << z << o << output << endl;
//in.str(string()); <-------------------- you can remove this line
}
f.close();
If you don't reset the input indicator, the in.get will not work as you expect. or you can simply use seekg(0)

When you change the content of the stringstream, by default it will set the position pointer to the end of the stream: http://www.cplusplus.com/reference/sstream/stringstream/str/. Add in.seekg(0); after in.str(line); and it should work:
#include <iostream>
#include <string>
#include <sstream>
#include <fstream>
#include <cctype>
using namespace std;
int main(int argc, char *argv[])
{
char c;
ifstream f("test.txt");
char n;
char z;
char o;
int output;
istringstream in;
string line;
while (getline(f, line))
{
in.str(line);
in.seekg(0);
do
{
c = in.get();
}
while (isspace(c));
in.unget();
in >> n >> c >> z >> c >> o >> c >> output;
cout << n << z << o << output << endl;
in.str(string());
}
f.close();
return 0;
}

Related

Get more values with istringstream

When I input [1,0,0,1,0] I get output with 1 0 0 1 0 0, I don't know why there is an extra zero and why the while loop doesn't terminate after ].
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
int main()
{
std::string str;
std::istringstream is;
std::vector<int> numbers;
std::getline(std::cin, str);
is.str(str);
char ch;
is >> ch;
while (!is.eof())
{
int num;
is >> num >> ch;
numbers.push_back(num);
}
for (auto num : numbers)
std::cout << num << " ";
std::cout << std::endl;
return 0;
}
Change the while loop part will get expected behavior:
int num;
while (is >> num >> ch) {
numbers.push_back(num);
}
The eof check is misused here, so the last character read failed and get a default number 0. Read this answer for more details:
https://stackoverflow.com/a/4533102/1292791

Trying to write a program that produces sum of all whitespace-separated integers in a text file

I'm not getting any errors, just an infinite loop! Here's my code:
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
#include<cmath>
#include<fstream>
#include<assert.h>
using namespace std;
inline void keep_window_open() { char ch; cin >> ch; }
int main() {
int sum{ 0 }, number;
vector<int> numbers;
string word;
fstream file;
file.open("file1.txt", fstream::in);
while (true) {
file >> number;
if (file.eof()) {
numbers.push_back(number);
break;
}
else if (file.fail()) { file >> word; }
else if (file.bad()) exit(1);
else numbers.push_back(number);
}
for (int x : numbers) sum += x;
cout << sum << "\n";
}
The file I am reading from:
words 32 jd: 5 alkj 3 12 fjkl
23 / 32
hey 332 2 jk 23 k 23 ksdl 3
32 kjd 3 klj 332 c 32
You are not reading the integers properly, or correctly checking if operator>> is successful before using number. And more importantly, you are not clearing the stream's error state when non-integer input is encountered by operator>>.
Try something more like this instead:
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <fstream>
#include <stdexcept>
using namespace std;
inline void keep_window_open() { char ch; cin >> ch; }
int main() {
int sum = 0, number;
vector<int> numbers;
string word;
ifstream file("file1.txt");
while (file >> word) {
try {
number = stoi(word);
}
catch (const std::exception &) {
continue;
}
numbers.push_back(number);
}
if (file.fail() && !file.eof())
exit(1);
for (int x : numbers)
sum += x;
cout << sum << "\n";
keep_window_open();
return 0;
}
Live Demo
See if this works:
#include<iostream>
#include<fstream>
#include <cctype> // isdigit
#include<string>
#include<vector>
using namespace std;
inline void keep_window_open() { char ch; cin >> ch; }
int main() {
int sum{ 0 };
string number; // new
vector<int> numbers;
fstream file;
file.open("file1.txt", fstream::in);
while (true) {
file >> number;
if (file.eof())
break;
if (isdigit(number[0])) // new
numbers.push_back(stoi(number));
}
file.close();
for (int x : numbers) sum += x;
cout << sum << "\n";
return 0;
}

Iterating through a string with sstream

Here is a piece of code:
#include <sstream>
#include <iostream>
using namespace std;
int main()
{
stringstream ss;
string st = "2,3,55,33,1124,34";
int a;
char ch;
ss.str(st);
while(ss >> a)
{
cout << a << endl;
ss >> ch;
}
return 0;
}
It produces the output:
2
3
55
33
1124
34
But if I remove the line ss >> ch it produces the output: 2.
Why does it stop iterating through the string? And what difference does ss >> ch make?
What difference does ss >> ch make?
ss >> ch takes a character from your stream an store it in your char ch variable.
So here it removes each and every comma (,) from your string.
Why does it stop iterating through the string without ss >> ch?
Without this operation, your iteration stops because ss >> a fails, since it tries to store a comma inside a, an int variable.
Note: If you replace your commas with spaces, you could get rid of ss >> ch, since a space is recognized as a separator.
Example:
#include <sstream>
#include <iostream>
using namespace std;
int main()
{
stringstream ss;
string st = "2 3 55 33 1124 34";
int a;
ss.str(st);
while (ss >> a)
cout << a << endl;
return 0;
}
You can also use this if you like to keep the commas
#include <sstream>
#include <iostream>
using namespace std;
int main()
{
stringstream ss;
string st = "2,3,55,33,1124,34";
std::string token;
ss.str(st);
while(getline(ss, token, ',')) {
cout << token << endl;
}
return 0;
}

C++ - Taking variable number of integers from standard input, n number of times

I'm not able to figure out why the loop in following program is not running exactly testCount times. Please help to make it correct.
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
int main() {
size_t testCount;
cin >> testCount;
if(testCount < 0 || testCount > 100) return 0;
int input;
while(testCount--) {
string instr;
getline(cin,instr);
istringstream iss(instr);
while(iss >> input) {
cout << input << endl;
}
}
return 0;
}
Thanks. I got it. The problem is with getline(). First loop cycle is getting wasted as getline() is taking first line containing just new line character when I pressed enter key after typing testCount value.
std::ws is an input stream manipulator which ignores all whitespaces to the point where the first non-whitespace character is encountered.
Also, getline leaves whitespaces where they are if they don't fit in the line. cin >> ws will discard those.
Here's the bullet proof code:
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
int main() {
size_t testCount;
cin >> testCount >> ws;
if(testCount < 0 || testCount > 100) return 0;
int input;
while(testCount--) {
cout << "testCount " << testCount << endl;
string instr;
cin >> ws;
getline(cin,instr);
istringstream iss(instr);
while(iss >> input) {
cout << input << endl;
}
}
return 0;
}

Reading integers from an unorganized text file

#include <iostream>
#include <fstream>
#include <string>
#include <cctype> // isdigit();
using namespace std;
int main()
{
ifstream fin;
fin.open("Sayı.txt");
while (!fin.eof()){
string word;
int n;
fin >> word; //First i read it as a string.
if (isdigit(word[0])){ //checks whether is it an int or not
fin.unget(); //
fin >> n; // if its a int read it as an int
cout << n << endl;
}
}
}
Suppose the text file is something like this:
100200300 Glass
Oven 400500601
My aim is simply to read integers from that text file and show them in console.
So the output should be like
100200300
400500601
You can see my attempt above.As output i get only the last digit of integers.Here's a sample output:
0
1
Simple just try converting the string read to an int using string streams, if it fails then it isn't an integer , otherwise it is an integer.
ifstream fin;
istringstream iss;
fin.open("Say1.txt");
string word;
while (fin>>word )
{
int n=NULL;
iss.str(word);
iss>>n;
if (!iss.fail())
cout<<n<<endl;
iss.clear();
}
I think the following should do what you want (untested code):
int c;
while ((fin >> std::ws, c = fin.peek()) != EOF)
{
if (is_digit(c))
{
int n;
fin >> n;
std::cout << n << std::endl;
}
else
{
std::string s;
fin >> s;
}
}