2016-08-25 82 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