I have a file that has certain fields separated by tabs. There will always be 12 tabs in a line, certain tabs are consecutive which indicates an empty field. I wanna use fscanf
I wanna use fscanf to read consecutive tabs as empty fields and store them in a structure.
Ideally, code should read a line, as with fgets()
and then parse the string.
Yet staying with fscanf()
, this can be done in a loop.
The main idea is to use "%[^/t/n]"
to read one token. If the next character is a '\t'
, then the return value will not be 1. Test for that. A width limit is wise.
Then read the separator and look for tab, end-of-line or if end-of-file/error occurred.
#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
}
Sample driving code
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.");
}
}