Error in fgets function

2

The program gives segmentation fault (core dump) when executing the fgets function. Any ideas?

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

main (int argc, char **argv)
{
    FILE *fp=NULL;
    char *f_name;

    switch(argc)
        {
        case(1):fgets(f_name,100,stdin);break;  
        case(2):f_name=argv[1];break;   
        default:printf("\nErro de syntax %s", argv[0]); exit(0);
        }

fputs(f_name, stdout);

fp=fopen(f_name, "r");

if (fp==NULL)
printf("\nNão abriu.\n");
else 
printf("\nAbriu\n");

}
    
asked by anonymous 16.05.2014 / 00:37

3 answers

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

int main (int argc, char **argv) {
    FILE *fp = NULL;
    char f_name[100];

    switch(argc) {
        case(1): fgets(f_name, 100, stdin); break;  
        case(2): strncpy(f_name, argv[1], 100); break;   
        default: printf("\nErro de syntax %s", argv[0]); exit(0);
    }

    fputs(f_name, stdout);
    fp = fopen(f_name, "r");
    if (fp == NULL)
        printf("\nNão abriu.\n");
    else 
        printf("\nAbriu\n");
}

I placed it on GitHub for future reference .

This will allocate the memory needed to store the content read in stdin with fgets() . In this case, the declaration as array guarantees the previous allocation of memory in stack .

It is also possible to keep using with pointer and giving a malloc() after the declaration and before of fgets() , but I think for you it will be easier to use the form of array , since you used it before.

There are other errors in the code that have now been remedied in the example above. The main thing is that in the second case was copying the wrong content, using the strncpy() you copy byte byte the contents of the first argument passed to the program.

Not directly related to the problem, but to better understand memory management, see

    
16.05.2014 / 00:50
2

As I was already writing somewhat complex comments on the other answers, I decided to add mine.

I'm using 2 separate variables, one to save characters and one to point to the desired array (f_buffer or argv [1]).

The code below is not tested, and there should be at least one thing missing: remove '\ n' which fgets leaves at the end of the array, just before '\ 0' (the '\ n' represents Enter which the user typed). Other functions remove '\ n', but fgets not, allowing you to differentiate a truncated entry from a complete entry. Doing this treatment is like "exercise for the reader" (as I hated it when I read it in a book, hahahaha ...). I changed the printf's at the end to better indicate what the program is doing.

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

#define BUFFER_SIZE 100

int main (int argc, char **argv)
{
    FILE *fp = NULL;
    char *f_name, f_buffer[BUFFER_SIZE];

    switch(argc) {
        case 1:
            fgets(f_buffer, BUFFER_SIZE, stdin);
            /* A FAZER: remover o '\n' do fim do do nome. */
            f_name = f_buffer;
            break;
        case 2:
            f_name = argv[1];
            break;
        default:
            printf("\nErro de syntax %s", argv[0]);
            exit(0);
    }

    fputs(f_name, stdout);

    fp = fopen(f_name, "r");

    if (fp == NULL)
        printf("\nNão abriu [[%s]].\n", f_name);
    else 
        printf("\nAbriu [[%s]]\n", f_name);
}
    
16.05.2014 / 21:22
1

You have a problem here between using arrays and pointers.

char *f_name;

Here you declared a pointer with no set value. When it does:

fgets(f_name, 100, stdin);

The fgets() expects to receive in the first argument a pointer pointing to some memory with at least 100 bytes. The first is the pointer to your buffer and the second is the size of it. When you passed an uninitialized pointer, it is causing fgets() to write somewhere unknown in memory, causing your crash .

The solution, as Maniero said, is to create an array with 100 chars at the beginning, like this:

char f_name[100];

When it does:

fgets(f_name, 100, stdin);

You are now passing a pointer to the first element of array (writing f_name in this case is equivalent to &f_name[0] ). You have effectively passed a pointer to a buffer of 100 bytes, everything will work. Except ...

f_name = argv[1];

Here f_name is an array , and setting the arrays value is illegal. That does not even make much sense. What you really want is to copy the data that is in argv[1] to the array . To do this, use strncpy , like this:

strncpy(f_name, argv[1], 100);

The function will copy up to 100 bytes from the source to the destination.

    
16.05.2014 / 01:24