【问题标题】:How to check a string contains a valid real number如何检查字符串是否包含有效的实数
【发布时间】:2017-04-05 09:13:03
【问题描述】:

我需要检查第二个命令行参数,看看它是否是一个有效的浮点数。

#include <stdio.h>
#include <math.h>

long int fact(int n)
{
    if (n >= 1)
        return n*fact(n - 1);
    else
        return 1;
}

double func(int x0, int n)
{
    int p = 2 * n + 1;

    return (double)pow(x0, p) / (double)fact(p);
}

double sinh_(int x0, int N)
{
    double sum = 0;
    int i = 0;
    for (i = 0; i <= N; i++)
    {
        sum = sum + func(x0, i);
    }

    return sum;
}

double err(int x0, int N)
{
    return abs(sinh(x0) - sinh_(x0, N));
}

int main(int argc, char**argv)
{
    double x0 = 0;
    int N = 0;

    printf("No of args %d\n", argc);

    //if CLA doesn't have exactly 4 arguments passed return -1
    //1st argument is app-name
    //2nd argument is x0
    //4th argument is N
    if (argc >= 3)
    {
        printf("Err: no of arguments should be 2");
        return -1;
    }
    //if the 2nd CLA is not a number, return -1     
    if (!isdigit(atof(argv[1])))
    {
        printf("1st argument must be a real value");
        return -1;
    }
    //if the 3rd CLA is not a number, return -1     
    if (!isdigit(atoi(argv[2])))
    {
        printf("2nd argument must be an int value");
        return -1;
    }

    x0 = atof(argv[1]);
    N = atoi(argv[2]);

    printf("Builtin sinh = %f", sinh(x0));
    printf("Approx sinh = %f", sinh_(x0, N));
    printf("Err value = %f", err(x0, N));
}

【问题讨论】:

  • 使用strtod 并检查*endptr
  • man page on GNU/Linux for strtol 有一个(相关的)扩展示例。
  • 另外,isdigit(atoi(argv[2])) 是错误的。它将字符串转换为整数,然后检查该整数是否是十进制数字的代码,即 48 到 57 的值之一,假设为 ASCII。 isdigit(atof(argv[1])) 因类似原因不正确,但涉及 double 而不是 int
  • 另外,检查if (argc &gt;= 3) 不正确。应该是if (argc != 3)

标签: c command-line


【解决方案1】:

atof 不会返回指示转换是否成功的状态,您需要为此使用strtod。检查endptr返回后是否为NULL,同时检查是否有上溢或下溢。

double strtod(const char *nptr, char **endptr);

char *end = NULL;
double x0 = strtod(argv[1], &end);
if (*end) {
      // error, not a valid floating point number
}
if (errno == ERANGE) {
     // error, overflow or underflow
}

【讨论】:

  • if (end) 将永远为真。
【解决方案2】:

strto... 系列函数,例如将字符串转换为doublestrtod 和将字符串转换为long intstrtol,可以为您提供有关转换结束的字符串中下落的信息。

如果字符串不是以可选的空格后跟有效数字开头,它们将报告转换在字符串开头结束。否则他们将报告导致转换结束的字符的位置。所以要检查错误,检查位置是否从字符串的开头“移动”,并检查报告的结束位置的字符。

这些函数还检查超出范围的值,将 errno 设置为 ERANGE 并返回特定值。

下面的代码检查字符串是否以数字后的空终止符结尾,但在某些情况下,对于包含多个分隔值的字符串,您可能需要检查有效的分隔字符。

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>

int main(int argc, char **argv)
{
    double x0;
    long int N;
    char *endptr;

    if (argc != 3)
    {
        fprintf(stderr, "usage: %s x0 N\n", argv[0]);
        return 2;
    }

    errno = 0;
    x0 = strtod(argv[1], &endptr);
    if (endptr == argv[1] || *endptr != '\0')
    {
        fprintf(stderr, "1st argument must be a real value\n");
        return 2;
    }
    if (errno == ERANGE)
    {
        fprintf(stderr, "1st argument out of range\n");
        return 2;
    }

    errno = 0;
    N = strtol(argv[2], &endptr, 10);
    if (endptr == argv[2] || *endptr != '\0')
    {
        fprintf(stderr, "2nd argument must be an integer value\n");
        return 2;
    }
    if (errno == ERANGE)
    {
        fprintf(stderr, "2nd argument out of range\n");
        return 2;
    }

    printf("x0:%g; N:%ld\n", x0, N);
    return 0;
}

为方便起见,我将N 的类型更改为long int,因为没有返回intstrtoi 函数。

【讨论】:

    猜你喜欢
    • 2017-01-20
    • 1970-01-01
    • 1970-01-01
    • 2017-09-23
    • 2013-11-20
    • 1970-01-01
    • 1970-01-01
    • 2021-11-21
    相关资源
    最近更新 更多