当有这样的文件时如何使用fgets和sscanf ?
No Nama Masakan Berat (Gram) Kalori
1 Asinan 250 208
2 Toge Goreng 250 243
3 Gado - Gado 150 295
4 Ketoprak 250 153
5 Pempek 200 384
6 Rawon 160 331
7 Soto Ayam 100 101
8 Soto Padang 100 127
9 Tongseng 120 331
10 Hamburger 125 257
11 Kerupuk Palembang 50 168
12 Kerupuk Udang 20 72
13 Mie Bakso 200 302
14 Nasi Tim Ayam 420 588
15 Pizza 125 163
16 Sate Kambing 180 729
17 Sayur Krecek 175 249
18 Siomay 100 361
19 Soto Betawi 150 135
20 Soto Makasar 150 525
21 Soto Sulung 150 86
这个文件有22行。那么如何扫描每种格式呢?使用fgets或fscanf?我认为解决方案可能是这样的:
while(!feof(fp))
{
fgets(buffer,100,fp);
sscanf(buffer,"%d",&struct[i].number);
sscanf(buffer,"%[^n]",struct[i].string);
sscanf(buffer,"%d",&struct[i].gram);
sscanf(buffer,"%d",&struct[i].calorie);
}
我做的是正确的吗?如果不是,请告诉我,这样我就不会对如何解决这个问题感到好奇。有时我总是遇到类似的问题,想知道如何解决它。谢谢你。
因为name字段可以包含空格,所以解析比较复杂。
使用指针保存行中的位置。然后解析或复制这些指针。
这只是几种解析策略之一。
#include <stdio.h>
#include <string.h>
int main ( void) {
char buffer[100] = "";
char string[100] = "";
char *filename = "file.txt";
int number = 0;
int gram = 0;
int calorie = 0;
FILE *pf = NULL;
if ( NULL != ( pf = fopen ( filename, "r"))) {
fgets(buffer,100,pf); // get header line
while(fgets(buffer,100,pf)) // get lines until end of file
{
char *name = buffer;
int span = 0;
if ( 1 != sscanf(buffer,"%d %n",&number, &span)) {
continue;
}
name += span; // name now points to first character of name field
char *endfield = NULL;
if ( NULL != ( endfield = strstr ( name, " "))) {; // endfield points to three spaces after name field
span = endfield - name;
if ( span && span < sizeof string) {
strncpy(string,name,span); // copy span characters
string[span] = 0; // zero terminate
printf ( "%-20s", string);
}
if ( 2 == sscanf(endfield,"%d%d",&gram,&calorie)) {
printf ( " gram:%3d calorie:%3d", gram, calorie);
}
printf ( "n");
}
}
fclose ( pf);
}
else {
perror ( filename);
}
return 0;
}
另一个策略是使用strtok
。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main ( void) {
char buffer[100] = "";
char string[100] = "";
char **token = NULL; // pointer to pointer to store tokens
char *filename = "file.txt";
char *whitespace = " trn";
int limit = 0;
int number = 0;
int gram = 0;
int calorie = 0;
FILE *pf = NULL;
if ( NULL != ( pf = fopen ( filename, "r"))) {
fgets ( buffer, 100, pf); // get header line
while ( fgets ( buffer, 100, pf)) {
char *line = buffer;
char *item = NULL;
int count = 0;
while ( ( item = strtok ( line, whitespace))) {
if ( count + 1 > limit) {
char **temp = realloc ( token, sizeof *token * ( count + 1));
if ( NULL == temp) {
fprintf ( stderr, "realloc problemn");
fclose ( pf);
free ( token);
exit (1);
}
token = temp;
limit = count + 1;
}
token[count] = item;
++count;
line = NULL;
}
if ( count < 4) { // too few tokens
continue;
}
number = 0;
gram = 0;
calorie = 0;
if ( 1 != sscanf ( token[0], "%d", &number)) { // the first token
continue;
}
if ( 1 != sscanf ( token[count - 2], "%d", &gram)) { // the next to last token
continue;
}
if ( 1 != sscanf ( token[count - 1], "%d", &calorie)) { // the last token
continue;
}
string[0] = 0;
for ( int each = 1; each < count - 2; ++each) {
strcat ( string, token[each]);
if ( each < count - 3) {
strcat ( string, " ");
}
}
printf ( "%2d %-20sgram:%3d calorie:%3dn", number, string, gram, calorie);
}
fclose ( pf);
free ( token);
}
else {
perror ( filename);
}
return 0;
}