newbie: string2int

G

Guest

how can I convert a (class) string to an int?

I use this code, but it is in C.
As printf in C is cout in C++,
please tell me how code below can be written in C++
----------------------------------
int integer(string &s)
{
int a;
sscanf(s.c_str(), "%d", &a);
return a;
}
 
J

John Harrison

how can I convert a (class) string to an int?

I use this code, but it is in C.
As printf in C is cout in C++,
please tell me how code below can be written in C++

This is better

int integer(const string& s)

Since you are not intending to modify s, its is better to use a const
reference. If you use a non-const reference then your function cannot be
called like this

integer(some_function_that_returns_a_string());
{
int a;
sscanf(s.c_str(), "%d", &a);
return a;
}

#include <sstream>
using namespace std;

int integer(const string& s)
{
istringstream buf(s);
int a;
buf >> a;
// error checking goes here
return a;
}

john
 
V

Victor Bazarov

how can I convert a (class) string to an int?

That's covered in the FAQ. See Miscellaneous Technical
Issues.
I use this code, but it is in C.

No, it isn't. There is no 'string' in C, and there
are no references in C.
As printf in C is cout in C++,
please tell me how code below can be written in C++
----------------------------------
int integer(string &s)
{
int a;
sscanf(s.c_str(), "%d", &a);
return a;
}
---------------------------------

But it _is_ written in C++! The only correction I'd
make is to give the argument a 'const' specifier:

int integer(string const &s) ...

Victor
 
C

Chris Theis

how can I convert a (class) string to an int?

I use this code, but it is in C.
As printf in C is cout in C++,
please tell me how code below can be written in C++
----------------------------------
int integer(string &s)
{
int a;
sscanf(s.c_str(), "%d", &a);
return a;
}

template<typename T>
T FromString( const std::string& s )
{
std::istringstream is(s);
T t;
is >> t;
if( !is ) {
// do whatever you like to do, in case the conversion was not successful
}
return t;
}

e.g: int d = FromString<int>( s );

HTH
Chris
 
C

Chris \( Val \)

[snip]

Hi Chris.

| template<typename T>
| T FromString( const std::string& s )
| {
| std::istringstream is(s);
| T t;
| is >> t;
| if( !is ) {
| // do whatever you like to do, in case the conversion was not successful

[snip]

The above won't catch an un-successful conversion.

I think you wanted:

if( !is.eof() )
{
// ...

Cheers.
Chris Val
 
A

Anubis

Victor said:
But it _is_ written in C++! The only correction I'd
make is to give the argument a 'const' specifier:

int integer(string const &s) ...

Victor

I agree.

It will be more readable to have a printf than all the stream stuff here...

LibC functions may have been written in C, but they are still freely
available in a C++ program, and still sufficient enough.

So if you fell more comfortable with printf than cout, go ahead, nobody
will burn you for that ;-).

PS: Don't tell too much people, but I think you C code might be far more
efficient :D.
 
C

Chris Theis

Chris ( Val ) said:
[snip]

Hi Chris.

| template<typename T>
| T FromString( const std::string& s )
| {
| std::istringstream is(s);
| T t;
| is >> t;
| if( !is ) {
| // do whatever you like to do, in case the conversion was not successful

[snip]

The above won't catch an un-successful conversion.

Well, it does on the implementations I've come across so far. Why do you
think it does not? An un-successful conversion sets the failbit which is
tested for by operator! for the ios_base class.
I think you wanted:

if( !is.eof() )
{
// ...

Which is also a way to go. However, I don't see why the usual test for the
stream state shouldn't work. If you could shed some light on this I'd be
happy.

Cheers
Chris
 
C

Chris \( Val \)

|
| | >
| >
Hi Chris.

| > | template<typename T>
| > | T FromString( const std::string& s )
| > | {
| > | std::istringstream is(s);
| > | T t;
| > | is >> t;
| > | if( !is ) {
| > | // do whatever you like to do, in case the conversion was not
| successful
| >
| > [snip]
| >
| > The above won't catch an un-successful conversion.
|
| Well, it does on the implementations I've come across so far. Why do you
| think it does not? An un-successful conversion sets the failbit which is
| tested for by operator! for the ios_base class.

Note, I said it won't catch an *un-successful* conversion.

Maybe you misunderstood my intentions, of which I'll try to
demonstrate below with some code.

| > I think you wanted:
| >
| > if( !is.eof() )
| > {
| > // ...
| >
|
| Which is also a way to go. However, I don't see why the usual test for the
| stream state shouldn't work. If you could shed some light on this I'd be
| happy.

Sure, hopefully the following will explain what I'm getting at.

template<typename T, typename U>
T FromString( const U& s )
{
std::istringstream is(s);
T t;
is >> t;
if( !is ) {
std::cout << "Error: Could not parse token " << std::flush;
}
return t;
}

int main()
{
// Note the character 'x'...
std::cout << FromString<int>( "12x34" ) << std::endl;

return 0;
}

I have modified the template function slightly to handle
the std::string class, but the above will indicate successful
conversion, and the message will not be output, resulting in
the integer '12' being output - not what we wanted.

Try the above using '.eof()', which will catch the error, if we
did not successfully read to the end of the token.

Cheers.
Chris Val

PS: It would be preferable to use both checks, and I'm sure you
understand this :).
 
C

Chris \( Val \)

|
| | |
| | | | >
| | > |
| Hi Chris.
|
| | > | template<typename T>
| | > | T FromString( const std::string& s )
| | > | {
| | > | std::istringstream is(s);
| | > | T t;
| | > | is >> t;
| | > | if( !is ) {
| | > | // do whatever you like to do, in case the conversion was not
| | successful
| | >
| | > [snip]
| | >
| | > The above won't catch an un-successful conversion.
| |
| | Well, it does on the implementations I've come across so far. Why do you
| | think it does not? An un-successful conversion sets the failbit which is
| | tested for by operator! for the ios_base class.
|
| Note, I said it won't catch an *un-successful* conversion.
|
| Maybe you misunderstood my intentions, of which I'll try to
| demonstrate below with some code.
|
| | > I think you wanted:
| | >
| | > if( !is.eof() )
| | > {
| | > // ...
| | >
| |
| | Which is also a way to go. However, I don't see why the usual test for the
| | stream state shouldn't work. If you could shed some light on this I'd be
| | happy.
|
| Sure, hopefully the following will explain what I'm getting at.
|
| template<typename T, typename U>
| T FromString( const U& s )
| {
| std::istringstream is(s);
| T t;
| is >> t;
| if( !is ) {
| std::cout << "Error: Could not parse token " << std::flush;
| }
| return t;
| }

[snip]

| I have modified the template function slightly to handle
| the std::string class, but the above will indicate successful

[snip]

Sorry, what I meant there was:

My compiler will not allow me to pass a const char*
as an argument, so I used another template parameter
'U' to bypass that.

Cheers.
Chris Val
 
C

Chris Theis

Chris ( Val ) said:
|
| | >
| >
Hi Chris.

| > | template<typename T>
| > | T FromString( const std::string& s )
| > | {
| > | std::istringstream is(s);
| > | T t;
| > | is >> t;
| > | if( !is ) {
| > | // do whatever you like to do, in case the conversion was not
| successful
| >
| > [snip]
| >
| > The above won't catch an un-successful conversion.
|
| Well, it does on the implementations I've come across so far. Why do you
| think it does not? An un-successful conversion sets the failbit which is
| tested for by operator! for the ios_base class.

Note, I said it won't catch an *un-successful* conversion.

Maybe you misunderstood my intentions, of which I'll try to
demonstrate below with some code.

| > I think you wanted:
| >
| > if( !is.eof() )
| > {
| > // ...
| >
|
| Which is also a way to go. However, I don't see why the usual test for the
| stream state shouldn't work. If you could shed some light on this I'd be
| happy.

Sure, hopefully the following will explain what I'm getting at.

template<typename T, typename U>
T FromString( const U& s )
{
std::istringstream is(s);
T t;
is >> t;
if( !is ) {
std::cout << "Error: Could not parse token " << std::flush;
}
return t;
}

int main()
{
// Note the character 'x'...
std::cout << FromString<int>( "12x34" ) << std::endl;

return 0;
}

I have modified the template function slightly to handle
the std::string class, but the above will indicate successful
conversion, and the message will not be output, resulting in
the integer '12' being output - not what we wanted.

Try the above using '.eof()', which will catch the error, if we
did not successfully read to the end of the token.

Cheers.
Chris Val

Okay now I get what you're aiming at. Sorry, but I was a little slow this
morning.
PS: It would be preferable to use both checks, and I'm sure you
understand this :).

You're absolutely right!

Cheers
Chris
 
G

Guest

how can I convert a (class) string to an int?
template<typename T>
T FromString( const std::string& s )
{
std::istringstream is(s);
T t;
is >> t;
if( !is ) {
// do whatever you like to do, in case the conversion was not successful
}
return t;
}

e.g: int d = FromString<int>( s );

Excellent but it works only inside the .cpp file:
if I use last line from other .cpp file I have this LINKER (not compiler) error:
----------------------------------------------------
Linking...
display_mode.obj : error LNK2001: unresolved external symbol "int __cdecl FromString<int>(class std::basic_string<char,struct
std::char_traits<char>,class std::allocator<char> > const &)"
(??$FromString@H@@YAHABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z)
----------------------------------------------------
WHY???

============= my files ================
------------------- extend_string.h -----------------
..........
template<typename T>
T FromString(const string& s);
------------------ extend_string.cpp ---------------
#include "extend_string.h"
..................
template<typename T>
T FromString(const string& s)
{
istringstream is(s);
T t;
is >> t;
return t;
}
------------- display_mode.cpp --------------------
#include "extend_string.h"
.............
void blablabla()
{
// settings is a map class (I load in settings an INI file)
setDisplayMode(
FromString<int>(settings["fullscreen.width"]),
FromString<int>(settings["fullscreen.height"]),
FromString<int>(settings["fullscreen.bpp"])
);
}
 
J

John Harrison

Excellent but it works only inside the .cpp file:
if I use last line from other .cpp file I have this LINKER (not compiler) error:
FromString said:
std::char_traits<char>,class std::allocator<char> > const &)"
(??$FromString@H@@YAHABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D
@2@@std@@@Z)

That's because template functions must go in header files.

This is covered in the FAQ.

john
 
J

Jonathan Turkanis

John Harrison said:
compiler) __cdecl

(??$FromString@H@@YAHABV?$basic_string@DU?$char_traits@D@std@@V?$alloc
ator@D

That's because template functions must go in header files.

Unless your compiler implements export

Jonathan
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,160
Messages
2,570,890
Members
47,423
Latest member
henerygril

Latest Threads

Top