C++ - can't move istringstream definition out of loop - c++

I have the following piece of code:
#include <sstream>
#include <iostream>
using namespace std;
int main()
{
string inp, s;
istringstream iss;
do
{
getline (cin, inp);
iss(inp);
int a = 0, b = 0; float c = 0;
iss >> s >> a >> b >> c;
cout << s << " " << a << " " << b << " " << c << endl;
}
while (s != "exit");
}
which generates the following error:
error: no match for call to ‘(std::istringstream) (std::string&)’
I know that the issue may be averted by using istringstream iss(inp); within the loop, however, is it not possible to move this defintion out of the loop?
(Of course, it is possible to move it out, only that I can't accomplish anything.)

You cannot call an object constructor after the object declaration. Furthermore std::istringstream::operator ()(std::string) is not (usually) declared anywhere.
Use std::istringstream::str(…) to assign its content after construction.

Related

Why am I not getting the output from the program. Whenever I run my code it stop after taking the input? [duplicate]

This question already has answers here:
How do I pass a cin'd c style string to a function?
(2 answers)
Closed last year.
Here is my code I am expecting the output but I am not getting .It stop after taking the input
I am expecting the output if i give name Harsh
Your name is Harsh
#include <iostream>
#include <cstring>
using namespace std;
int main() {
cout << "Enter your name" << endl;
char *s;
cin >> s;
cout << "Your name is " << s;
return 0;
}
I have also tried with cin.getline(s,100);but still it is not working.
So I request to you to solve the problem and give me solution.
Your code has undefined behavior because you are not allocating any memory for s to point at. s is an uninitialized pointer.
Try this instead:
#include <iostream>
using namespace std;
int main(){
cout << "Enter your name" << endl;
char s[100];
cin >> s; // or: cin.getline(s,100);
cout << "Your name is " << s;
return 0;
}
Alternatively, you should use std::string instead, eg:
#include <iostream>
#include <string>
using namespace std;
int main(){
cout << "Enter your name" << endl;
string s;
cin >> s; // or: getline(cin,s);
cout << "Your name is " << s;
return 0;
}
s in your code is unallocated.
Since it is C++ we're talking about, you probably don't want to use pointers and memory allocation, and use std::string instead.
#include <iostream>
#include <string>
using namespace std;
int main ()
{
cout << "Enter your name" << endl;
string s; // Instead of dealing with char* allocation and memory issues.
cin >> s;
cout << "Your name is " << s;
return 0;
}
you have done it correctly but the problem with output is because of the memory allocation.
You have to allocate memory and try to avoid the concept of a pointer in that. Instead
Use string s;
or
char s[50];

Keep getting "member reference base type 'string [1000]' is not a structure or union" error and dont know how to fix it?

This program reads an SSN from the user and checks if it matches an SSN in a text file provided. Tried switching the array to a vector and it didnt work. Tried putting the array in the structure function and using info:: but nothing seems to work. I know this is pretty basic but I cant get it, thanks.
#include <iostream>
#include <fstream>
using namespace std;
int main(int argc, char* argv[]){
struct info{
string SSN;
string firstName;
string lastName;
};
string list[1000];
string userSSN;
char x;
fstream input(argv[1]);
int i = 0;
while(!input.eof()){
input >> list.x[i] >> list.SSN[i] >> list.firstName[i] >> list.lastName[i];
i++;
}
input.close();
cout << "Input a SSN:" << endl;
cin >> userSSN >> endl;
for(int k = 0; k < i; k++){
if(userSSN.compare(list.SSN[k]) == 0){
cout << "Found at location " << k << endl;
}
}
}
list is just an array of 1000 std::strings. It looks like you need it to be of type info. Even that won't solve your problems as info has no member named x. After that, to access a member of info in an array would be like
list[i].SSN
not
list.SSN[i]
There are so many things wrong with this code that I don't know where to start. Let's see:
Using using namespace std; is almost always a bad idea, and if you have an identifier list, then it's even worse because it conflicts with std::list.
Using std::string without #include <string> is not guaranteed to work. It may work if you include some other standard header, but don't rely on it.
Your variable x is unused.
string list[1000]; should probably be info list[1000];.
list.SSN[i] et al should probably be changed to list[i].SSN.
list.x[i] does not make sense at all and can probably be removed. (Or you meant to read into the otherwise unused x to skip parts of the file.)
You cannot read from std::cin into std::endl. Remove std::endl from that line.
Using std::string's compare function is pretty strange here, just use ==.
The issues in your code were already pointed out in other's answers. I'll show you a "working" example:
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
using std::string;
using std::vector;
using std::cout;
using std::cin;
struct info {
char x; // You were reading that from the file so I added it
string SSN;
string firstName;
string lastName;
friend std::istream &operator>>( std::istream &is, info &i ) {
// maybe you should check data input somehow...
is >> i.x >> i.SSN >> i.firstName >> i.lastName;
return is;
}
};
int main(int argc, char* argv[]) {
// check if a file name has been passed as a parameter
string file_name;
if ( argc < 2 ) {
cout << "Please, enter the input file name:\n";
cin >> file_name;
}
else
file_name = argv[1];
std::ifstream input(file_name);
if ( !input ) {
std::cerr << "Error. Unable to open file: " << file_name << '\n';
exit(-1);
}
// Just use a vector to store all the structs
vector<info> my_list;
info temp_info;
while( input >> temp_info ) {
my_list.push_back(temp_info);
}
input.close();
cout << "Input a SSN: ";
string userSSN;
cin >> userSSN;
// That's not cheap. You may want to change the container or sort it
for ( int k = 0; k < my_list.size(); k++ ) {
if ( userSSN == my_list[k].SSN ) {
cout << "Found at location " << k << '\n';
}
}
return 0;
}

why i need clear stringstream before reuse?

For example:
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
int main() {
int num = 10;
string str;
stringstream toString;
toString << num;
toString >> str;
cout << str << "\n"; //10
int num2 = 20;
string str2;
toString << num2;
toString >> str2;
cout << str2 << "\n"; //str2 is empty
return 0;
}
I know that I must clear this like:
toString.str("");
toString.clear();
But why doesn't it clear automatically after using operator >>?
If I do toString >> a >> b >> c and the first one fails, I don't want the flag to be cleared so that the final state appears to have succeeded.
After the first read toString >> str;. then the rdstate() of toString is std::ios_base::eofbit, because during the reading of str the end of the string has been reached.
Then the line toString << num2; does not modify the string stored in toString but sets the failbit of toString. That is the standard behavior of all formatted output.
The line toString >> str2; does nothing: the failbit is already set, and no reading is performed: str2 stays empty.
The clear() function resets the rdstate() of toString to std::ios_base::goodbit.
The reasons why the >> must not call clear() are:
in case there is an error, then one must be able to test it using the functions bad(), fail(), eof() (or rdstate() directly),
and one can use the operator >> several times:
#include <iostream>
#include <sstream>
int main() {
std::stringstream sstr("10 20");
int i, j;
sstr >> i >> j;
if(!sstr.fail()) {
std::cout << i << " " << j << "\n";
return 0;
}
return 1;
}

error C2678: binary '>>' : no operator found which takes a left-hand operand of type 'std::basic_istream<_Elem,_Traits>'

I get this strange error. I think I have included all necessary files. What could cause this?
The error is caused by this line :
cin >> x >> "\n" >> y >> "\n";
Here is the code:
#ifndef ARITMETICE_H
#define ARITMETICE_H
#include <iostream>
#include <string>
#include "UI\comanda.h"
using namespace Calculator::Calcule;
namespace Calculator{
namespace UI{
template<int Operatie(int, int)>
class CmdAritmetice : public ComandaCalcule
{
public:
CmdAritmetice(const string &nume) : ComandaCalcule(nume)
{
}
void Execute()
{
cout << Nume() << "\n";
cout << "Introduceti doua numere intregi (x, y)\n";
int x, y;
cin >> x >> "\n" >> y >> "\n"; // here a get the error
cout << x << " " << Nume() << " " << y << " = " << Operatie (x,y) <<"\n";
}
};
}
}
#endif
The problem is cin >> "\n". It purports to read user input into a string literal, which doesn't make any sense. Just drop it, make it cin >> x >> y;
Not sure what you expected to happen when you tried to extract data from a stream into a string literal!
cin >> must has a writable variable in the right,
your
cin>>"\n"
redirect cin to a const char* type, which is read only
in a word, just use cin>> x >> y; and the iostream will do the rest for you.
cin is object of type istream. This class has overloaded operator >> to take input from console and put the value into given variable. The variable must be l-value, not r-value. In short, the expression given on right of >> must be writable variable.
This will not work:
const int x;
cin >> x;
Simply because x is a const int&, and not int& which what istream::operator>>(int&) expects.
Going this way further, when you make a call:
cin >> "\n";
You are essentially calling operator >> (const char*) and not operator >> (char*), and hence the error. Because of multiple overloads of operator>> and template code behind, the error is not clear.
Note: The exact signature of operator >> might differ, but problem is with const-ness.
If your intention is to consume white spaces and one new line character (note the are flavors of new line representations), you might write a manipulator
#include <cctype>
#include <iostream>
#include <sstream>
std::istream& nl(std::istream& is) {
typedef std::istream::traits_type traits;
while(true) {
traits::int_type ch;
if(std::isspace(ch = is.get())) {
if(ch == '\n') break;
}
else {
is.putback(ch);
// No space and no '\n'
is.setstate(std::ios_base::failbit);
break;
}
}
return is;
}
int main()
{
std::istringstream s("1\n2");
int x, y;
s >> x >> nl >> y >> nl;
std::cout << x << ' ' << y << '\n';
if(s.fail()) {
// The missing '\n' after '2'
std::cout <<"Failure\n";
}
return 0;
}

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.