4

次の文字を無視して、char 配列の最初の 3 文字を double として解析したい場合、本当にこれを行う必要がありますか?

int main() {
    const char a[] = "1.23";
    char *b = malloc(sizeof(char) * 4);

    memcpy(b, a, sizeof(文字) * 3);
    b[3] = '\0';

    printf("%f\n", strtod(b, NULL)); // 1.20000 を出力します。これは私が望むものです

    無料 (b);
}

strtod数字を検索する文字列の最大長を指定できるような機能はありませんか?

編集:私はそれを印刷したい1.2(現在はそうしています)、ではありません 1.23

4

4 に答える 4

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 を指定します。これは、その特定のフィールドに対して最大 3sscanf()文字を読み取り、解析の最後までに消費された文字数を に保存することを意味します。毎回正確に 3 文字を読み取る必要がある場合は、その値を確認できます。3 つ以下で問題ない場合は、そのまま使用できます。参考までに、幅指定子のドキュメントを次に示します。numCharsReadsscanf(str, "%3lf", &val)

最大フィールド幅を指定するオプションの 10 進整数。文字の読み取りは、この最大値に達するか、一致しない文字が見つかったときのいずれか早い方で停止します。ほとんどの変換では最初の空白文字が破棄され (例外は以下に示されています)、これらの破棄された文字は最大フィールド幅にはカウントされません。文字列入力の変換では、入力の終わりを示すために終端のヌル バイト ('\0') が格納されます。最大フィールド幅には、このターミネータは含まれません。

于 2015-07-14T21:58:20.260 に答える
1

いいえ、標準ライブラリにはそのような関数はありません。

しかし、自分で転がすのは楽しいです。

/*
 * 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;
}
于 2013-05-07T09:52:55.280 に答える