在网上看我没有找到满意我的解决方案,所以我自己尝试了。但现在在讲座中也有人说调用函数和等待返回可能会导致堆栈溢出,这是一个坏主意吗?我使用此函数来检查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;
}
}
对于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)
检查字符串是否代表浮点数?
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;
}