-1

I am to copy a file from the inputed source to the inputed destination. I am getting a segmentation fault error about 2 seconds after the destination is entered. The output file is created so fopen() is working.

I looked online and I see a lot of c=getc(fp). I prefer fread() and fwrite() for this question because it's a little more basic.

Code

#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 */
}
Andrew Ricci
  • 475
  • 5
  • 21
  • 6
    You should check the return values of `fopen`. – MikeCAT Oct 03 '15 at 14:40
  • 3
    fgets() reads a line *including* the \n . You should remove that first. – wildplasser Oct 03 '15 at 14:44
  • Conceptual error here: `if (source[254] == '\n' && source[255] == '\0')` (and again with the destination): it's not the last character in the *buffer* that may be a newline, but the last read character instead. – Jongware Oct 03 '15 at 14:45
  • 1
    "The output file is created so fopen() is working" - but only for the write file. – Jongware Oct 03 '15 at 14:48
  • 1
    If user types `Y` then enter, `fgets(x, 2, stdin);` only saves `"Y"` with its null character leaving the `'\n'` in `stdin` for the next input function. – chux - Reinstate Monica Oct 03 '15 at 14:57
  • `fgets(source, 256, stdin); if (source[254] == '\n' && source[255] == '\0')` --> may lead to undefined behavior. Do not use `source` until check the return value from `fgets()`. – chux - Reinstate Monica Oct 03 '15 at 15:00

3 Answers3

2

fgets store the newline character read in the buffer.

It may prevent fopen to open "the specified file" and fopen may return NULL.

Please delete newline characters if they are in the buffer.
This can be done using this function:

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 */
}

please pass source and destination to this function after reading file names to them.

MikeCAT
  • 73,922
  • 11
  • 45
  • 70
1

Check the return value of fopen.
The program is getting SEGFAULT at fread(a, 1, 1, sp); This happens when SP is NULL. Since the program trying to read only one byte there will not be any chance of overflow.

fopen fails because the source consists of newline character at the end. If you remove newline character from the source and destination before calling fopen your program will work fine.

Gangadhar
  • 10,248
  • 3
  • 31
  • 50
0

Main issue is leaving the '\n' in the filename and then the following fopen() failed, code did not check fopen() return value. Other 2 answers well answered that and at least 1 deserves acceptance.

Subsequent OP edit changed int a[1] to int *a causing a new fault. Suggest changing to

char a[1];
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256