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.

AgentRev
  • 749
  • 1
  • 8
  • 20
  • Are you allowed to use Boost? – Alok Save Sep 15 '11 at 18:35
  • I don't suppose you are allowed to use stringstream? – nobsid Sep 15 '11 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." – AgentRev Sep 15 '11 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 – Anthony Accioly Sep 15 '11 at 18:39
  • possible duplicate of [Convert char array to single int?](http://stackoverflow.com/questions/6093414/convert-char-array-to-single-int) – Alok Save Sep 15 '11 at 18:39
  • I wouldn't consider it as duplicate, since I am limited to using only the aforementioned classes and function. – AgentRev Sep 15 '11 at 18:47
  • 3
    `stringstream`s *are* iostream classes. See http://cplusplus.com/reference/iostream/stringstream/. – robert Sep 15 '11 at 18:54
  • I wonder why `system()` is allowed. – R. Martinho Fernandes Sep 15 '11 at 20:20
  • Hmm. I wonder if the prof meant only `class iostream` and `class string`, or if he meant "only those classes defined in `` and ``. There are more classes in `` than just `iostream`. – Robᵩ Sep 15 '11 at 20:23
  • `system()` is allowed to people using MS Windows IDEs that auto-launch a command prompt window to run your console-mode program can do `system("pause");` – Robᵩ Sep 15 '11 at 20:24

5 Answers5

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.)

R. Martinho Fernandes
  • 228,013
  • 71
  • 433
  • 510
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).

robert
  • 3,484
  • 3
  • 29
  • 38
  • `std::ostringstream("1234")` would be enough – Andriy Tylychko Sep 15 '11 at 18:39
  • I just added some extra information in bold text to my question. – AgentRev Sep 15 '11 at 18:49
  • Thanks, Andy. I have adapted the code to demonstrate that `stringstream`s can be reused, while `ostringstream`s cannot. It would be interesting to determine if my way of doing it is *actually* faster. I'm not sure. – robert Sep 15 '11 at 18:52
  • 2
    @AgentRev: Technically, stringstream is both an iostream _and_ a string class in the standard library. – Mooing Duck Sep 15 '11 at 19:03
  • @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?) – robert Sep 15 '11 at 20:10
  • This isn't thread-safe. Use `thread_local` instead of `static`. –  Jan 23 '15 at 08:25
  • @рытфолд: Thanks for pointing out! I updated my answer with a warning about thread-safety. – robert Jan 23 '15 at 12:12
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;
}
Ahmed Khalaf
  • 1,401
  • 2
  • 15
  • 29
  • 4
    Usually, primitive types like `int` (and char, short, long, float, double, ...) are passed *by value*, not by reference. – robert Sep 15 '11 at 22:23
1
std::string mystring = "12";

std::ostringstream str(mystring);
int someint;
str >> someint;
Tony The Lion
  • 61,704
  • 67
  • 242
  • 415
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.

Mooing Duck
  • 64,318
  • 19
  • 100
  • 158