2016-08-25 33 views
-2

假设有一个字符串我想用C解析。 解析我想使用函数sscanf()从C中的字符串解析浮点值时出现问题

现在,在一个点上,在字符串中有一个浮点型数字,它可能会扩展到一个很大的值(十进制之前/之后),有时甚至更少。基本上这意味着数字的宽度是可变的。

例如,

的数目可以是15.5686,15.5686778887或156.867788

让我们这样的字符串

Str1 = "Hello15.5686World" 
Str1 = "Hello15.5686778887World" 

在运行期间任何上述串的可能必须被解析。

然而,数字的起点是固定的,但我们不知道它在哪里结束。那么,什么是确定相同的方法,以便“世界”(数字后的子字符串)可以被正确解析或读取。

+1

您必须缩小可能的输入范围。 1)数字可以使用什么浮点格式?它只是小数,还是十六进制? 2)字符串的非数字部分是否可以包含数字? – EOF

+0

如果我们可以知道数字的最大宽度,那么我们可以修复它的开始/结束点。但是,无论数字有多大或多少,每次需要解析字符串时,它总是会使用该空间量。 – Anand

+1

@EOF:是的,非数字部分可能包含数字。 – Anand

回答

1

这使用strpbrk查找字符串中的小数点。
no指针将迭代到字符串的开始位置以查找小数点前的数字。如果小数点前的所有字符均为数字,则前四个字符被假定为前导字符串。
s指针迭代到字符串末尾以查找小数点后面的数字。如果小数点后面的所有字符都是数字,则最后六个字符被认为是尾随字符串。

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <ctype.h> 

int main(void) 
{ 
    //char str[] = { "abc123def98.76543zyc098"}; 
    char str[] = { "123498.76543123456"}; 
    char *leading = NULL; 
    char *trailing = NULL; 
    char *no = NULL; 
    char *s = NULL; 
    char *decimal = NULL; 
    double value; 

    if ((decimal = strpbrk (str, ".")) != NULL) {//find the decimal 
     s = decimal;//for trailing string 
     no = decimal;//for start of numeric value 
     while (no > str) {//stop at start of str 
      no--;//iterate toward start 
      if (!isdigit (*no)) { 
       no++; 
       break; 
      } 
     } 
     while (*s) {//stop at '\0' 
      s++;//iterate toward end of str 
      if (!isdigit (*s)) { 
       break; 
      } 
     } 
     if (no == str) {//all digits 
      no = str + 4;//first four characters will belong to leading 
      if (no >= decimal) { 
       printf ("problem with leading string\n"); 
       exit (1); 
      } 
     } 
     if (*s == '\0') {//all digits 
      s = s - 6;//last six characters will belong to trailing 
      if (s <= decimal) { 
       printf ("problem with trailing string\n"); 
       exit (1); 
      } 
     } 

     if ((trailing = malloc (strlen (s) + 1)) == NULL) { 
      printf ("malloc problem\n"); 
      exit (1); 
     } 

     if ((leading = malloc ((no - str) + 1)) == NULL) { 
      free (trailing); 
      printf ("malloc problem\n"); 
      exit (1); 
     } 

     memcpy (trailing, s, strlen (s)); 
     trailing[strlen (s)] = '\0'; 

     memcpy (leading, str, no - str); 
     leading[no - str] = '\0'; 

     *s = '\0';//for the next sscanf terminate no at s 

     if ((sscanf (no, "%lf", &value)) != 1) { 
      free (leading); 
      free (trailing); 
      printf ("sscanf problem\n"); 
      exit (1); 
     } 


     printf ("leading %s\n", leading); 
     printf ("value %f\n", value); 
     printf ("trailing %s\n", trailing); 


    } 
    else { 
     printf ("no decimal found\n"); 
    } 

    free (leading); 
    free (trailing); 

    return 0; 
} 
+0

直到现在,根据我的要求工作。我会继续尝试不同的输入。非常感谢。 – Anand

2

您可以使用strtod系列函数来解析字符串。你可以传递一个指针的指针字符strtod,解析数后,该指针则指向字符串的其余部分:

const char *Str1 = "Hello15.5686World", *endptr; 
double num = strtod(Str1 + strlen("Hello"), &endptr); 

printf("number: %f, rest of string: %s\n", num, endptr); 
+0

考虑到OP说非数字部分可以包含数字,序列'“H0xello15.5686World”'可能不会返回OP期望的内容。此外,'strtod()'在这种情况下将失败,因为''H''既不是空格也不是十六进制/十进制字符。 – EOF

+1

@EOF OP说:“然而,数字的起点是固定的,但我们不知道它在哪里结束。”所以这只是将数字的开头传递给'strtol'的问题。 – fuz

+0

@BLUEPIXY谢谢。 – fuz