从文件中扫描带有空格的字符串,同时在同一行中扫描其前后的数字

Scanning a string with spaces from a file while also scanning numbers before and after it in the same line

我实际上是新手,所以我在学习时遇到了一个错误,我实际上是在尝试 fscanf 从文件中然后将其显示在屏幕上一切正常,直到我添加书名 space 在文件中。它显示book.id很好,但它只显示书的名字,后面的整数变为0。

示例输出:

我的函数:

void display_unsorted(FILE *fptr){
    int x;
    int lines_num=how_many_lines_in_file(fptr);

    fptr=fopen("books.dat","r");
    if(fptr==NULL){
    printf("this file is not open");}

    for(i=0;i<lines_num;i++){
    fscanf(fptr,"%d\t%s\t%d\n",&books[i].id,books[i].name,&books[i].quantity);
    }
    for(x=0;x<lines_num;x++){
    printf("%d\t%s\t%d\n",books[x].id,books[x].name,books[x].quantity);
    }

    fclose(fptr);    
}

fscanf 会在发现空白时停止阅读 space,您可以使用以下方法覆盖此行为:

fscanf(fptr,"%d %99[^0-9] %d\n", &books[i].id, books[i].name, &books[i].quantity);
                ^^^^^^^^^

正在翻译,将读取最多99个字符的字符串,找到任何数字即停止读取,即从0到9的字符。

我把\t去掉了,不用了,就算文件里有,一个空白的space就够了。

请注意,这是针对最大大小为 100 个字符的 books[i].name 容器,即 99 个字符加上空终止符,这必须适应您的代码中未显示的容器大小.

另请注意,如果字符串中包含数字,这将无法按预期工作。

假设输入文件中的字段分隔符是<tab>,OP不清楚,除了调用fscanf()中的格式字符串,然后

fscanf(fptr,"%d\t%s\t%d\n",&books[i].id,books[i].name,&books[i].quantity);

可以更改为:

fscanf( fptr,"%d %[^\t] %d",
             &books[i].id,
              books[i].name,
             &books[i].quantity );

其中 'set' 格式说明符:%[^\t] 将继续输入字符,直到遇到 <tab><tab> 将留在输入流中,但是,下面的 space 将消耗 white space%d 也是如此),但是 space更具可读性。

如前所述,strchr 可用于查找第一个 space,strrchr 可用于查找最后一个 space。这些指针之间的区别在于名称中的字符。
sscanf 可用于解析前导和尾随整数。
strncpy 可用于从行内复制名称。
该程序只处理一行。将其包装在 while ( fgets ( line, sizeof line, fptr)) 中将处理文件中的每一行。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main ( void) {
    char line[200] = "123 firstname lastname 456\n";
    char name[120] = "";
    char *first = line;
    char *last = line;
    int leading = 0;
    int trailing = 0;
    int valid = 1;
    int span = 0;
    int result = 0;

    if ( ( first = strchr ( line, ' '))) {
        if ( ( last = strrchr ( line, ' ')) && last > first) {
            result = sscanf ( line, "%d", &leading);
            result += sscanf ( last, "%d", &trailing);
            if ( 2 != result) {
                fprintf ( stderr, "two numbers needed\n");
                valid = 0;
            }
            while ( ' ' == *first) {
                ++first;//skip leading space
            }
            while ( ' ' == *last) {
                --last;//skip trailing space
            }
            span = 1 + last - first;//characters in name
            if ( span < sizeof name) {
                strncpy ( name, first, span);
                name[span] = 0;
            }
            else {
                fprintf ( stderr, "name is too long\n");
                valid = 0;
            }
        }
        else {
            fprintf ( stderr, "two spaces needed\n");
            valid = 0;
        }
    }
    else {
        fprintf ( stderr, "spaces needed\n");
        valid = 0;
    }

    if ( valid) {
        printf ( "name %s\n", name);
        printf ( "leading number %d\n", leading);
        printf ( "trailing number %d\n", trailing);
    }

    return 0;
}