在fread / fwrite循环中获取分段错误,复制文件

时间:2015-10-03 14:39:05

标签: c segmentation-fault fwrite fread feof

我要将文件从输入源复制到输入目的地。输入目的地后约2秒钟我收到分段错误错误。输出文件已创建,因此fopen()正在运行。

我在网上看了很多c=getc(fp)。我更喜欢fread()fwrite()这个问题,因为它更基本。

代码

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

//void rmnewline(char *string);
void remove_last_newline(char *str);

int main()
{
  char x[3];
  x[0]='y';
  int ch;

  while(x[0]=='y'||x[0]=='Y')
  {
    char source[256], destination[256];
    int *a;

    printf("Enter a source file: ");
    fgets(source, 256, stdin);
    if (source[254] == '\n' && source[255] == '\0') { while ( (ch = fgetc(stdin)) != EOF && ch != '\n'); }
    remove_last_newline(source);

    printf("Enter a destination file: ");
    fgets(destination, 256, stdin);
    if (destination[254] == '\n' && destination[255] == '\0') { while ( (ch = fgetc(stdin)) != EOF && ch != '\n'); }
    remove_last_newline(destination);

    FILE *sp, *dp;

    sp = fopen(source, "r");
    if (sp == NULL) { printf("ERROR: Could not open source file."); exit(1); }
    dp = fopen(destination, "w");
    if (dp == NULL) { printf("ERROR: Could not open destination file."); exit(1); }
    while(1)
    {
      fread(a, 1, 1, sp);
      if (feof(sp))
      break;
      fwrite(a, 1, 1, dp);
    }

    fclose(sp);
    fclose(dp);

    printf("Run Again?(y/n):");
    fgets(x, 2, stdin);
    while ( (ch = fgetc(stdin)) != EOF && ch != '\n');
 }

}

/*void rmnewline(char *string)
{
    int i, l = strlen(string);

    for(i=0; i<=l; i++)
    {
      if(string[i] == '\0')
         return;
      if(string[i] == '\n')
     {
       string[i] == '\0';
       return;
     }
  }

}*/

void remove_last_newline(char *str) {
    if (*str == '\0') return; /* do nothing if the string is empty */
    while(str[1] != '\0') str++; /* search for the end of the string */
    if (*str == '\n') *str = '\0'; /* if the last character is newline, delete it */
}

3 个答案:

答案 0 :(得分:2)

fgets将读取的换行符存储在缓冲区中。

可能会阻止fopen打开&#34;指定的文件&#34;并且fopen可能会返回NULL

如果换行符在缓冲区中,请删除换行符 这可以使用此功能完成:

void remove_last_newline(char *str) {
    if (*str == '\0') return; /* do nothing if the string is empty */
    while(str[1] != '\0') str++; /* search for the end of the string */
    if (*str == '\n') *str = '\0'; /* if the last character is newline, delete it */
}

请在阅读文件名后将sourcedestination传递给此功能。

答案 1 :(得分:1)

检查fopen的返回值。
该计划正在fread(a, 1, 1, sp);获得SEGFAULT 当SP为NULL时会发生这种情况。由于程序试图只读取一个字节,因此不会有任何溢出的可能性。

fopen失败,因为源包含最后的换行符。如果在调用fopen之前从源和目标中删除newline字符,则程序将正常工作。

答案 2 :(得分:0)

主要问题是将'\n'保留在文件名中,然后以下fopen()失败,代码未检查fopen()返回值。其他2个答案得到了很好的回答,至少有1个答案值得接受。

后续OP编辑将int a[1]更改为int *a,从而导致新故障。建议改为

char a[1];