在C语言中将字符串转换为双精度变量

22
我写了下面的代码。它应该将类似于"88"的字符串转换为双精度浮点数88并打印出来。
void convertType(char* value)
{
   int i = 0;
   char ch;
   double ret = 0;
   while((ch = value[i])!= '\0')
   {
      ret = ret*10 + (ch - '0');
      i++;
   }
   printf("%d",ret); //or %lf..
}

// input string :88

但它总是打印0。但当我将ret的类型更改为int时,它可以正常工作。当类型为floatdouble时,它会打印0。那么我为什么会得到这些不明确的结果呢?


1
在 C 语言中没有字符串这个东西;-) - Aidanc
3
"%f""%g"(指数格式用"%e")既可用于(float)也可用于(double) - geekosaur
14
C标准不同意你的看法。C标准库引言中“术语定义”部分的第一句话在7.1.1节中说:“字符串是由连续字符序列组成并以包括第一个空字符为结束符的。”因此,就标准而言,字符串是存在的。 - Jonathan Leffler
顺便说一句:如果你想要一个稍微更快、更小的循环版本: for( ; *value != '\0'; ret = 10*ret + *value++ - '0'); - abelenky
1
@JonathanLefflerm 是的,字符串存在。但是它们不像许多其他语言那样是语言的数据类型。它们只是标准库中几个函数理解的一种约定。 - Lee Daniel Crocker
显示剩余3条评论
8个回答

35

使用sscanf函数(在C++中包含头文件stdio.hcstdio):

char str[] = "12345.56";
double d;

sscanf(str, "%lf", &d);

printf("%lf", d);

2
我不同意这是一个好答案。它没有解决问题,而且 OP 的循环解析字符串到双精度浮点数也没有任何问题。 - abelenky
3
我不是说这是一种错误的方式,但它是在重新发明轮子(就像我们在波兰所说的那样)。 - Hauleth
4
这个回答很好啊,它能够将一个字符串转化为双精度浮点数,为什么不接受这个答案呢?如果有什么本质的问题,请进一步阐述。 - Alexej Magura

6
你可能可以使用atof()函数,它返回一个double类型的值。

源代码


我尝试了atof和strtod()函数,两者都打印出0...只有当ret的类型更改为int时才有效。 - Jinu Joseph Daniel
@Jinu,这不是 atof 或 strtod 的问题。请检查我的答案。 - Pavan Manjunath
此外,此答案中的链接现在已经失效。 - Anderson Green

5
但它总是打印 0...但当我将 ret 的类型更改为 int 时,它就可以正常工作了...当类型为 float 或 double 时,它会打印零。
逻辑没问题。只是你的格式说明符不正确。将其更改为 %f 就行了!

1
如果您想将char*解析为double,应使用“atof”函数。
如果要打印double,还应使用分隔符“%f”:
更多信息和用例可以在此处找到。
用法示例:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
   float val;
   char str[20];

   strcpy(str, "98993489");
   val = atof(str);
   printf("String value = %s, Float value = %f\n", str, val);

   strcpy(str, "tutorialspoint.com");
   val = atof(str);
   printf("String value = %s, Float value = %f\n", str, val);

   return(0);
}

要打印它,必须将其打印为浮点数:

printf("This is the value in float: %f\n", yourFloatValue);

1
atof函数在某些情况下似乎不太可靠。 - Anderson Green

1
将字符串转换为C语言中的双精度变量
如果不考虑溢出问题,但代码想要检测数值文本后面的额外非空格文本:
// return 1 on success
int convertType(const char* value, double *destination) {
  char sentinel;
  return sscanf(value,"%f %c", destination, &sentinel) == 1;
}

如果sscanf()无法找到一个double,则sscanf()的返回值将是EOF或0。
如果sscanf()在数字文本后找到非空格文本,则返回2。
如果只扫描了一个double,没有额外的内容,sscanf()返回1。前导和尾随空格都可以。
示例:
double x;
if (convertType(some_string, &x)) {
  printf("%.17e\n", x);  // or whatever FP format you like
} else {
  puts("Failed");
}

0
这对我有效:
double stod(const char* s); //declaration

double d = stod(row[0]); //call


double stod(const char* s){    //definition
    double rez = 0, fact = 1;
    if (*s == '-'){
        s++;
        fact = -1;
    };
    for (int point_seen = 0; *s; s++){
        if (*s == '.'){
            point_seen = 1;
            continue;
        };
        int d = *s - '0';
        if (d >= 0 && d <= 9){
            if (point_seen) fact /= 10.0f;
            rez = rez * 10.0f + (float)d;
        };
    };
    return rez * fact;
};

考虑添加一些关于你的代码如何工作的细节? - PiRocks

-2

以下代码对我有效。

#include <stdio.h>

void convertType(char* value);

int main(int argc, char *argv[]) {
    char *str="0929";
    convertType(str);

    return  0;
}

void convertType(char* value) {
    double ret = 0;

    while(*value != '\0') {
        ret = ret*10 +(*value - '0');
        value++;
    }

    fprintf(stdout, "value: %f\n", ret);
}

这并不能为输入-.00314159E+003提供一个好的答案,不是吗? - Jonathan Leffler

-2
#define ZERO 48
#define NINE 57
#define MINUS 45
#define DECPNT 46

long strtolng_n(char* str, int n)
{
    int sign = 1;
    int place = 1;
    long ret = 0;

    int i;
    for (i = n-1; i >= 0; i--, place *= 10)
    {
        int c = str[i];
        switch (c)
        {
            case MINUS:
                if (i == 0) sign = -1;
                else return -1;
                break;
            default:
                if (c >= ZERO && c <= NINE) ret += (c - ZERO) * place;
                else return -1;
        }
    }

    return sign * ret;
}

double _double_fraction(char* str, int n)
{
    double place = 0.1;
    double ret = 0.0;

    int i;
    for (i = 0; i < n; i++, place /= 10)
    {
        int c = str[i];
        ret += (c - ZERO) * place;
    }
    return ret;
}
double strtodbl(char* str)
{
    int n = 0;
    int sign = 1;
    int d = -1;
    long ret = 0;

    char* temp = str;
    while (*temp != '\0')
    {
        switch (*temp)
        {
            case MINUS:
                if (n == 0) sign = -1;
                else return -1;
                break;
            case DECPNT:
                if (d == -1) d = n;
                else return -1;
                break;
            default:
                if (*temp < ZERO && *temp > NINE) return -1;
        }
        n++;
        temp++;
    }

    if (d == -1)
    {
        return (double)(strtolng_n(str, n));
    }
    else if (d == 0)
    {
        return _double_fraction((str+d+1), (n-d-1));
    }
    else if (sign == -1 && d == 1)
    {
        return (-1)*_double_fraction((str+d+1), (n-d-1));
    }
    else if (sign == -1)
    {
        ret = strtolng_n(str+1, d-1);
        return (-1) * (ret + _double_fraction((str+d+1), (n-d-1)));
    }
    else
    {
        ret = strtolng_n(str, d);
        return ret + _double_fraction((str+d+1), (n-d-1));
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接