Search code examples
cscanfterminate

Why is my program suddenly terminating before executing scanf()?


I am trying to write code to replace a line from a text file. It compiles successfully, but it terminates out of nowhere as soon as it tries to scan the line number to be replaced.

I really have no idea what I am doing wrong. I have also tried with fgets() but it still doesn't work.

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

#define MAXNAME 30
#define MAXLINE 256

int main(){
    char fileName[MAXNAME];
    FILE *originalFileCheck;

    printf("Input the name of the file to be opened: ");
    scanf("%s", fileName);
    originalFileCheck = fopen(fileName, "r");

    if(originalFileCheck == NULL){
        printf("The file %s was not opened successfully. The program will now terminate.\n", fileName);
        exit(1);
    }
    else{
        FILE *tempFileWrite;
        char tempName[MAXNAME] = "temp.txt";
        tempFileWrite = fopen(tempName, "w");

        char newLine[MAXLINE];
        int lineNum;

        printf("Input the content of the new line: ");
        scanf("%s", newLine);
        printf("Input the number of the line you want to replace: ");
        scanf("%d", &lineNum); /* it terminates WITHOUT scanning this int*/

        char str[MAXLINE];
        int counter = 1;
        while(fgets(str, MAXLINE, originalFileCheck) != NULL){
            if(counter != lineNum){
                for(int i = 0; str[i] != '\0' && str[i] != '\n'; i++){
                    fputc(str[i], tempFileWrite);
                }
                fprintf(tempFileWrite, "\n");
            }
            else{
                 fprintf(newLine, "%s\n", tempFileWrite);
                }
            counter++;
        }

        fclose(tempFileWrite);
        fclose(originalFileCheck);
        ...
        return 0;
}

Solution

  • the following proposed code:

    1. cleanly compiles
    2. checks for input errors
    3. checks for output errors
    4. performs the desired functionality
    5. properly cleans up when an error occurs

    and now, the proposed code:

    #include <stdio.h>
    #include <stdlib.h>
    
    #define MAXNAME 30
    #define MAXLINE 256
    
    int main( void )
    {
        char fileName[MAXNAME];
        FILE *originalFileCheck;
    
        printf("Input the name of the file to be opened: ");
        if( !fgets( filename, sizeof( fileName ), stdin) )
        {
            fprintf( stderr, "fgets to input 'original' file name failed\n" );
            exit( EXIT_FAILURE );
        }
    
        // remove trailing newline
        fileName[ strcspn( fileName, "\n" ) ] = '\0';
        originalFileCheck = fopen( fileName, "r" );
        if( !originalFileCheck )
        {
            perror( "fopen original file for read failed" );
            exit( EXIT_FAILURE );
        }
    
    
        FILE *tempFileWrite;
        char tempName[ MAXNAME ] = "temp.txt";
    
        tempFileWrite = fopen( tempName, "w" );
        if( !tempFileWrite )
        {
            perror( "fopen to write new file failed" );
            fclose( originalFileCheck );
            exit( EXIT_FAILURE );
        }
    
        char newLine[ MAXLINE ];
        int lineNum;
    
        printf("Input the content of the new line: ");
        if( !fgets( newLine, sizeof( newLine ), stdin ) )
        {
            perror"fgets to input new line content failed" );
            fclose( originalFileCheck );
            exit( EXIT_FAILURE );
        }
    
        printf("Input the number of the line you want to replace: ");
        if( scanf("%d", &lineNum) != 1 )
        {
            fprintf( stderr, "scanf for replacement line number failed\n" );
            fclose( originalFileCheck );
            fclose( tempFileWrite );
            exit( EXIT_FAILURE );
        } 
    
        char str[MAXLINE];
        int counter = 1;
        while( fgets(str, sizeof( str ), originalFileCheck) )
        {
            if(counter != lineNum)
            {
                if( fputs( str, tempFileWrite ) == EOF )
                {
                    perror( "fputs for original line failed" );
                    fclose( originalFileCheck );
                    fclose( tempFileWrite );
                    exit( EXIT_FAILURE );
                }
            }
    
            else
            {
                if( fputs( newLine, tempFileWrite ) == EOF )
                {
                    perror( "fputs for replacement line failed" );
                    fclose( originalFileCheck );
                    fclose( tempFileWrite );
                    exit( EXIT_FAILURE );
                }
            }
            counter++;
        }
    
        fclose(tempFileWrite);
        fclose(originalFileCheck);
    
        return 0;
    }