1

I want to read a string (str) from the user and a number (num) via scanf() but I don't know how to initialize str correctly.

int main(void)
{
    char *str = NULL;
    int num;
    scanf("%s %d", str, &num);
    printf("str: %s\nnum: %d\n", str, num);
}

If I do it like this I get a segmentation fault.

My problem is that I don't know the length of str so I can't say something like this:

char str[20];

and I'm also not allowed to hardcode some high amount of index e.g.:

char str[999];

My question now: How can I initialize str in this case?

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • 1
    Possible duplicate (among many): [How can I read an input string of unknown length?](https://stackoverflow.com/questions/16870485/how-can-i-read-an-input-string-of-unknown-length) Quite possibly `scanf` with `%s` is the wrong tool for the job - it stops scanning a string at the first space. With `fgets()` you can tell from the absence of a newline in the buffer that the read was not completed. You can then reallocate the buffer and continue the read. – Weather Vane Jul 10 '22 at 13:50
  • @MaxwellD.Dorliea seems a bit overcomplicated but if thats the only possibility? – mariekart42 Jul 10 '22 at 13:55
  • 1
    Reliable input is often non-trivial operation, especially when it is completely open-ended. – Weather Vane Jul 10 '22 at 13:57
  • @WeatherVane I do know there are other ways for handling this but I don't know any other way that is reliable than this present solution. I advise you just keep the solution in a separate c file(modularize it). – Maxwell D. Dorliea Jul 10 '22 at 14:08
  • 1
    You should probably disclose the constraints under which you are working — they are non-standard. Specifying `char str[1024];` and using `%1023s` is a reasonable mechanism in most circumstances. It is simpler than the alternatives. You're only looking for a single word — meaning a sequence of characters that aren't white space characters — or you wouldn't be using `%s`. – Jonathan Leffler Jul 10 '22 at 14:09
  • @MaxwellD.Dorliea unusal situations like this rarely have a one-function-fits-all solution. – Weather Vane Jul 10 '22 at 14:12
  • To _read_ a string, use from the user, use `"%*s"`. This will read a "word" input of any length, but does not save it. To read a line, use `"%*[^n]%*c"`. To also save requires more work. – chux - Reinstate Monica Jul 10 '22 at 14:43

1 Answers1

1

Some implementations provide for a %ms specifier to allocate memory as required by the POSIX specification of scanf(). Even some Unix-like systems (e.g. macOS Monterey 12.x and earlier) do not provide it.

If that is available (check the manual), this will work.

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

int main(void) {
    char *str = NULL;
    int num;
    scanf("%ms %d", &str, &num);
    printf("str: %s\nnum: %d\n", str, num);
    free(str);
    return 0;
}

To capture a string that includes space and tab, but no digits,

scanf("%m[^\n0123456789] %d", &str, &num);  

could be used

xing
  • 2,125
  • 2
  • 14
  • 10
  • This worked only for a word. If you try a sentence it will print the first word before space(' '). – Maxwell D. Dorliea Jul 10 '22 at 14:03
  • @MaxwellD.Dorliea — that's not a legitimate critique: the question attempts to use `%s`, and this answer follows the question. The question doesn't specify an alternative behaviour. If the OP wanted to read a line, then [`fgets()`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/fgets.html) or POSIX's [`getline()`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getline.html) might be appropriate. – Jonathan Leffler Jul 10 '22 at 14:05
  • @JonathanLeffler I wasn't critiquing but just giving a heads up. – Maxwell D. Dorliea Jul 10 '22 at 14:10