在具有固定宽度列的文本文件上使用fscanf

时间:2013-12-08 07:34:46

标签: c file scanf

如何使用fscanf()来解析这段数据?字符串和double之间有很多空格。

039 Mt Albert Rd, Holland landing                9.50
043 Queensville Side Road, Queensville           10.00

while(3==fscanf(filename, "%d?????%lf\n", &int[size], &string[size], &double[size])) {
    size++;
}

3 个答案:

答案 0 :(得分:2)

如果double的开头始终在同一列(在您的示例中为50),则从那里扫描字符串:

char buf[120];
while (fgets(buf, sizeof buf, fp)) {
    if (isdigit(buf[0])
    &&  sscanf(buf, "%d", &int[size])==1
    &&  sscanf(buf+50, "%f", &double[size])==1)
        size++;
}

或者如果你真的对字符串感兴趣

while (sscanf(fp, "%3d%47c%f", &int[size], &string[size], &double[size])==3) {
    // remove trailing blanks from the string
    int pos=strlen(string[size])-1;
    while (pos>=0 && string[size][pos]==' ')
        pos--;
    string[size][++pos]='\0';
}

答案 1 :(得分:1)

由于您只需要三个值,整数,字符串和double,以及列似乎是对齐的,因此您可以使用%c转换说明符为字符串指定合适的长度。

while (fscanf("%d %45c %lf", &intarr[size], &string[size], &dblarr[size]) == 3)
    size++;

请注意,在C(或C ++)中,您的三个数组名称中有两个是不可能的;类型intdouble是保留字,不能用作变量名。字符串的确切长度由文件格式决定;我把它算作45,但选择你的价值以适应(评论提到34个字符,恰好是“Queensville Side Road,Queensville”的长度)。扫描的名称一般包括尾随空白;如果你愿意,你可以安排删除它们。

答案 2 :(得分:0)

您没有告诉我们中间地址字段的任何信息。我只是假设它不包含数字或-+并且我不假设第二个数字从某个固定列开始(例如因为输入可能有制表符,所以在视觉上第二个数字可以对齐,但它们的相对偏移 - 线的开始 - 可能不是固定的。)

我会逐行读取文件,并处理每一行:

 char* line=NULL;
 size_t linesize= 0;
 while (!feof (fil)) {
    ssize_t linelen = getline(&line, &linesize);
    if (linelen<0) break;
    // read the first number
    char* pc = NULL;
    long firstnum = strtol (line, &pc, 0);
    if (!pc || pc == line) break;
    // skip to start of second number
    while (*pc && !isdigit(*pc) && *pc != '-' && *pc != '+') pc++;
    char* startsec = pc;
    double secondnum = strtod(startsec, &pc);
    if (!pc || pc == startsec) break;
    do_something_with_numbers (firstnum, secondnum); 
 }
 free (line);
 fclose (fil);

如果您可以告诉我们有关地址字段的更多信息,我们可以提供更多帮助!