Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/63.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 字符串长度有限的strod_C_Strtod - Fatal编程技术网

C 字符串长度有限的strod

C 字符串长度有限的strod,c,strtod,C,Strtod,如果我想将char数组中的前3个字符作为双精度字符进行解析,而忽略以下字符,那么我真的需要这样做吗 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 i

如果我想将char数组中的前3个字符作为双精度字符进行解析,而忽略以下字符,那么我真的需要这样做吗

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); } int main(){ 常量字符a[]=“1.23”; char*b=malloc(sizeof(char)*4); memcpy(b,a,sizeof(char)*3); b[3]='\0'; printf(“%f\n”,strod(b,NULL));//打印1.20000,这是我想要的 免费(b); } 是否有一个类似于strtod的函数,允许您指定搜索数字时应使用的最大字符串长度


编辑:我想让它打印
1.2
(目前是这样),而不是
1.23

strtod的签名是这样的

   double strtod(const char *nptr, char **endptr);
该函数将返回由
nptr
指向的字符串的初始部分。如果
endptr
不是
NULL
,则指向转换中使用的最后一个字符后的字符的指针将存储在
endptr
引用的位置


因此,它不允许您指定需要转换的字符数。因此,您必须修改输入本身,并将其传递给<代码> Strutod .< /P> < P>如果您总是希望只考虑给定字符串中的三个第一个字符,则可以使用以下代码:

#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;
}
#包括
#包括
双解析(const char*str){
char*tmp=0;
双结果=0;
asprintf(&tmp,“%.3s”,str);
结果=strtod(tmp,0);
免费(tmp);
返回结果;
}
内部主(空){
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
返回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;
}
/*
*与strtod()相同,但只考虑前n个字符。
*另外返回0。如果“nptr”为空,则将errno设置为EINVAL。
*/
双strntod(常量字符*nptr,字符**endptr,大小)
{
双重结果;
/*执行输入验证*/
如果(!nptr)
{
errno=EINVAL;
结果=0。;
如果(endptr)
{
*endptr=nptr;
}
后进先出;
}
如果(strlen(nptr)而
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;
}
#包括
double parseDouble(const char*str){
双val=0;
int numCharsRead;
//通过设置或返回错误标志来处理错误。
如果(sscanf(str、%3lf%n、&val和numCharsRead)!=1){
puts(“未能解析双精度!”;
}
否则如果(numharsread!=3){
puts(“读取少于三个字符!”);
}
返回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”);//读取少于三个字符!\n0.300000
返回0;
}
sscanf(str、%3lf%n)、&val和numCharsRead
是重要的部分:您指定的最大宽度为3,这意味着
sscanf()
将为该特定字段读取最多3个字符,并将解析结束时消耗的字符数存储在
numCharsRead
中。如果您希望每次只读取3个字符,则可以检查该值;如果您对3个或更少字符没有问题,则可以使用
sscanf(str,%3lf,&val)
。以下是宽度说明符的文档,供参考:

指定最大字段宽度的可选十进制整数。 当达到此最大值或出现错误时,将停止读取字符 找到非匹配字符,以先发生的为准。大多数转换 丢弃初始空白字符(例外情况如下所述), 这些被丢弃的字符不计入最大字段宽度。 字符串输入转换存储一个终止的空字节('\0')以标记结束 最大字段宽度不包括此终止符


我已经知道了。我在问是否有其他函数提供了我想要的功能。我没有期望的精度,我希望它受到字符串大小的限制,所以
“1.23”=>1.2
“1234”=>123.0
&
“0.09”=>0.0
@alk您获取字符串的前三个字符:
“1234”=>“123”
,然后将其转换为双精度
“123”=>123.0
@Tyilo:好的,我明白了…-不管这背后的想法是什么,你可能想看看我的答案,找到一个可能的解决办法。@Tyilo:欢迎,但你确定你接受了正确的答案…;->?@Tyilo,这只是一种迂回的方式,除了
asprintf()
不是很好移植,而且
memcpy()
更适合只复制字节。正确的方法是
sscanf()
,我添加了一个关于它的答案。很好,除了两点。1)使用
str==“1.3”
,-->
numCharsRead==4
val==123
中的
3
%3lf%n
将扫描并在转换中使用的特许证数量限制为3。
%n
报告扫描的数量,是否在转换中使用。2)
val
未在失败路径上定义。请尝试
printf(“%lf\n”,parseDouble(“xyz”))
首先。是的,第一个是一个很好的观点。我没有提出它,但它在文档中引起了我的注意;唯一的解决办法是可能手动跳过字符串中的任何空白。至于
val
未定义,你是对的,但这只是一个简单的例子。实际上,你可能想C以不同的方式运行,如果解析失败,则设置或返回错误标志。确定
val
count对OP的目标并不重要,但