3
\$\begingroup\$

I'm teaching myself C++ by reading Stroupstrup's Programming Principles and Practice Using C++, and I'm working on an exercise in chapter 4. The exercise asks to convert input as a digit to the corresponding spelled-out value e.g. input of 1 gives the output "one".

#include "std_lib_facilities.h"

using namespace std;

//Workaround for compiler issue.
int stoi( const std::string& str, std::size_t* pos = 0, int base = 10 )
    {
        const char* begin = str.c_str() ;
        char* end = nullptr ;
        long value = std::strtol( begin, &end, base ) ;

        if( errno == ERANGE || value > std::numeric_limits<int>::max() )
            throw std::out_of_range( "stoi: out ofrange" ) ;

        if( end == str.c_str() )
            throw std::invalid_argument( "stoi: invalid argument" ) ;

        if(pos) *pos = end - begin ;

        return value ;
    }


int main()
{
    struct Numbers
    {
        string spelled;
        int digit;
    };
    const Numbers nums[]
    {
        {"zero", 0},
        {"one", 1},
        {"two", 2},
        {"three", 3},
        {"four", 4},
        {"five", 5},
        {"six", 6},
        {"seven", 7},
        {"eight", 8},
        {"nine", 9},
        {"ten", 10}
    };

    string response = " ";

    cout << "Type a number either spelled out or as a digit.\n";

    cin >> response;
    if(response.size() == 1)
    {
        cout << nums[stoi(response)].spelled;
    }
    else if(response.size() > 1)
    {
        for(int i=0; i<=10; ++i)
        {
            if(response == nums[i].spelled)
            {
                cout << nums[i].digit << endl;
                break;
            }
            else;
        }
    }
}

Is there a better way to check the type of input the user gives other than checking the response size? Would it have been easier/more efficient if I had used a vector? In my for loop, does that break in the if statement break the loop?

\$\endgroup\$
1
  • \$\begingroup\$ Sorry if I'm missing something, but does your code handle multi-digit numbers? (like 25?) Somehow reading through this quickly, I am missing a case where you'd handle multiple digit numbers. \$\endgroup\$
    – sunny
    Sep 23, 2015 at 14:29

1 Answer 1

2
\$\begingroup\$

This is now a conflict:

using namespace std;

//Workaround for compiler issue.
int stoi( const std::string& str, std::size_t* pos = 0, int base = 10 )

There is an stoi in the standard namespace. Because you used using this will be considered with your function. They both have the same parameter types so this should generate a compiler error.

The only reason it may not be doing so is that you are using an archaic version of the language.

You have to reset errno to a zero state before using a function that sets it (std::strtol does not change the value if there is no error it just sets the value if there is an error).

    if( errno == ERANGE || value > std::numeric_limits<int>::max() )
        throw std::out_of_range( "stoi: out ofrange" ) ;

This will fail if a previous library call set errno to ERANGE.

Don't like the extra indention of you r function:

int stoi( const std::string& str, std::size_t* pos = 0, int base = 10 )
    {
^^^^!

Prefer to use {} around block statements.

if( errno == ERANGE || value > std::numeric_limits<int>::max() )
            throw std::out_of_range( "stoi: out ofrange" ) ;

// Best to be safe
// So consistent use of '{}' is usually best.
if( errno == ERANGE || value > std::numeric_limits<int>::max() ) {
            throw std::out_of_range( "stoi: out ofrange" ) ;
}

Readability enhanced by using another line:

if(pos) *pos = end - begin ;

// Easier to read for your next maintainer.
if(pos) {
    *pos = end - begin ;
}
\$\endgroup\$
1
  • \$\begingroup\$ The workaround is solely for me. Codeblocks, for whatever reason, does not recognize stoi for me even though I'm using C++11. That said, you didn't answer any of my question. \$\endgroup\$
    – CoopTang
    Sep 27, 2015 at 22:37

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.