jabk
jabk

Reputation: 1458

Segmentation fault in c when reading a line

I want to read user input(like terminal) until exit is written or ctrl+c/ctrl+d is pressed. I read every line(until return/enter is pressed), check if it's just space or a comment(#) and then execute some functions.

I tried three methods, but no success. I get an error every time I insert a string and press enter

char line[256];
while(printf("%s>", shell_name) && scanf("%50[^\n]", line) != EOF)
{

Segmentation fault (core dumped)

while(printf("%s>", shell_name) && getline(line, 100, stdin) != EOF)

note: expected ‘size_t * restrict’ but argument is of type ‘int’

while(printf("%s>", shell_name) && fgets(line, sizeof(line), stdin) != NULL)
{

Segmentation fault (core dumped)

for more orientation I'm doing this next

if(isspace(&line) == 0 && &line[0] != "#")

what am i doing wrong? is there a more suitable/easy/better option?

Upvotes: 1

Views: 2556

Answers (1)

Jongware
Jongware

Reputation: 22457

The segfault probably kicks in because you enter into an infinite loop: scanf("%50[^\n]", line) reads your input and stops at the Return. The Return is not consumed and stays in the input buffer. So what happens next time around? scanf checks the input buffer, and hey! there is a return! So it stops reading. Et cetera.

Adding a space as the first character inside the scanf format string resolves that:

int main()
{
    char line[256];
    char *shell_name = "mysh";

    while (printf("%s>", shell_name) && scanf(" %50[^\n]", line) != EOF)
    {
        printf ("you entered [%s]\n", line);
    }
    printf ("done.\n");
    return 0;
}

On a further note, this is wrong:

if(isspace(&line) == 0 && &line[0] != "#")

-- gcc complains

warning: passing argument 1 of 'isspace' makes integer from pointer without a cast
warning: comparison with string literal results in unspecified behavior

The first on isspace(&line), where you probably meant isspace(line[0]), the second on &line[0] != "#", which can be written much more concisely as line[0] != '#'.


on getline

getline works different from the other "get from stdin" functions, because it will automatically allocate memory if asked to. Since it needs to return not one, but three results (the number of characters, the string entered, and its length) you need to provide pointers to the string and size arguments:

size_t line_size = 0;
char *ptr_to_line = NULL;

while (printf("%s>", shell_name) && getline(&ptr_to_line, &line_size, stdin) != -1)
      ...

When using this way, you should not use the static string size allocation, as the function will fill in appropriate values. (But don't forget it uses malloc and realloc internally, so make sure to free the result. It uses malloc the first time, realloc after that to resize.)

Upvotes: 1

Related Questions