Building an istringstream with a string temporary - c++

While trying my code to answer another question I found out that the following didn't compile
#include <iostream>
#include <cstring>
#include <sstream>
#include <string>
using namespace std;
// (main omitted)
const char * coin = "3D";
istringstream ss(string(s));
int i;
ss >> hex >> i; <--- error here
cout << (char) i << endl;
It failed with the following error:
test.cpp:15:11: error: invalid operands of types ‘std::istringstream(std::string) {aka std::basic_istringstream<char>(std::basic_string<char>)}’ and ‘std::ios_base&(std::ios_base&)’ to binary ‘operator>>’
While the following compiled and ran properly :
const char* coin = "3D";
string s(coin);
istringstream ss(s); // or directly istringstream ss("3D")
int i;
ss >> hex >> i;
cout << (char) i << endl;
If I look at the definition of the constructor of istringstream, it accepts const std::string& (actually the basic_string<char> equivalent), and that compiles. So I guess the template argument deduction has a behaviour I don't understand and create a not so conform istringstream, but why ?
I am using GCC 4.6.1 (Ubuntu flavor).
EDIT : since istringstream is a typedef, I doubt there's any problem with templates in the end.

istringstream ss(string(s));
Your compiler thinks that's a declaration of a function taking a string (named s) and returning an istringstream. Surround the argument in parentheses in order to disambiguate it. By the way, what is s? Did you mean coin there?
istringstream ss( (string(coin)) );
Read this if you are confused.
In this particular case, you could of course have just done this:
istringstream ss(coin);
If your compiler supports it, you can also avoid the MVP using uniform initialization syntax:
istringstream ss{string{coin}};
That probably looks a bit odd to most people, I know it looks odd to me, but that's just because I'm so used to the old syntax.

Related

How to pass string to gets_s() in C++?

#include<iostream>
using namespace std;
int main() {
string str;
gets_s(str);
cout << str << endl;
return 0;
}
When I tried to run the above code it threw an error that no instance of gets_s() matched the argument list.
How can I pass an std::string instead of a char[] to gets_s() function if is possible?
The C function get_s takes a char* and a length argument, not a std::string.
Your best options are:
Formatted input:
std::cin >> str;
Read a line:
std::getline(std::cin, str);
Don't do that. Use the stream in a normal way:
#include<iostream>
using namespace std;
int main()
{
string str;
cin >> str;
cout << str << endl;
return 0;
}
gets_s has a significant limitation in that you must provide an upper limit on the number of characters you want to read.
Since you are using string the superior alternative is to use getline
#include <iostream>
#include <string>
using namespace std;
string str;
getline(cin, str);
This will expand the string to hold as many characters as are entered by the user.
gets_s() takes two arguments: pointer to char array and maximal size (your call is missing it). You cannot pass std::string - only C style strings.
Instead of C functions, why not use C++ way std::cin >> str or getline(std::cin, str)?
In C also don't use gets_s() (it's optional in C11) or gets() - use fgets() instead.
Well, there are a lot of answers about std::getline, but in case if you really need to use get_s, you may write such code:
size_t length = 10; // Just for example
std::string my_string(length, 0);
get_s(&my_string[0], length); // C++14 and older
get_s(my_string.data(), length); // C++17 and newer

String not reversing in C++

I wrote a program that reverses the string that is inputted by the user, but it doesn't work. I did it using string reverse_name(name.rbegin(), name.rend()) from Reverse the string in C++, but it doesn't work and gives me the error:
no viable conversion from 'std::__cxx11::basic_string<char,
std::char_traits<char>, std::allocator<char> >::reverse_iterator' (aka
'reverse_iterator<__normal_iterator<char *, std::__cxx11::basic_string<char> > >') to
'std::__cxx11::string' (aka 'basic_string<char>')
string reversed_word = (word.rbegin(), word.rend());
My code:
#include <iostream>
using namespace std;
int main()
{
string word, reversed_word;
cin >> word;
reversed_word = (word.rbegin(), word.rend());
cout << reversed_word;
return 0;
}
This line is wrong:
reversed_word = (word.rbegin(), word.rend());
The error message is self explanatory. Here is a simplified version to help make it easier for you to understand:
no viable conversion from 'reverse_iterator' ... to ... 'std::string'
You can't assign a (reverse) iterator to a string, but that is exactly what you are trying to do. The expression (word.rbegin(), word.rend()) does not construct a new string, like you are expecting. It simply evaluates the two iterators as-is, separated by the comma operator, which returns the value on the right side. So the line above is effectively the same as this:
reversed_word = word.rend();
To do what you are attempting, you need to pass the iterators to the std::string constructor instead. Either like this:
string reversed_word;
...
reversed_word = string(word.rbegin(), word.rend());
Or like this 1:
string reversed_word(word.rbegin(), word.rend());
1: as shown in this answer to the question you linked to, and even shown in your own question where you say "I did it using ... ".
The easiest way to do it.
#include <iostream>
#include <algorithm>
#include <string>
using namespace std;
int main()
{
string word, copy;
cin >> word;
copy = word
reverse(word.begin(), word.end());
cout << copy << endl;
cout << word << endl;
return 0;
}

Redirecting std::cin directly to std::cout

An exercise about standard io asks me to:
Read input from the standard input and write it to the standard output.
A possible solution is:
#include<iostream>
#include<string>
using std::cin; using std::cout;
using std::string;
int main()
{
string word;
while (cin >> word)
cout << word;
return 0;
}
The string acts as a buffer in this example. If one tries to get rid of the buffer by doing something like this:
#include<iostream>
using std::cin; using std::cout;
int main()
{
while (cout << cin)
;
return 0;
}
the results are very different. When I run this code I get an interminable stream of
0x600d300x600d300x600d300x600d300x600d300x600d300x600d300x600d300x600d300x600d300x600d300x600d300x600d300x600d300x600d300x600d300x600d300x600d300x600d300x600d300x600d300x600d300x600d300x600d300x600d300x600d300x600d300x600d300x600d300x600d300x600d300x600d30
on the terminal.
Why this happens? Why do these programs behave differently?
cout << cin will not work the way you want it to. In C++11 and later, it won't even compile.
You are seeing an unfortunate side-effect of the (now obsolete) "safe bool" idiom.
Before C++11, a std::istream could be implicitly converted to a void* to emulate bool semantics. (Since C++11, explicit operator bool() const fills that role)
Therefore, the code:
while (cout << cin)
compiles in C++98 or C++03, because it can be implicitly converted to:
while (cout << static_cast<void*>(cin) )
This cast is allowed to produce any non-NULL void* when cin is not in an error state. In your case, it is producing the pointer 0x600d30.
In first solution, you extract a string from cin and reinject it in cout. But in the second way, compiler tries to convert cin into a value suitable for injection in cout.
Your implementation converted cin to a pointer and repeatedly printed it. Mine simply converted cin to a bool and repeadedly prints 1.
But beware, even your first version is not transparent to multiple spaces or tabs, and would probably not respect lines either. I would prefer:
#include<iostream>
#include <string>
int main()
{
std::string line;
while (std::getline(std::cin, line)) {
std::cout << line << std::endl;
}
return 0;
}

Attempting to convert int to string

It's quite clear from the code below that I am attempting to convert an int to a string.
#include <sstream>
#include <string>
#include <iostream>
int num = 1;
ostringstream convert;
convert << num;
string str = convert.str();
However, I get the error message
Line 7: error: expected constructor, destructor, or type conversion
before '<<' token
What I am doing wrong? This is basically the same snippet of code that everyone recommends to convert an int to a string.
There's 2 issues here, first you are missing main so subsequently this code is not valid at the top-level (eg outside main/functions/etc). When you compile your program the compiler looks for main then starts executing the code from that point onwards. There's a few things that are allowed before main but this expression is not one of them. The reason is because you are trying to compute something but the program flow never actually goes there, so how can the compiler decide when to execute that code? It matters what order that happens in and before main that order is not defined. That statement is not side-effect free so that's what the error message you posted is complaining about. The compiler looks for main as that's where code will start executing from so you want to put your code in main for that reason (I know this is more to this and it's not 100% accurate but I think this is a good starting point/heuristic for new programmers to get better understanding). You might want to read this question Is main() really start of a C++ program?
Secondly there's an issue with namespaces. ostringstream is in the std namespace, try std::ostringstream instead. The situation with string is similar, use std::string for that.
With these changes the code will end up looking something like this:
int main(){
int num = 1;
std::ostringstream convert;
convert << num; //This isn't allowed outside of main
std::string str = convert.str();
std::cout << str;
return 0;
}
#include <string>
#include <sstream> // std::stringstream
#include <iostream>
int main()
{
int num = 1;
std::stringstream convert;
convert << num;
std::string str = convert.str();
std::cout << str ;
return 0;
}

Qt c++ aggregate 'std::stringstream ss' has incomplete type and cannot be defined

I have this function in my program that converts integers to strings:
QString Stats_Manager::convertInt(int num)
{
stringstream ss;
ss << num;
return ss.str();
}
But when ever i run this i get the error:
aggregate 'std::stringstream ss' has incomplete type and cannot be defined
Im not really sure what that means. But if you know how to fix it or need any more code please just comment. Thanks.
You probably have a forward declaration of the class, but haven't included the header:
#include <sstream>
//...
QString Stats_Manager::convertInt(int num)
{
std::stringstream ss; // <-- also note namespace qualification
ss << num;
return ss.str();
}
Like it's written up there, you forget to type #include <sstream>
#include <sstream>
using namespace std;
QString Stats_Manager::convertInt(int num)
{
stringstream ss;
ss << num;
return ss.str();
}
You can also use some other ways to convert int to string, like
char numstr[21]; // enough to hold all numbers up to 64-bits
sprintf(numstr, "%d", age);
result = name + numstr;
check this!