开发者

get atof to continue converting a string to a number after the first non valid ch in a string

i'd like to know if there a way to get atof continue converting to number even if there are non valid charcters in the way

for example let say i have string "444-3-3-33" i want to covert 开发者_运维知识库it to a double a=4443333 (and keep the string as it was) happy to get any suggestions or an alternative way

thanks!


I can't take credit for this solution, though it's a good one, see this SO post. For those too lazy to skip over, the author recommends using a locale to treat all non-numeric digits as whitespace. It might be overkill for your solution but the idea is easily adaptable. Instead of all non-numeric, you could just use "-" as your whitespace. Here's his code, not mine. Please, if you like this give him the upvote.

struct digits_only: std::ctype<char> 
{
    digits_only(): std::ctype<char>(get_table()) {}

    static std::ctype_base::mask const* get_table()
    {
        static std::vector<std::ctype_base::mask> 
            rc(std::ctype<char>::table_size,std::ctype_base::space);

        std::fill(&rc['0'], &rc['9'], std::ctype_base::digit);
        return &rc[0];
    }
};

bool in_range(int lower, int upper, std::string const &input) { 
    std::istringstream buffer(input);
    buffer.imbue(std::locale(std::locale(), new digits_only()));

    int n;

    while (buffer>>n)
        if (n < lower || upper < n)
            return false;
    return true;
}

Then just remove the whitespace and pass the string to atof.


Both of the following strip out non-digits for me

bool no_digit(char ch) {return !std::isdigit(ch);}

std::string read_number(const std::string& input)
{
    std::string result;
    std::remove_copy_if( input.begin()
                       , input.end()
                       , std::back_inserter(result)
                       , &no_digit);
    return result;
}

std::string read_number(std::istream& is)
{
    std::string result;
    for(;;) {
        while(is.good() && !std::isdigit(is.peek()))
            is.get();
        if(!is.good())
            return result;
        result += is.get();
    }
    assert(false);
}

You can then read number using string streams:

std::istringstream iss(read_number("444-3-3-33");
int i;
if( !(iss>>i) ) throw "something went wrong!";
std::cout << i << '\n';


I would recommend sscanf

[edit]

upon further review, it would seem that you'll have to use strstr as sscanf could have an issue with the embedded '-'

further, the page should give you a good start on finding (and removing) your '-' char's

[/edit]


copy the 'string number' to a local buffer(a std::string), then strip out the accepted chars from the number(compressing the string, as to not leave blank space, thus using std::string.replace), then call atof on std::string.c_str. alternatly you can use c strings, but then this wouldn't be C++.

alternatively, create a custom version of atof your self, using the source from say stdlibc or basic math.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜