首页 > 解决方案 > 在 c 中使用 fgets 函数的分段错误错误

问题描述

我正在用 C 编写一个小代码,用于将文本文件中的特定字符串复制到另一个文本文件中。绳子在中间某处。我用 C 编写了一个代码。编译时,我遇到了分段错误错误。

请帮忙。我的代码如下:

int main()
{
    FILE *fptr1, *fptr2;
    char c;
    char data[100];

    // Open one file for reading
    fptr1 = fopen(SPATH, "r");
    if (fptr1 == NULL)
    {
        printf("Cannot open file %s \n", SPATH);
        exit(0);
    }

    // Open another file for writing
    fptr2 = fopen(DPATH, "w");
    if (fptr2 == NULL)
    {
        printf("Cannot open file %s \n", DPATH);
        exit(0);
    }

    // Read contents from file
    while (!feof(fptr1))
    {
        fgets(data[20],29,fptr1);
        printf("\n %s",data[20]);
        fputs(data[29], fptr2);
    }   

    printf("\nContents copied to %s", "file2.txt");

    fclose(fptr1);
    fclose(fptr2);
    return 0;
}

标签: csegmentation-faultfgets

解决方案


而( !feof (file) )总是错的?, 因为在遇到之前feof(file)不测试。如果您通过以下方式控制循环:trueEOF

while ( !feof (file) ) {
    /* read statement  */
    /* write statement */
}

您的读取语句将读取文件中的最后一行(或字符),让下一次读取触发EOF,但是,当前读取成功且未设置EOF,您的写入完成正常。

接下来发生什么?

您测试feof (file)which is still false,因此!feof (file)测试true并再次开始处理循环中的语句。您的读取失败,因为读取指针位于之前EOF,您的读取无效,然后您通过向文件写入不确定的值来调用调用未定义行为的写入语句。一旦你触发Undefined Behavior,你的程序可以做任何事情,从出现到成功完成或 SEGFAULT 或介于两者之间的任何事情。

相反,只需使用fgets自身控制您的读取循环。这样,只有fgets成功后,您才会进入循环并将值写入文件,例如

#include <stdio.h>

#define MAXC  100           /* if you need a constant, #define one (or more) */
#define DPATH "file2.txt"

int main (int argc, char **argv) {

    FILE *fptr1 = NULL,     /* initialize all variables (good practice) */
         *fptr2 = NULL;
    char data[MAXC] = "";

    /* open/validate file for reading (default stdin) */
    fptr1 = argc > 1 ? fopen (argv[1], "r") : stdin;
    if (fptr1 == NULL) {
        fprintf (stderr, "error: file open failed '%s'.\n", argv[1]);
        return 1;
    }

    /* open/validate file for writing */
    fptr2 = fopen (DPATH, "w");
    if (fptr2 == NULL) {
        fprintf (stderr, "error: file open failed '%s'.\n", DPATH);
        return 1;
    }

    /* read contents from file */
    while (fgets (data, sizeof data, fptr1)) {  /* read 99-char blocks */
        printf ("%s", data);    /* (optional) output to stdout */
        fputs (data, fptr2);    /* write block to fptr2 */
    }

    printf ("\nContents copied to %s\n", DPATH);

    fclose(fptr1);
    if (fclose(fptr2) == EOF)   /* always validate close-after-write */
        perror ("fclose-fptr2");

    return 0;
}

注意:不要在代码中使用幻数或硬编码值,相反,如果您需要常量#define它们(或者对于数字常量,您也可以使用全局enum来定义它们)。

*示例输入文件**

$ cat dat/captnjack.txt
This is a tale
Of Captain Jack Sparrow
A Pirate So Brave
On the Seven Seas.

检查输出文件是否存在:

$ ls -al file2.txt
ls: cannot access 'file2.txt': No such file or directory

示例使用/输出

$ ./bin/fgets_copy_file <dat/captnjack.txt
This is a tale
Of Captain Jack Sparrow
A Pirate So Brave
On the Seven Seas.

Contents copied to file2.txt

检查file2.txt

$ cat file2.txt
This is a tale
Of Captain Jack Sparrow
A Pirate So Brave
On the Seven Seas.

如果您还有其他问题,请仔细查看并告诉我。


推荐阅读