这是检查字符串是否代表浮点数的不好方法吗?

问题描述 投票:5回答:2

在网上看我没有找到满意我的解决方案,所以我自己尝试了。但现在在讲座中也有人说调用函数和等待返回可能会导致堆栈溢出,这是一个坏主意吗?我使用此函数来检查argv [1]是否为浮点数。循环会更好吗?还是有更直观的方法?必须有一个点,然后必须至少跟一个数字对吗?

#include <stdbool.h>
#include <ctype.h>

 /**
 * checks if string is floating point number
 * please call function with pointCounter=0 and digitAfterPoint=false
 */
bool isFloatString(char *s, int pointCounter, bool digitAfterPoint) 
{                                                                   

    if (isdigit(*s))
    {
        if(pointCounter==1)
        {
            digitAfterPoint=true;
        }
        return  isFloatString(s+1, pointCounter, digitAfterPoint);
    }

    else if (*s == '.' && pointCounter==0)
    {
        return isFloatString(s+1, pointCounter+1,digitAfterPoint);
    }
    else if (*s == '\0' && digitAfterPoint)
    {
        return true;
    }
    else
    {
        return false;
    }

}
c
2个回答
4
投票

对于999位数和一个点,每个返回地址有1000个递归调用,堆栈上有三个参数。我会发现没关系。然而,非递归迭代解决方案消除了状态参数,并且更易于阅读(仅在这种情况下)。

bool isFloatString(char *s)
{
    int pointCounter = 0;
    bool digitAfterPoint = false;
    while (*s != '\0')
    {
        if (isdigit(*s))
            digitAfterPoint = pointCounter == 1;
        }
        else if (*s == '.' && pointCounter == 0)
        {
            ++pointCounter;
        }
        else
        {
            return false;
        }
        ++s;
    }
    return digitAfterPoint;
}

介意:递归解决方案受到恶意堆栈溢出的影响。


@MatteoItalia正确地指出只有尾递归(结果没有做任何事情),所以任何成熟的C / C ++编译器都会将递归转换为跳转(迭代)。在这里他的反汇编(参见评论中的链接)。

isFloatString(char*, int, bool):
  movsx ecx, BYTE PTR [rdi]
  mov r9d, edx
  mov r8d, ecx
  sub ecx, 48
  cmp ecx, 9
  jbe .L23
  cmp r8b, 46
  je .L24
  test r8b, r8b
  sete al
  and eax, edx
  ret
.L24:
  xor eax, eax
  test esi, esi
  je .L25
.L1:
  rep ret
.L23:
  movsx eax, BYTE PTR [rdi+1]
  mov ecx, eax
  sub eax, 48
  cmp esi, 1
  je .L26
  cmp eax, 9
  movzx edx, dl
  jbe .L10
  cmp cl, 46
  je .L27
.L8:
  test cl, cl
  sete al
  and eax, r9d
  ret
.L26:
  cmp eax, 9
  jbe .L28
  xor eax, eax
  cmp cl, 46
  mov r9d, 1
  jne .L8
  jmp .L1
.L28:
  mov edx, 1
.L10:
  add rdi, 2
  jmp isFloatString(char*, int, bool)
.L25:
  movzx edx, dl
  add rdi, 1
  mov esi, 1
  jmp isFloatString(char*, int, bool)
.L27:
  xor eax, eax
  test esi, esi
  jne .L1
  add rdi, 2
  mov esi, 1
  jmp isFloatString(char*, int, bool)

0
投票

检查字符串是否代表浮点数?

C标准库使用strtof()strtod()strtold()提供简单的强大解决方案

// leading whitespace OK, trailing text OK, over/underflow OK
bool isFloatString_Simple(const char *s) {
  char *endptr;
  strtof(s, &endptr);
  return endptr > s;
}

领先的空间还行吗? 数字文本后是尾随垃圾吗? 如果溢出一个问题? 如果下流问题?

然后需要更多代码。根据需要调整。

bool isFloatString_Picky(const char *s) {
  char *endptr;
  errno = 0;
  float f = strtof(s, &endptr);
  if (s == endptr) return false; // no conversion

  if (isspace((unsigned char) *s)) return false; // reject leading white-space
  if (*endptr) return false; // reject junk after numeric text

  if (errno) {
    if (fabsf(f) > 1.0f) return false; // reject on overflow
    // yet pass on underflow.
  }
  return true;
}
© www.soinside.com 2019 - 2024. All rights reserved.