簡體   English   中英

使用sscanf從字符串中讀取多個單詞

[英]Read more than one word from string with sscanf

我正在嘗試從文件中讀取格式化的內容。 為此,我使用fgets()sscanf()逐行讀取。

該文件的內容應該是一個表。 一行將類似於以下示例:

456    2    39    chained_words    62.5    // comment with more than one word

要閱讀它,我使用:

fgets(temp,MAXLINELENGTH,file);
sscanf(temp,"%d %d %d %s %f // %s",&num1,&num2,&num3,word,&num4,comment);

它可以與前五個元素以及//之后的第一個單詞配合使用,但是問題是我需要將整個注釋存儲在comment char *變量中。 我嘗試了其他帖子中提出的多種解決方案,例如指定排除某些字符的格式,但沒有任何效果。

我很樂意解決問題的任何提示!

在您的注釋之后,如果要在現有comment之后添加另一個數字,則會使事情復雜化。 原因是comment包含多個單詞,您沒有要搜索的離散結尾。

但是,C很少會讓您失望。 每當您需要從行或緩沖區中解析數據時,您都會查看數據格式並詢問“我將使用什么作為我需要的開始或結束的參考?” 在這里,沒有任何注釋,我們將需要使用緩沖區的末尾作為參考並向后工作。

這樣做時,我們假設該值是換行符之前的最后一行(沒有制表符或空格)。 我們可以向后循環,直到找到要驗證的最后一個非空白字符為止,但出於此目的,我們進行假設。

出於此問題的目的,我們將解析行分為兩部分。 我們可以可靠的方式通過原始的sscanf調用讀取所有內容,直至評論為止。 因此,我們將在一行的第一部分(直到並包括浮點數)的第一部分中考慮所有內容,並在注釋字符//部分之后考慮所有內容。您將照常讀取/解析第一部分:

        sscanf (line, "%d %d %d %s %f", &d1, &d2, &d3, word, &f1);

搜索在一條線上一個特定的字符,我們有一個手動字符逐字符比較,(我們總是有),我們有strchrstrrchr函數string.h ,將搜索的文本行的第( strchr )或給定字符的最后一次( strrchr )出現。 這兩個函數都返回一個指向字符串中該字符指針

從我們的行尾開始,如果我們找到/ ,則現在有一個指針(字符串中的地址)指向注釋開頭之前的最后一個'/' 現在,我們使用指針將行的其余部分讀入comment (值和全部)。

        p = strrchr (line, '/');            /* find last '/' in line    */
        sscanf (p, "/ %[^\n]%*c", comment); /* read comment and value   */

現在,我們僅在comment中工作(而不是line )。 我們知道,如果我們從comment的末尾開始尋找空格' ' ,我們將能夠讀取我們的最后一個值。 讀取完最后一個值后,由於我們的指針指向該值之前的地址,因此我們知道可以在該指針處以null-terminate comment以完成解析。

        p = strrchr (comment, ' ');         /* find last space in file  */
        sscanf (p, " %d", &d4);             /* read last value into d4  */
        *p = 0;                             /* null-terminate comment   */

注意:如果需要,您可以檢查/刪除comment任何尾隨空格,但是出於我們的目的,省略了該空格)

放在一起,您將得到如下所示的內容:

快速范例

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

#define MAXS 128

int main (int argc, char **argv) {

    if (argc < 2 ) {                /* check for at least 1 argument    */
        fprintf (stderr, "error: insufficient input, usage: %s filename\n", 
                argv[0]);
        return 1;
    }

    char line[MAXS] = {0};
    char word[MAXS] = {0};
    char comment[MAXS] = {0};
    char *p = NULL;
    size_t idx = 0;
    int d1, d2, d3, d4;
    float f1 = 0.0;
    FILE *fp = NULL;

    d1 = d2 = d3 = d4 = 0;

    if (!(fp = fopen (argv[1], "r"))) {  /* open/validate file   */
        fprintf (stderr, "error: file open failed '%s'.", argv[1]);
        return 1;
    }

    while (fgets (line, MAXS, fp) != NULL)  /* read each line in file */
    {
        /* read buffer through first float */
        sscanf (line, "%d %d %d %s %f", &d1, &d2, &d3, word, &f1);

        p = strrchr (line, '/');            /* find last '/' in line    */
        sscanf (p, "/ %[^\n]%*c", comment); /* read comment and value   */
        p = strrchr (comment, ' ');         /* find last space in file  */
        sscanf (p, " %d", &d4);             /* read last value into d4  */
        *p = 0;                             /* null-terminate comment   */

        printf ("\nline : %zu\n\n %s\n", idx, line);
        printf ("   d1 : %d\n   d2 : %d\n   d3 : %d\n   d4 : %d\n   f1 : %.2f\n",
                d1, d2, d3, d4, f1);
        printf ("   chained : %s\n   comment : %s\n", word, comment);

        idx++;
    }

    fclose (fp);

    return 0;
}

輸入項

$ cat dat/strwcmt.txt
456    2    39    chained_words    62.5    // comment with more than one word    227
457    2    42    more_chained_w   64.5    // another comment    228
458 3 45 s_n_a_f_u 66.5 // this is still another comment 229

輸出量

$ ./bin/str_rd_mixed dat/strwcmt.txt

$ ./bin/str_rd_mixed dat/strwcmt.txt

line : 0

 456    2    39    chained_words    62.5    // comment with more than one word    227

   d1 : 456
   d2 : 2
   d3 : 39
   d4 : 227
   f1 : 62.50
   chained : chained_words
   comment : comment with more than one word

line : 1

 457    2    42    more_chained_w   64.5    // another comment    228

   d1 : 457
   d2 : 2
   d3 : 42
   d4 : 228
   f1 : 64.50
   chained : more_chained_w
   comment : another comment

line : 2

 458 3 45 s_n_a_f_u 66.5 // this is still another comment 229

   d1 : 458
   d2 : 3
   d3 : 45
   d4 : 229
   f1 : 66.50
   chained : s_n_a_f_u
   comment : this is still another comment

注意:處理此問題的不同方法沒有限制。 這只是一種方法。 另一個方法是將整行標記為單獨的單詞,檢查每個單詞是否以數字開頭(並包含浮點“。”),然后簡單地轉換所有數字並根據需要連接所有非數字單詞。 由你決定。 工具箱越大,使用該工具箱的方式就越多。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM