且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

仅读取 C 中文本文件中的固定列宽

更新时间:2023-02-20 10:38:42

如果您的行始终填充为 40 个字符加上换行符,您可以使用 %20c 来读取每个 20 个字符的字段.这将节省空白和所有;如果你愿意,你可以在之后把它们脱掉.请注意,这不会为字符串终止;你必须这样做.

If your lines were consistently padded to 40 characters plus newline, you could use %20c to read each 20-character field. That would save the blanks and all; you could strip those off afterwards if you wish. Note that this does not null terminate the strings; you have to do that.

char first[21];
char last[21];

while (scanf(" %20c %20c", first, last) == 2)
{
    first[20] = last[20] = '\0';
    printf("[%s] [%s]\n", first, last);
}

使用格式正确的数据,这会产生:

With properly formatted data, this produces:

[Carlos              ] [Rivera Bernal       ]
[Thomas              ] [James Hanner        ]
[James               ] [Patrick Sullivan    ]
[Brayan              ] [Williams            ]
[Khaterine           ] [Smith               ]
[Ben                 ] [Thompson            ]

但是,如果第二个字段没有填充到(至少)20 个字符,%20c 将消耗换行符和下一行的开头:

However, if the second field is not padded to (at least) 20 characters, the %20c will consume the newline and start of the next line:

[Carlos              ] [Rivera Bernal 
Thoma]
[s              James] [Hanner
James        ]
[Patrick Sullivan
Bra] [yan              Wil]
[liams
Khaterine     ] [Smith
Ben           ]

适用于给定数据的下一个选择是:

Your next choice, which works on the given data, is:

while (scanf(" %20[^ ] %20[^\n]", first, last) == 2)
    printf("[%s] [%s]\n", first, last);

它在第一个字段中最多读取 20 个字符(或第一个空格),然后在第二个字段中最多读取 20 个字符(或换行符).在我的数据副本上,产生了:

It reads up to 20 characters (or the first blank) in the first field, then up to 20 characters (or the newline) in the second field. On my copy of your data, that produced:

[Carlos] [Rivera Bernal ]
[Thomas] [James Hanner]
[James] [Patrick Sullivan]
[Brayan] [Williams]
[Khaterine] [Smith]
[Ben] [Thompson]

卡洛斯的名字后面必须有一个空格,而不是其他任何人的名字.您可以结合使用这些技术来读取包含空格的名字":

There must be a trailing blank after Carlos's name and not anyone else's. You could combine the techniques to read a 'first name' that has blanks in it:

while (scanf(" %20c %20[^\n]", first, last) == 2)
{
    first[20] = last[20] = '\0';
    printf("[%s] [%s]\n", first, last);
}

产生:

[Carlos              ] [Rivera Bernal ]
[Thomas              ] [James Hanner]
[James               ] [Patrick Sullivan]
[Brayan              ] [Williams]
[Khaterine           ] [Smith]
[Ben                 ] [Thompson]

您可以编写一个函数来将尾随空白设为空.例如:

You could write a function to null trailing blanks. For example:

#include <assert.h>
#include <stdio.h>

static void null_trailing_blanks(char *buffer, size_t buflen)
{
    assert(buflen > 0);
    buffer[--buflen] = '\0';
    while (buflen > 0 && buffer[buflen-1] == ' ')
        buffer[--buflen] = '\0';
}

int main(void)
{
    char first[21];
    char last[21];

    while (scanf(" %20c %20c", first, last) == 2)
    {
        null_trailing_blanks(first, sizeof(first));
        null_trailing_blanks(last, sizeof(last));
        printf("[%s] [%s]\n", first, last);
    }

    return 0;
}

在完全填充的数据集上,产生:

On the fully-padded data set, that yields:

[Carlos] [Rivera Bernal]
[Thomas] [James Hanner]
[James] [Patrick Sullivan]
[Brayan] [Williams]
[Khaterine] [Smith]
[Ben] [Thompson]