在C中使用fgets函数进行细分错误

时间:2018-06-22 02:00:20

标签: c segmentation-fault 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;
}

3 个答案:

答案 0 :(得分:2)

while ( !feof (file) ) is always wrong?,因为feof(file)在遇到true之前不会测试EOF。如果您使用以下方法控制循环:

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

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

接下来会发生什么?

您测试仍然feof (file)的{​​{1}},因此false测试!feof (file),然后再次开始处理循环中的语句。您的读取失败,因为读取指针正好位于true之前,因此您的读取无效,然后您通过写一个 Undefined Behavior 来调用您的write语句对文件的价值不确定。触发未定义行为的程序,您的程序可以执行任何操作,从显示成功完成到执行SEGFAULT或介于两者之间。

相反,只需使用EOF本身来控制您的读取循环。这样,只有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

仔细检查一下,如果还有其他问题,请告诉我。

答案 1 :(得分:1)

就像其他人回答所说的那样,fgets的定义是:

char * fgets ( char * str, int num, FILE * stream );

data的类型为char*,因此data[whatever]的类型为char。不好您应该将其更改为data。您还可以在其他几个地方进行此操作。也将它们更改为data

要弄清楚问题出在fget中,您可以使用GDB之类的调试器:

$ gcc foo.c -g -o myprogram // Compile your program. '-g' means to use debug, and '-o myprogram' is the name of the program you want to make.

// LOTS of warnings that you should have read, which tell you you're probably using 'data' wrong

$ gdb myprogram
(gdb) break main
Breakpoint 1 at 0x40074e: file foo.c, line 7.
(gdb) run
Starting program: /home/anthonyd973/Desktop/myprogram

Breakpoint 1, main () at foo.c:7
7       {
(gdb) next
13      fptr1 = fopen(SPATH, "r");
(gdb) next
14      if (fptr1 == NULL)
(gdb) next
23      fptr2 = fopen(DPATH, "w");
(gdb) next
24      if (fptr2 == NULL)
(gdb) next
33      while (!feof(fptr1))
(gdb) next
35      fgets(data[20],29,fptr1);
(gdb) next

Program received signal SIGSEGV, Segmentation fault. // So the problem is at line 35, during 'fgets'.
(gdb) quit
A debugging session is active.

        Inferior 1 [process 17669] will be killed.

Quit anyway? (y or n) y

$

答案 2 :(得分:1)

如下修改您的while循环:

while (!feof(fptr1))
{

    fgets(data, 99, fptr1);

    fputs(data, fptr2);

}

请阅读有关fgets(),fputs()的文档。只需输入man fgetsman fputs