不使用内置函数(例如atoi或atof)将字符串转换为浮点数或整数

时间:2018-10-08 15:06:36

标签: c++ type-conversion

我是C ++的新手,我们的老师要求我们获得一个具有上述名称的函数。到目前为止,我已经有了一个将字符串转换为整数的函数,但是我不知道如何修改使其在字符串中的数字表示浮点数的情况下起作用。

int convert(char str[], int size) {
    int number = 0;
    for (int i = 0; i < size; ++i) {
        number += (str[i] - 48)*pow(10, (size - i - 1));
    }
    return number;
}

如果我跑步:

char myString[] = "12345";
convert(myString, 5);

我得到:

12345

但是如果我跑步:

char myString[] = "123.45";
convert(myString, 5);

我得到:

122845

如何修改程序以使其也可以与浮点数一起使用?我知道 convert 函数是要返回一个int的,所以,我应该再使用两个函数吗?

我在考虑的一个因素是将字符串确定为要转换为整数或字符串,而另一个将实际将字符串转换为浮点数。

3 个答案:

答案 0 :(得分:1)

这是执行此操作的功能...

template<class T, class S>
T convert_string_to_number(S s)
{
    auto result = T(0.l);
    if (s.back() == L'F' || s.back() == L'f')
        s = s.substr(0u, s.size() - 1u);
    auto temp = s;
    auto should_add = false;
    if (!std::is_floating_point<T>::value)
    {
        should_add = temp.at(temp.find_first_of(L'.') + 1) >= '5';
        temp.erase(temp.begin() + temp.find_first_of(L'.'), temp.end());
    }
    else if (temp.find_first_of(L'.') != S::npos)
        temp.erase(temp.begin() + temp.find_first_of(L'.'));
    for (int i = temp.size() - 1u; i >= 0; --i)
        if (temp[i] >= L'0' && temp[i] <= L'9')
            result += T(std::powl(10.l, temp.size() - i - 1.l) * (temp[i] - L'0'));
        else
            throw std::invalid_argument("Invalid numerical string!");
    if (s.find(L'-') != S::npos)
        result = -T(std::fabs(result));
    if (s.find(L'.') != S::npos && std::is_floating_point<T>::value)
        result /= T(std::powl(10.l, s.size() - s.find(L'.') - 1.l));
    return std::is_floating_point<T>::value ? T(result) : T(result + T(should_add));
}

只需像平常一样使用它即可...

auto some_number = convert_string_to_number<float>(myString); ...

答案 1 :(得分:0)

对于赋值的浮点部分:正则表达式呢?它也是一种内置功能,但具有通用性,不是为您的特定任务而设计的,因此希望您的老师对此想法感到满意。

您可以使用以下正则表达式:[+-]?([0-9]*[.])?[0-9]+(我从this answer获得)来检测提供的字符串是否为浮点数。然后,您可以稍微修改表达式以捕获点分隔符之前/之后的+/-符号和部分。提取这些功能后,任务应该相对简单。

还请将您的方法签名更改为:float convert(const std::string& str)

答案 2 :(得分:0)

尝试一下:

int convert(char str[], int size) {
    int number = 0;
    for (int i = 0; i < size; ++i) {
        number += (str[i] - 48)*pow(10, (size - i - 1));
    }
    return number;
}

int pow10(int radix)
{
    int r = 1;
    for (int i = 0; i < radix; i++)
        r *= 10;
    return r;
}

float convert2float(char str[], int size) {       //size =6
    // convert to string_without_decimal
    char str_without_decimal[10];
    int c = 0;
    for (int i = 0; i < size; i++)
    {
        if (str[i] >= 48 && str[i] <= 57) {
            str_without_decimal[c] = str[i];
            c++;
        }
    }
    str_without_decimal[c] = '\0';      //str_without_decimal = "12345"

    //adjust size if dot present or not.  If no dot present => size = c
    size = (size != c ?) size - 1 : size;      //size = 5 = 6-1 since dot is present

    //convert to decimal
    int decimal = convert(str_without_decimal, size);  //decimal = 12345

    //get divisor
    int i;
    for (i = size; i >= 0; i--) {
        if (str[i] == '.') break;
    }
    int divisor = pow10(size - i);     //divisor = 10;
    return (float)decimal/(float) divisor;  // result = 12345 /10
}

int main()
{
    char str[] = "1234.5";
    float f = convert2float(str, 6);
    cout << f << endl;
    return 0;
}