istringstream-function string_to_int cannot take c-str, why? - c++

I learned a helper function that can convert strings to integers:
int string_to_int(string s)
{
istringstream instr(s);
int n;
instr>>n;
return n;
}
It's mentioned that the argument s cannot be c-str string, why is this the case?

But you can pass a C style string.
The reason for that is because the std::string constructor can implicitly accept a CharT* (Char type, which is char in this case) as a parameter. Thus, something like the following would work:
#include <iostream>
#include <sstream>
using namespace std;
int string_to_int(string s)
{
istringstream instr(s);
int n;
instr>>n;
return n;
}
int main()
{
const char* test = "12345";
std::cout << string_to_int(test) << "\n"; // Outputs 12345
std::cout << string_to_int("122") << "\n"; // Outputs 122
}

Related

Store cout output into variable

How can I store the output from cout into a variable of string or character type?
I have written following code but it doesn't work:
#include<iostream>
#include<stdio.h>
using namespace std;
int main(){
string n;
n = (cout<<"\nHello world");
cout<<n;
return 0;
}
#include <sstream>
std::ostringstream a;
a << "Hello, world!";
std::string b = a.str(); // Or better, `std::move(a).str()`.
std::cout << b;
Other answers have shown you how to capture formatted output using a std::(o)stringstream object directly. But, if for some reason, you really need to capture the output of std::cout, then you can temporarily redirect std::cout to use a std::ostringstream's buffer, eg:
#include <iostream>
#include <sstream>
using namespace std;
int main(){
ostringstream oss;
auto cout_buff = cout.rdbuf(oss.rdbuf());
cout << "\nHello world";
cout.rdbuf(cout_buff);
string n = oss.str();
cout << n;
return 0;
}
Online Demo
Of course there's a way! But you have to use a different kind of stream:
std::ostringstream ss;
ss << "\nHello world";
std::string result = ss.str();
Also, in C++20, you can simply use std::format:
std::string n = std::format("Hello {}! I have {} cats\n", "world", 3);
// n == "Hello world! I have 3 cats\n"

Alternative for a loop in C++

I want to reverse a string without the use of a loop. My code with the loop looks like:
#include <iostream>
#include <string>
using namespace std;
string reverseString(string str) {
string changedString;
int strLength = int(str.length() - 1);
for(int i {strLength}; i >= 0; i--) {
changedString.push_back(str.at(i));
}
return changedString;
}
int main() {
string str;
cout << "Enter a string to reverse it:\n" << flush;
cin >> str;
cout << reverseString(str) << flush;
}
Now I need to write a function without the loop. Only the methods of String should be used. Can you help me solving this problem?
It is very simple to write such a function
std::string reverse( const std::string &s )
{
return { s.rbegin(), s.rend() };
}
Here is a demonstrative program
#include <iostream>
#include <string>
std::string reverse( const std::string &s )
{
return { s.rbegin(), s.rend() };
}
int main()
{
std::string s( "Hello World" );
std::cout << s << '\n';
std::cout << reverse( s ) << '\n';
return 0;
}
Its output is
Hello World
dlroW olleH
Well, you can do that using recursion. Here are some links if you aren't aware what recursion is : link1 and link2.
Technically it won't be a loop.
string reverseString(string str, int index, string ans) {
if (index == -1) return ans;
ans += str[index];
return reverseString(str, index - 1, ans);
}
Parameters for this function will be str as it was by default, index = size(str) - 1 and ans ans = "";
reverseString(str, size(str) - 1, "") for example.
If you want your function to take exactly one argument, then you can write wrapper function and the one I wrote will have different name - reverseStringWrapper for example and in reverseString there will be only one line - return reverseStringWrapper(str, size(str) - 1, "");
string reverseStringWrapper(string str, int index, string ans) {
if (index == -1) return ans;
ans += str[index];
return reverseString(str, index - 1, ans);
}
string reverseString(string str) {
return reverseStringWrapper(str, size(str) - 1, "");
}
How was this?
In c, You can use strrev() function to reverse the string(char*)
In c++, you can either use std::reverse() or StringBuilder.reverse()
method to reverse a string.
.
This way you can reverse the char array(char*).
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
// Function to reverse a given character array using std::reverse
void reverse(char *str)
{
std::reverse(str, str + strlen(str));
}
// main function
int main()
{
/* using C string */
char s[] = "Hello World";
reverse(s);
cout << "Reverse of the given string is : " << s;
return 0;
}
This way you can reverse the string.
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
// Function to reverse a given character array using std::reverse
void reverse(char* str)
{
std::reverse(str, str + strlen(str));
}
// main function
int main()
{
/* using C string */
// char s[] = "Techie Delight";
string s = "hello world";
int n = s.length();
// declaring character array
char char_array[n + 1];
// copying the contents of the
// string to char array
strcpy(char_array, s.c_str());
reverse(char_array);
s = char_array;
cout << "Reverse of the given string is : " << s;
return 0;
}
Hope this might Helps:)

Assign a integer to char pointer using stringstream

I want to assign integer to a char pointer using stringstream. But I am getting error while running this program at line ss >> p. Please help me here i want integer to go into the buffer first and the it must be assigned to a char*.
#include <string> // std::string
#include <iostream> // std::cout
#include <sstream> // std::stringstream
using namespace std;
int main ()
{
stringstream ss;
int n=100;
char *p;
ss << n;
ss >> p; //not working
cout << ss;
return 0;
}
Use stringstream::str to get a C++ string, then use .c_str() on the string:
#include <string> // std::string
#include <iostream> // std::cout
#include <sstream> // std::stringstream
using namespace std;
int main ()
{
stringstream ss;
int n = 100;
char* p;
ss << n;
string tmp = ss.str();
p = const_cast<char*>(tmp.c_str());
cout << "p: " << p << '\n';
return 0;
}
Beware that the char pointer becomes invalid as soon as the string goes out of scope. If you need some kind of factory function behavior, return a string by value, use strlcpy or maybe new and shared_ptr.
#include <string> // std::string
#include <iostream> // std::cout
#include <sstream> // std::stringstream
using namespace std;
int main ()
{
stringstream ss;
int n=100;
char buffer[100];
char *p = buffer;
ss << n;
ss >> p;
cout << p;
return 0;
}
This is fixing only the problem you directly encountered - there's no storage behind p so it will crash. Stylistically there are many other things to improve / fix, but this should show you what part of this was actually wrong.

Convert char to const char* String Insert C++

I have a problem with String Insertion because, I can not add a char, just a const char. How can i easily convert it?
The compiler just accept like this:
b.insert(i,"a");
But i want like this:
b.insert(i,b[ii]);
Full Code:
#include <stdio.h>
#include <string.h>
#include <string>
#include <iostream>
using namespace std;
int main()
{
string a,b;
int aa=0;
cin >> a;
b=a;
for(int i=0;i<a.length()+1;i++)
{
for(int ii=0;ii<a.length();ii++)
{
b.insert(i,a[ii]);
if (b == string(b.rbegin(), b.rend()))
{
cout << b << endl;aa=1;
break;
}
b.erase (b.begin()+i);
}
if(aa=1)break;
}
if(aa==0)
cout << "NA" << endl;
return 0;
}
See the documentation for std::string::insert. The version that takes a single char also needs a count argument.
b.insert(i,1,b[ii]);
You should use the following overload of std::string::insert:
basic_string& insert( size_type index, size_type count, CharT ch );
See http://en.cppreference.com/w/cpp/string/basic_string/insert

Generic way to convert a string into a numerical type?

I have this class:
template<typename T> class Parser
{
public:
Parser() : count(0) {}
virtual void parse(const string&);
void get_token(void);
private:
T result;
char token;
string expression;
int count;
};
now had the class not been generic, had the result been say, a double, I would have used this method to detect numbers.
while((strchr("1234567890.",token))
{
/* add token to a "temp" string */
/* etc. etc. */
}
result = atof(temp.c_str());
But since result is generic, I can't use any method like atof and atoi etc.
What do I do?
Boost has this functionality built-in:
#include <boost/lexical_cast.hpp>
void Parser<T>::get_token() {
std::string token = ...;
result = boost::lexical_cast<T>(token);
}
Add exception handling as required.
Or, perhaps you don't want to use Boost for some reason:
void Parser<T>::get_token() {
std::string token = ...;
std::stringstream ss;
ss << token;
ss >> result;
}
Check the error state of ss as required.
More expansive answers may be found on this related question, though it discusses only int specifically.
Another generic template based Numeric To String converter. It takes ints and doubles.
#include <sstream>
#include <iostream>
#include <string>
using namespace std;
template <class T>
inline std::string Numeric_To_String (const T& t)
{
std::stringstream ss;
ss << t;
return ss.str();
}
int main(int argc, char *argv[])
{
int i = 9;
double d = 1.2345;
string s;
cout <<"Generic Numeric_To_String( anyDatatype ) \n\n";
s = Numeric_To_String( i );
cout <<"int i to string : "<< s <<" "<< endl;
s = Numeric_To_String( d );
cout <<"double d to string : "<< s <<" "<< endl;
cout <<" \n";
return 0;
}
If you only have a hand full of types you want to parse, you can use template specialization:
template<>
void Parser<int>::parse(const string&)
{
result = atoi(string.c_str());
}
template<>
void Parser<float>::parse(const string&)
{
result = atof(string.c_str());
}
...
But this only works if you implement every convertion you need, of course.
With C++17 you can use the templated std::from_chars.
https://en.cppreference.com/w/cpp/utility/from_chars
#include <charconv>
#include <iostream>
template <typename Number>
auto stringTo(std::string_view str)
{
Number number;
std::from_chars(str.data(), str.data() + str.size(), number);
return number;
}
int main()
{
const auto str = std::string("42");
std::cout << stringTo<long>(str) << '\n';
std::cout << stringTo<double>(str) << '\n';
}
Check the return value of std::from_chars to detect errors.
const auto result = std::from_chars(...);
if (result.ec == std::errc::invalid_argument || result.ec == std::errc::result_out_of_range)
{
std::cout << "string to number error" << '\n';
}
More info and examples: https://www.bfilipek.com/2018/12/fromchars.html
GCC and clang don't yet support the floating point version of std::from_chars (August 2019).