【问题标题】:Why is fgets() not reading the entire file?为什么 fgets() 没有读取整个文件?
【发布时间】:2020-06-09 16:20:36
【问题描述】:

我正在读取文件以将文本保存到数组中。文本最终要保存到的数组是plainText[]。但奇怪的是, fgets() 并没有读取整个文件。它在停止之前只读取文件的一半。

这是文件的完整内容:

bbbbbbbbb
bbbbbbbbb
bbbbbbbbb
bbbbbbbbb
bbbbbbbbb
bbbbbbbbb
bbbbbbbbb
bbbbbbbbb

有 8 行 b,每列 9 个,总共 72 个 b。但是,我得到的输出在打印时仅包含 36 个 b。

plainText[ ] 打印时的输出:

bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb

这是打开和读取文件的代码。

int main(int argc, char **argv) {
    //send an error code if the correct number of arguments have not been met to run the program
    if (argc < 3) {
        printf("Please enter the encryption file and the file to be encrypted.\n");
        return ERROR;
    }

    //open file to be encrypted (aka, plaintext)
    char *fileToEncrypt = argv[2];
    FILE *plainFile = fopen(fileToEncrypt, "r");
    //return an error code if the file to encrypt cannot be found
    if (plainFile == 0) {
        printf("The file you wish to encrypt cannot be found on this machine.\n");
        printf("Please ensure that you are in the correct directory and that there are no typos.\n");
        return ERROR;
    }

这是我使用 fgets() 读取文件内容并将其传输到 plainText[ ] 的地方。

//read contents of file to encrypt
char plainText[STRING_LENGTH + 1], temp2[STRING_LENGTH + 1];


//fill array with null terminators so we don't receive
//memory errors from strcat(plainText, temp2)
for (int i = 0; i < STRING_LENGTH; i++)
    plainText[i] = '\0';

//pointer to end of string in order to remove \n
char *bptr = plainText;

//read the file again if it is found there are multiple lines
while (fgets(temp2, STRING_LENGTH, plainFile)) {
    fgets(temp2, STRING_LENGTH, plainFile);
    strcat(plainText, temp2);
    bptr[strlen(bptr) - 1] = '\0'; //remove \n at end of string at a result of fgets()
}

//close file
fclose(plainFile);

循环告诉 fgets() 只要有内容就继续读取,但 fgets() 在文件中途停止输入内容。这是为什么呢?

【问题讨论】:

  • while (fgets(temp2, STRING_LENGTH, plainFile)) { fgets(temp2, STRING_LENGTH, plainFile); 你打电话给fgets 两次。所以第一个读取一行,第二个读取另一行。 STRING_LENGTH 是如何定义的?请发帖minimal reproducible example
  • bptr[strlen(bptr) - 1] = '\0'; 是 UB 如果文件以 null 字符开头。
  • Off by 1:由于缓冲区足够大,代码可以使用fgets(temp2, STRING_LENGTH + 1, plainFile)

标签: c file fgets


【解决方案1】:

在循环中:

while (fgets(temp2, STRING_LENGTH, plainFile)) {
    fgets(temp2, STRING_LENGTH, plainFile);
    strcat(plainText, temp2);
    bptr[strlen(bptr) - 1] = '\0'; //remove \n at end of string at a result of fgets()
}

当您调用fgets() 两次时,每隔一行将被丢弃。你看不到这一点,因为你所有的行都是平等的,如果你用文件中的不同行测试它,这将变得很明显。

要更正此问题,您可以尝试:

while (fgets(temp2, STRING_LENGTH, plainFile)) {
    strcat(plainText, temp2);
    bptr[strlen(bptr) - 1] = '\0'; //remove \n at end of string at a result of fgets()
}

【讨论】:

    【解决方案2】:

    fgets在条件中每次调用都会读入一行到缓冲区中

    while (fgets(temp2, STRING_LENGTH, plainFile)) {
    

    然后你直接再次调用它,让它读到第二行:

    fgets(temp2, STRING_LENGTH, plainFile);
    

    如果您删除第二行,您的代码应该可以按预期工作。 您的代码目前无法按预期工作,因为它只使用 strcat 复制每一行。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-08-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-07-21
      • 2019-08-20
      • 1970-01-01
      相关资源
      最近更新 更多