[英]read consecutive tabs as empty field fscanf
我有一個文件,其中某些字段由制表符分隔。 一行中總會有12個制表符,某些制表符是連續的,表示空字段。 我想使用fscanf將連續的標簽讀取為空字段並將它們存儲在結構中。 但似乎有一個問題。 這是我的檔案:
usrid User Id 0 15 string d k y y 0 0
當我嘗試使用fscanf讀取時,選項卡后面的選項卡不會被識別為空字段,並且數據存儲在錯誤的結構字段中。 處理問題的最佳方法是什么?
fscanf
是一個非首發。 讀取空字段的唯一方法是使用"%c"
來讀取分隔符(這需要您事先知道哪些字段是空的 - 不是很有用)否則,根據所使用的格式說明符 , fscanf
會消耗掉tabs
作為前導空格或遇到匹配的失敗或輸入失敗 。
繼續注釋,為了基於可能分隔空字段的分隔符進行標記化,您將需要使用strsep
因為strtok
將連續分隔符視為一個。
雖然你的字符串有些不清楚tabs
的位置,但是使用strsep
進行標記的簡短示例如下所示。 請注意, strsep
將指針指針作為其第一個參數,例如
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main (void) {
int n = 0;
const char *delim = "\t\n";
char *s = strdup ("usrid\tUser Id 0\t15\tstring\td\tk\ty\ty\t\t\t0\t0"),
*toks = s, /* tokenize with separate pointer to preserve s */
*p;
while ((p = strsep (&toks, delim)))
printf ("token[%2d]: '%s'\n", n++ + 1, p);
free (s);
}
( 注意:因為strsep
會修改字符串指針所持有的地址,所以你需要保留一個指向s
開頭的指針,以便在不再需要它時可以釋放它 - 感謝JL)
示例使用/輸出
$ ./bin/strtok_tab
token[ 1]: 'usrid'
token[ 2]: 'User Id 0'
token[ 3]: '15'
token[ 4]: 'string'
token[ 5]: 'd'
token[ 6]: 'k'
token[ 7]: 'y'
token[ 8]: 'y'
token[ 9]: ''
token[10]: ''
token[11]: '0'
token[12]: '0'
仔細看看,如果您有其他問題,請告訴我。
我想使用fscanf將連續的標簽讀取為空字段並將它們存儲在結構中。
理想情況下,代碼應該讀取一行 ,就像fgets()
,然后解析字符串 。
然而繼續使用fscanf()
,這可以在一個循環中完成。
主要思想是使用"%[^/t/n]"
來讀取一個標記。 如果下一個字符是'\\t'
,那么返回值將不是1.測試它。 寬度限制是明智的。
然后讀取分隔符並查找選項卡,行尾或發生文件結束/錯誤。
#define TABS_PER_LINE 12
#define TOKENS_PER_LINE (TABS_PER_LINE + 1)
#define TOKEN_SIZE 100
#define TOKEN_FMT_N "99"
int fread_tab_delimited_line(FILE *istream, int n, char token[n][TOKEN_SIZE]) {
for (int i = 0; i < n; i++) {
int token_count = fscanf(istream, "%" TOKEN_FMT_N "[^\t\n]", token[i]);
if (token_count != 1) {
token[i][0] = '\0'; // Empty token
}
char separator;
int term_count = fscanf(istream, "%c", &separator); // fgetc() makes more sense here
// if end-of-file or end-of-line
if (term_count != 1 || separator == '\n') {
if (i == 0 && token_count != 1 && term_count != 1) {
return 0;
}
return i + 1;
}
if (separator != '\t') {
return -1; // Token too long
}
}
return -1; // Token too many tokens found
}
樣品驅動代碼
void test_tab_delimited_line(FILE *istream) {
char token[TOKENS_PER_LINE][TOKEN_SIZE];
long long line_count = 0;
int token_count;
while ((token_count = fread_tab_delimited_line(istream, TOKENS_PER_LINE, token)) > 0) {
printf("Line %lld\n", ++line_count);
for (int i = 0; i < token_count; i++) {
printf("%d: <%s>\n", i, token[i]);
}
} while (token_count > 0);
if (token_count < 0) {
puts("Trouble reading any tokens.");
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.