如果我想将char数组中的前3个字符解析为double,忽略以下字符,我真的需要这样做吗?
int main() { const char a[] = "1.23"; char *b = malloc(sizeof(char) * 4); memcpy(b, a, sizeof(char) * 3); b[3] = '\0'; printf("%f\n", strtod(b, NULL)); // Prints 1.20000, which is what I want free(b); }
是不是像strtod
这样的函数允许你指定它应该搜索数字的最大字符串长度?
修改:我希望它能够打印1.2
(目前正在进行),不是 1.23
!
答案 0 :(得分:5)
虽然strtod()
不允许您限制字符串长度,但您可以使用sscanf()
最大字段宽度并可选择检查字符串数量消费的字符,如下:
#include <stdio.h>
double parseDouble(const char *str){
double val = 0;
int numCharsRead;
// Handle errors by setting or returning an error flag.
if(sscanf(str, "%3lf%n", &val, &numCharsRead) != 1){
puts("Failed to parse double!");
}
else if(numCharsRead != 3){
puts("Read less than three characters!");
}
return val;
}
int main(){
printf("%lf\n", parseDouble("1.3")); // 1.300000
printf("%lf\n", parseDouble("1.5999")); // 1.500000
printf("%lf\n", parseDouble(".391")); // 0.390000
printf("%lf\n", parseDouble(".3")); // Read less than three characters!\n0.300000
return 0;
}
sscanf(str, "%3lf%n", &val, &numCharsRead
是重要的部分:您指定的最大宽度为3,这意味着sscanf()
将为该特定字段读取最多3个字符,并且还存储numCharsRead
中解析结束时消耗的字符数。如果您每次只读3个字符,则可以检查该值;如果您使用3或更少,则可以使用sscanf(str, "%3lf", &val)
。作为参考,这里是宽度说明符的文档:
可选的十进制整数,指定最大字段宽度。 当达到此最大值或a时,读取字符会停止 找到不匹配的字符,以先发生者为准。大多数转换 丢弃最初的空白字符(以下说明例外情况), 并且这些丢弃的字符不计入最大字段宽度。 字符串输入转换存储终止空字节(&#39; \ 0&#39;)以标记结尾 输入;最大字段宽度不包括此终结符。
答案 1 :(得分:2)
如果您始终只想考虑给定字符串中的前三个字符,可以使用以下代码:
#include <stdio.h>
#include <string.h>
double parse_double(const char *str) {
char *tmp = 0;
double result = 0;
asprintf(&tmp, "%.3s", str);
result = strtod(tmp, 0);
free(tmp);
return result;
}
int main(void) {
printf("%f\n", parse_double("1.23")); // 1.2
printf("%f\n", parse_double("1234")); // 123
printf("%f\n", parse_double("0.09")); // 0.0
return 0;
}
答案 2 :(得分:0)
strtod
的签名就像这样
double strtod(const char *nptr, char **endptr);
该函数将返回nptr
指向的字符串的初始部分。如果endptr
不是NULL
,则转换中使用的最后一个字符后面的字符指针将存储在endptr
引用的位置。
因此它不允许您指定需要转换的字符数。因此,您必须自行修改输入并将其传递给strtod
。
答案 3 :(得分:0)
不,标准库中没有这样的功能。
但推出一个人自己很有趣:
/*
* Same as strtod() but only takes the first n characters into account.
* Additionally returns 0. and sets errno to EINVAL if 'nptr' is NULL.
*/
double strntod(const char *nptr, char **endptr, size_t n)
{
double result;
/* perform input validation */
if (!nptr)
{
errno = EINVAL;
result = 0.;
if (endptr)
{
*endptr = nptr;
}
goto lblExit;
}
if (strlen(nptr) <= n)
{
/* Nothing to truncate: fall back to standard 'strtod()' */
result = strtod(nptr, endptr);
}
else
{
/* create working copy of string */
char * ptmp = strdup(nptr);
/* Test whether 'strdup()' failed */
if (!ptmp)
{
result = 0.;
if (endptr)
{
*endptr = nptr;
}
goto lblExit;
}
/* truncate working copy to n characters */
ptmp[n] = `\0`;
/* do original 'strtod()' on truncated working copy */
result = strtod(ptmp, endptr);
/* adjust '*endptr' to point to original character array, but to working copy */
if (endptr)
{
*endptr = nptr + (*endptr - ptmp);
}
/* free working copy */
free(ptmp);
}
lblExit:
return result;
}