[英]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);
搜索在一條線上一個特定的字符,我們有一個手動字符逐字符比較,(我們總是有),我們有strchr
和strrchr
函數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.