首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用c++中的fgets函数分割故障错误

使用c++中的fgets函数分割故障错误
EN

Stack Overflow用户
提问于 2018-06-22 10:00:20
回答 3查看 412关注 0票数 1

我正在用C语言编写一小段代码,用于将特定字符串从一个文本文件复制到另一个文本文件中。这根线在中间的某处。我用C写了一段代码,当我编译的时候,我得到了一个分段错误。

请帮帮忙。我的代码如下:

代码语言:javascript
复制
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;
}
EN

回答 3

Stack Overflow用户

发布于 2018-06-22 12:37:51

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

代码语言:javascript
复制
while ( !feof (file) ) {
    /* read statement  */
    /* write statement */
}

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

接下来会发生什么?

您测试feof (file),它仍然是false,所以!feof (file)测试true,您再次开始处理循环中的语句。你的读失败了,因为读指针就在EOF之前,你有一个无效的读,然后你调用你的写语句,通过向你的文件写入一个不确定的值来调用未定义的行为。一旦你触发了未定义的行为,你的程序可以做任何事情,从看起来成功完成,或者SEGFAULT,或者介于两者之间的任何事情。

相反,只需使用fgets本身控制读取循环即可。这样,只有当fgets成功时,您才会输入循环并将值写入到文件中,例如

代码语言:javascript
复制
#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;
}

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

**输入文件示例**

代码语言:javascript
复制
$ cat dat/captnjack.txt
This is a tale
Of Captain Jack Sparrow
A Pirate So Brave
On the Seven Seas.

检查输出文件是否存在:

代码语言:javascript
复制
$ ls -al file2.txt
ls: cannot access 'file2.txt': No such file or directory

示例使用/输出

代码语言:javascript
复制
$ ./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

代码语言:javascript
复制
$ cat file2.txt
This is a tale
Of Captain Jack Sparrow
A Pirate So Brave
On the Seven Seas.

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

票数 1
EN

Stack Overflow用户

发布于 2018-06-22 10:19:45

就像另一个回答的人说的那样,fgets的定义是:

代码语言:javascript
复制
char * fgets ( char * str, int num, FILE * stream );

data属于char*类型,因此data[whatever]属于char类型。这可不是什么好事。您应该将其更改为仅data。你还可以在其他几个地方这样做。也将它们更改为data

要找出问题是在fgets期间出现的,您可以使用GDB这样的调试器:

代码语言:javascript
复制
$ 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

$
票数 0
EN

Stack Overflow用户

发布于 2018-06-22 11:50:57

按如下方式修改您的while循环:

代码语言:javascript
复制
while (!feof(fptr1))
{

    fgets(data, 99, fptr1);

    fputs(data, fptr2);

}

请阅读有关fgets()、fput()的文档。只需输入man fgetsman fputs即可。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50979637

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档