10

For whatever reason the following code prints (null):

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

int main(void)
{
    char *foo; 
    scanf("%ms", &foo);
    printf("%s", foo);
    free(foo);
}

I'm trying to allocate memory for a string dynamically but as I said earlier my program simply outputs (null). I worked around this by making a function using getche and realloc but it seems almost pointless due to the fact that I also had to program what would happen if the user entered backspace, tab, etc.. But as I said that is just a work around and I would rather know why the above code is not working...

Additional Information:

I am using the Pelles C IDE v7.00 and compiling with the C11 standard

Keith Miller
  • 1,337
  • 1
  • 16
  • 32

5 Answers5

9

I am not seeing %m in section 7.21.6.2 of the Draft C11 standard (the section on fscanf). I suggest that you avoid it and call malloc() as you would in C99.

Norman Ramsey
  • 198,648
  • 61
  • 360
  • 533
  • 3
    Seeing as you can't predict how much space to allocate with `scanf("%s")`, I'd also recommend avoiding `scanf` entirely and using `fgets` and `sscanf`. – jamesdlin Apr 16 '13 at 18:10
  • 7
    The `%ms` notation is a POSIX extension in [`scanf()`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/scanf.html) compared with the standard C version of `scanf()`. – Jonathan Leffler Nov 11 '13 at 00:02
  • Maybe use this in conjunction with a method that tells you how big the data is, that you receive in advance (on the stack). Just an idea. – Vandrey Mar 14 '20 at 22:40
2

%m is a POSIX extension, which may be why it's not available in Pelles C.

ulatekh
  • 1,311
  • 1
  • 14
  • 19
1

There is an example in the man page for scanf/sscanf (page 3, from line 270-290) that states the following:

EXAMPLE

To use the dynamic allocation conversion specifier, specify m as a length modifier (thus %ms or %m[range]). The caller must free(3) the returned string, as in the following example:

char *p;
int n;

errno = 0;
n = scanf("%m[a-z]", &p);
if (n == 1) {
   printf("read: %s\n", p);
   free(p);
} else if (errno != 0) {
   perror("scanf");
} else {
   fprintf(stderr, "No matching characters\n");
}

As shown in the above example, it is necessary to call free(3) only if the scanf() call successfully read a string.

Source: SCANF(3) - Linux Programmer's Manual - GNU - 2013-01-30

Palec
  • 12,743
  • 8
  • 69
  • 138
Steve
  • 11
  • 1
0

I am using Linux 3.2.0 amd 64 with gcc 4.7.2. Using the code:

char *s; 
scanf("%ms", &s);
printf("%s", s);
free(s);

works fine but it won't accept whitespaces.

For static allocation, you can instead use:

char s[100];
printf("Enter string (max 99 characters): ");
scanf("%100[^\n]s", &s);
printf("You entered: %s\n", s);

Hope it helps!

Arun
  • 2,222
  • 7
  • 43
  • 78
  • Sorry for that but you are not helping him because if you take a look at your `scanf()` function you will definitely realize that it is wrong ! it should be `scanf("%ms", s)` as s is a pointer in itself ! Please note that there is no `&` before the `s`. Besides keep in mind that it will not work for the next `scanf` in the program if there are any !!! Hope it is clear !!! – Meninx - メネンックス Jan 18 '15 at 14:31
  • 6
    @Meninx: no, with `%ms`, it should be `scanf("%ms", &s)`. The POSIX `m` extension allocates the string for you and assigns it to `s`, which must be of type `char*`. – Rudy Velthuis Jul 31 '16 at 16:02
  • The `scanf("%ms", &s)` is correct, the call modifies the pointer stored in `s`. However, **the `scanf("%100[^\n]s", &s)` is wrong**. It needs to be `scanf("%99[^\n]", s)`. In this case, the pointer to the first byte of the buffer needs to be passed by value, so `s` is correct. And the `s` after the closing bracket `]` is wrong, it's not part of the conversion. But, most importantly, the buffer must be longer than the field width to leave room for the terminating null byte. **Using a field width of 100 for a 100 byte buffer allows users to overrun the buffer**. – cmaster - reinstate monica Mar 14 '20 at 22:50
0

as Arun says, this solution is right and Meninx's opinion is wrong:

char *s;
scanf("%ms", &s);
printf("%s", s);
free(s);

I have read the 'man scanf', it says:

An optional 'm' character. This is used with string conversions(%s, %c, %[),
and relieves the caller of the need to allocate a corresponding buffer to hold the input: instead, scanf() allocates a buffer of sufficient size, and assigns the address of this buffer to the corresponding pointer argument, which should be a pointer to a char * variable (this variable does not need to be initialized before the call). The caller should subsequently free(3) this buffer when it is no longer required.

Community
  • 1
  • 1
zhangjie
  • 321
  • 3
  • 10