0

here's the offending code using ubuntu

char *name;

int main(void)
{
  fgets(name, sizeof(name), stdin);
}
void HUD()
{
  printf("%s ", name); 
}

Here's my problem. I started with scanf("%s", &name) and was getting junk at the end of the string. Through the last 2 hours have been reading docs on scanf, and fgets, because apparently scanf shouldn't be used when you don't know the size of the array you want, (and since user input can vary in size) I decided to try using fgets. I've also tried setting a fixed value both by char name[100]; and by fgets(name, 100, stdin)

Now I'm getting a segmentation fault, and through reading every result I found on the first 2 pages of google, my syntax appears correct, and I've found nothing on cboard or here to fix my problem.

Any ideas?

nanthil
  • 65
  • 1
  • 4
  • 11
  • i've done that already. No success. Still getting segmentation fault. – nanthil Jun 05 '15 at 01:03
  • You can use `scanf()` just fine when you don't know the length of the input, as long as you specify a field width that prevents your array from being overrun. `fgets()` has exactly the same limitation; it's just more explicit about making you tell it the limit on how many characters it should read. – John Bollinger Jun 05 '15 at 01:07
  • Do note, however, that `scanf()` and `fgets()` differ on how to determine when to stop reading. – John Bollinger Jun 05 '15 at 01:09

2 Answers2

3

sizeof(name) Will be the size of the pointer on your system, on mine it's 8 bytes. Not the size of the buffer, as you might have been expecting

Also char* name is uninitialised. You will try to write to an uninitialised buffer and it will end in undefined behaviour.

To resolve either make it a fixed size buffer or allocate some space on the heap.

Allocate

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

#define NAME_SIZE 100
char *name;

void HUD()
{
  printf("%s ", name); 
}

int main(void)
{
    name=calloc(NAME_SIZE, sizeof(char));
    fgets(name, NAME_SIZE, stdin);

    HUD();

    free(name);
}

Static Array

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

#define NAME_SIZE 100
char name[NAME_SIZE];

void HUD()
{
  printf("%s ", name); 
}

int main(void)
{
    fgets(name, NAME_SIZE, stdin);

    HUD();
}

You must pass the size of the buffer to fgets so it know how much space it has to write in to.

Paul Rooney
  • 20,879
  • 9
  • 40
  • 61
  • Is there not a way to read the string until they hit \n and set the size of array to chars entered + \0 ? – nanthil Jun 05 '15 at 01:18
  • Things get complicated because buffers don't automatically re size in fgets, you'll have to roll your own solution. fgets will read until array_size - 1 chars have been read or a new line character was reached. – Ryan Jun 05 '15 at 01:19
  • @nathanil in c you don't get much for free. You'd have to implement your own solution that would reallocate a larger buffer as the input grew. If you look at std::string in c++ this does something along those lines. – Paul Rooney Jun 05 '15 at 01:22
  • Thanks guys. This is my 3rd day on this project, a week after starting C coming from C#. I'm learning the hard way that nothing is free in C, like the first time I had to manually sort things haha :) – nanthil Jun 05 '15 at 01:24
  • @nanthil, not with `fgets()`, no. However, although it's not in the C standard, POSIX `scanf()` actually does provide this feature. It might be used like like this: `scanf("%m[^\n]", name)`. There's a bit of a difference in newline handling that you'll have to look out for. – John Bollinger Jun 05 '15 at 01:27
  • @nanthil there is a POSIX function called `getline` which will allocate memory as it goes (although read the documentation carefully as it is a bit unintuitively). Robust commandline input is actually one of the more difficult things to do in C so don't feel discouraged – M.M Jun 05 '15 at 02:17
  • If appreciate it if the down voter could inform me of the shortcomings of my answer, so I can learn from it. – Paul Rooney Jun 05 '15 at 22:26
-2

char *fgets(char *restrict s, int n, FILE *restrict stream);

The fgets() function shall read bytes from stream into the array pointed to by s, until n-1 bytes are read, or a is read and transferred to s, or an end-of-file condition is encountered. The string is then terminated with a null byte. [0]

You need to allocate it to a specific size and call fgets with that size. This code can help you accomplish the same thing, but it has a fixed size buffer.

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

char name;
char* buffer;
int buffer_size = 16;
int i = 0;


void HUD()
{
        printf("%s ", buffer);
}

int main(void)
{
        buffer = malloc(buffer_size);
        if(!buffer) return;

        for(;;) {
                name = getchar();
                if(name < 0) {
                        buffer[i] = '\0';
                        goto finish;
                } else if(i < (buffer_size -1)) {
                        buffer[i++] = name;
                } else if(name == '\n') {
                        break;
                }
        }
        buffer[i] = '\0';
        finish:
            HUD();
            free(buffer);
            return 0;
}

[0] http://pubs.opengroup.org/onlinepubs/009695399/functions/fgets.html

Ryan
  • 14,392
  • 8
  • 62
  • 102
  • What does initializing the variable do? I'm coming from C#, and I was under the impression that if no specific size was given, it would read what I give it, and add a null char to the end of it because it is a char * ... this really wasn't explained to me very well when they explained reading input – nanthil Jun 05 '15 at 01:08
  • `goto finish;` Kill it with fire! – this Jul 14 '15 at 00:52