【问题标题】:How to cut or truncate lines from a text file in C [duplicate]如何从C中的文本文件中剪切或截断行[重复]
【发布时间】:2015-03-01 18:17:02
【问题描述】:

我正在读取每行大于 63 个字符的文件,我希望将字符截断为 63。但是,它无法截断从文件中读取的行。

在这个程序中,我们假设文件有 10 行

目标:我想从每行读取 63 个字符。任何超过 63 个字符的行,读取 63 个字符并截断其余字符。如果有更简单的方法可以做到这一点,请告诉我。

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

int main(void)
{
    char a[10][63];
    char line[255];

    int count = 0;

    //Open file                
    FILE *fp;
    fp = fopen("lines.dat", "r"); 

    //Read each line from file to the "line array"
    while(fgets(line, 255,fp) != NULL)
    {
        line[63] = '\0';

        //copy the lines into "a array" char by char
        int x;
        for(x = 0; x < 64; ++x)
        {
            a[count][x] = line[x];
        }

        count++;
    }

    fclose(fp);

    //Print all lines that have been copied to the "a array"
    int i;
    for(i = 0; i < 10; i++)
    {
        printf("%s", a[i]);
    }


}

【问题讨论】:

标签: c arrays string char truncate


【解决方案1】:

正如 Weather Vane 提到的,您的 char 矩阵不够宽,无法容纳 63 个字符的行加上最后的 '\0'

您的代码还有其他问题:

  • 您读取带有 fgets(line, 255,fp) 的行,然后在 63 个字符后强制使用 '\0'。如果该行有超过 254 个字节怎么办?在下一次调用之前,该行的其余部分将在 stdin 中保持未读状态,并且您的矩阵中将有一个或多个额外的错误行块。

  • 你不处理行尾的换行符:如果一行被截断,它在矩阵中没有'\n',而它处理较短的行。

  • 你应该如何处理短于 63 个字符的行?别理他们?跳过他们?我知道你假设它们都至少有 63 个字符,但你的程序应该优雅且可预测地处理不符合要求的输入。

这是一个修改后的程序:

#include <stdio.h>

#define NROWS  10
#define NCOLS  63
int main(void)
{
    char a[NROWS][NCOLS+1];
    int row, col, c;

    //Open file                
    FILE *fp;
    fp = fopen("lines.dat", "r");
    if (fp == NULL)
        return 1;

    for (row = 0; row < NROWS;) {
        for (col = 0; (c = getc(fp)) != EOF;) {
            if (c == '\n')
                break;
            if (col < NCOLS)
                a[row][col++] = c;
        }
        //terminate the string.
        a[row][col] = '\0';
        if (col == 0 && c == EOF)
            break;
        if (col < NCOLS) {
            // handle short lines: here just accept them.
        }
        row++;
        if (c == EOF)
            break;
    }

    fclose(fp);

    //Print all lines that have been copied to the "a array"
    for (int i = 0; i < row; i++) {
        printf("%s\n", a[i]);
    }
}

你坚持使用fgets,这里有一个替代方案:

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

#define NROWS  10
#define NCOLS  63
int main(void)
{
    char a[NROWS][NCOLS+1];
    char *p;
    int row, c;

    //Open file                
    FILE *fp;
    fp = fopen("lines.dat", "r");
    if (fp == NULL)
        return 1;

    for (row = 0; row < NROWS;) {
        if (!fgets(a[row], NCOLS+1, fp))
            break; // stop at EOF
        if ((p = strchr(a[row], '\n')) != NULL)
            *p = '\0';  // accept short lines
        row++;
        // skip extra characters upto the end of line
        while ((c = getc(fp)) != EOF && c != '\n')
            continue;
        if (c == EOF)
            break;
    }

    fclose(fp);

    //Print all lines that have been copied to the "a array"
    for (int i = 0; i < row; i++) {
        printf("%s\n", a[i]);
    }
}

【讨论】:

  • 这真的很好。虽然我不打算跳过短线。所以如果我想包含较短的行,我应该怎么做?
  • 如果你想包含短线,在第一个版本中,只需删除测试并在所有情况下增加row。对于第二个版本,您需要用'\0' 覆盖'\n',而不是用continue 跳过该行。我编辑了回复。
【解决方案2】:

您的数组不够大,无法容纳 63 个字符字符串终止符。

char a[10][63];

应该是

char a[10][64];

然后您可以通过63正确索引字符串,因为索引范围是0..63

将字符串复制到数组中的更简单方法是使用库函数,您需要#include &lt;string.h&gt;

while(fgets(line, 255, fp) != NULL)
{
    line[63] = '\0';
    strcpy (a[count], line);
    count++;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-01
    • 2010-10-09
    • 2022-01-01
    • 2010-10-26
    • 2011-09-26
    相关资源
    最近更新 更多