3

I'm new to C so I'm having a little trouble handling everything Java already did for me in the background. Basically what I would like to achieve is this:

  • Declare an array of char with no specified size
  • Ask to the user a string in input (single word or phrase)
  • Set the previous array of char with size of the length of the input string (dynamically)
  • Put the inputed string inside the char array

I've tried using scanf but it doesn't seem to handle string as an array of char(?) so I'm not able to work on the variable I've also read about malloc() functions which dynamically allocates space for an array so I could use it to set the size of the array as the strlen of the string and then put '\0' at the end (just like .asciiz in some assembly language) but I can't figure out how to correlate malloc and input string. Any help would be appreciated! Thanks for your attention

Alex
  • 85
  • 1
  • 8
  • 2
    One option is [`getline`](http://man7.org/linux/man-pages/man3/getline.3.html). (This was actually a comparatively difficult task until `getline` became standard, I think?) – Ry- Dec 09 '17 at 16:45
  • `char *myString=malloc(strlen(s)+1); strcpy(myString, s);` will do the trick. – Paul Ogilvie Dec 09 '17 at 16:45
  • @PaulOgilvie: Where did `s` come from? The question is about taking it as input. – Ry- Dec 09 '17 at 16:46
  • `char s[1024]; fgets(s, 1024, stdin);` OK Now? – Paul Ogilvie Dec 09 '17 at 16:47
  • @PaulOgilvie: Doesn’t work for more than 1024 characters, ’course! Sometimes that’s fine, and when it’s not, you can do it repeatedly after checking for `\n`, certainly… or use `getline`. – Ry- Dec 09 '17 at 16:47
  • Yep; my typo: `gets` or better `fgets` – Paul Ogilvie Dec 09 '17 at 16:48
  • 1
    @PaulOgilvie: Your bigger typo is "`gets` or better" — never, ever use `gets()`; never, ever suggest using it on SO. [The `gets()` function is too dangerous to be used, ever!](https://stackoverflow.com/questions/1694036/why-is-the-gets-function-dangerous-why-should-it-not-be-used) It should be treated as if it were implemented `char *gets(char *s) { assert(s != 0); abort(); return 0; }`. It should be completely anathema. – Jonathan Leffler Dec 09 '17 at 16:58

2 Answers2

4

You can use getline to read an entire line and not have to worry about managing memory during that read. The function was only standardized in POSIX.1-2008, so if you’re using glibc you’ll need to compile with -D_POSIX_C_SOURCE=200809L, for example.

To summarize the linked documentation: getline takes a pointer to a string, and will allocate memory entirely for you if the string is NULL and the size is 0. It returns −1 if it fails to allocate memory (e.g. there’s more input than free memory) or if the end of the input is reached immediately. You always have to free the memory allocated in this way, even if it fails.

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

int main(void) {
    size_t input_size = 0;
    char* input_line = NULL;

    if (getline(&input_line, &input_size, stdin) == -1) {
        free(input_line);
        perror("Failed to read input");
        return EXIT_FAILURE;
    }

    printf("Got input: '%s'\n", input_line);
    free(input_line);
}
Ry-
  • 218,210
  • 55
  • 464
  • 476
2

C does not provide a way for you to create an array of unspecified size. Generally, to do this sort of thing, you must create an array of some size (e.g., using malloc) and start reading user input. If the user input continues too long, you increase the size of the array (using realloc) and continue reading.

Once you reach the end of whatever the user is inputting, then you can reduce the array to match the actual size (again using realloc) if desired.

A consequence of this is that you cannot read the user input in one go. You must write code that reads portions of specific size, either character-by-character or as many characters as fit in the array you have created so far.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312