2

It might sound stupid, but I was just wondering how can I parse a string to an integer in C++?

This is for a school project, and the explanation sheet says : "Only the use of iostream and string classes and system() function is permitted; The use of any other class or function is prohibited."

I have searched around a bit, but the only suggestions I found are using classes like atoi or atof.

The input string is already checked for error before the parsing, so it will always only contain an integer.

I wouldn't mind doing the parsing manually with conditionals, but I don't think it would be my teacher's (or anyone's) preferred way.

Thanks a bunch if you can help.

10
  • Are you allowed to use Boost? Commented Sep 15, 2011 at 18:35
  • I don't suppose you are allowed to use stringstream? Commented Sep 15, 2011 at 18:38
  • 1
    No, the explanation sheet clearly says "Only the use of iostream and string classes and system() function is permitted; The use of any other class or function is prohibited." Commented Sep 15, 2011 at 18:39
  • Well, atoi and atof are functions (not classes). And they are not .NET specific (ANSI C in fact). Ask your teacher about it, but I don't think it is really a big deal to use it Commented Sep 15, 2011 at 18:39
  • 3
    stringstreams are iostream classes. See cplusplus.com/reference/iostream/stringstream. Commented Sep 15, 2011 at 18:54

5 Answers 5

40

So, you can use system(), huh? Behold this masterpiece of engineering:

#include <fstream>

void download_boost() {
    system("wget http://downloads.sourceforge.net/"
           "project/boost/boost/1.47.0/boost_1_47_0.tar.bz2"
           "?r=http%3A%2F%2Fwww.boost.org%2Fusers%2Fhistory%2F"
           "version_1_47_0.html&ts=1316116936&use_mirror=kent"
           " -O boost_1_47_0.tar.bz2");
}

void unpack_boost() {
    system("tar --bzip2 -xf boost_1_47_0.tar.bz2");
}

void write_program() {
    std::ofstream os("blah.cpp");
    os << "#include \"boost/lexical_cast.hpp\"\n"
          "#include <iostream>\n"
          "#include <string>\n"
          "int main() { std::string s; std::cin >> s;"
          "int i = boost::lexical_cast<int>(s);"
          "std::cout << i; }";
}

void compile_program() {
    system("g++ -Iboost_1_47_0 blah.cpp");
}

void run_program() {
    system("./a.out");
}

int main() {
    download_boost();
    unpack_boost();
    write_program();
    compile_program();
    run_program();
}

(I'm assuming a typical Linux installation with some common tools installed.)

Sign up to request clarification or add additional context in comments.

7 Comments

Now that's what I call lateral thinking!
Literal thinking. Thinking with literals.
Cute. But, you used std::ofstream, which is not allowed.
@Rob: I think the text is ambiguous enough to wonder if it allows the iostream class, the class in the <iostream> header or the classes in the iostream library. But well, it's a joke anyway.
At the end of write_program, shouldn't std::cout >> i; be std::cout << i;?
|
2
#include <iostream>
#include <string>

int stringToInt(const std::string &text)
{
    int number = 0;

    int powerIndex = 1;

    for (int i = text.length() - 1; i >= 0; i--)
    {
        number += powerIndex * (text.at(i) - '0');

        powerIndex *= 10;
    }

    return number;
}

std::string intToString (int number)
{
    std::string text = "";

    int numberHolder = number;

    while (numberHolder)
    {
        char digit = (numberHolder % 10) + '0';

        text = digit + text;

        numberHolder /= 10;
    }

    return text;

}
int main ()
{
    //Testing...

    int number = stringToInt("123");

    std::string text = intToString(456);

    std::cout << number << "\n" << text << "\n";

    return 0;
}

1 Comment

Usually, primitive types like int (and char, short, long, float, double, ...) are passed by value, not by reference.
2

stringstreams come closest to what you want to do, although it may seem a little cumbersome at first.

Example:

#include <string>
#include <sstream>

// (...)
std::string str = "12345";
std::istringstream ss(str);
int num;
ss >> num;

As a function (and optimized):

#include <sstream>
#include <string>

int stringToInt(const std::string &str) {
    static std::istringstream ss;
    ss.clear();
    ss.str(str);

    int num;
    ss >> num;

    return num;
}

Here, I am reusing the std::istringstream by applying the static keyword. I have created a very simple benchmark that demonstrates that this is approximately 2 times faster than not reusing: http://pastebin.com/vLSmCyMF

Warning regarding thread-safety: As рытфолд has noted in the comments, the above implementation of stringToInt is not thread-safe. If you want to call this function safely from multiple threads, you should use the thread_local storage class specifier (available since C++11).

7 Comments

std::ostringstream("1234") would be enough
I just added some extra information in bold text to my question.
Thanks, Andy. I have adapted the code to demonstrate that stringstreams can be reused, while ostringstreams cannot. It would be interesting to determine if my way of doing it is actually faster. I'm not sure.
@AgentRev: Technically, stringstream is both an iostream and a string class in the standard library.
@SoapBox: I have appended additional results with -O3 switch. It appears that it makes no difference in this specific case. (Or is there anything wrong with the compilation command?)
|
1
std::string mystring = "12";

std::ostringstream str(mystring);
int someint;
str >> someint;

5 Comments

std::ostream? probably you meant std::ostringstream
@Andy T: Yes, indeed! Fixed it
I'm pretty sure ostringstream doesn't have operator>> (only <<). I think it should be istringstream instead.
I just added some extra information in bold text to my question.
Remember to test str.fail() after using operator>>.
1

Basically, given a std::string mystring that contains only an integer: Start with an int result = 0;.
While mystring has digits
Multiply result by ten
Add biggest digit (first in string)
Remember that the character '0' does not have the value of 0.
Remove the biggest digit from the string

So:
If I have the string "1543", result = 0
we multiply result by ten : result = 0
we add the first digit: result = 1
remove the first digit from the string "543"
we multiply result by ten : result = 10
we add the first digit: result = 15
remove the first digit from the string "43"
we multiply result by ten : result = 150
we add the first digit: result = 154
remove the first digit from the string "3"
we multiply result by ten : result = 1540
we add the first digit: result = 1543
remove the first digit from the string ""
string is empty, so we're done

I wrote code, but then remembered this was a homework problem.

1 Comment

This is assuming stringstream is not allowed

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.