0

How to dynamically accept a string with spaces? I had tried gets(), but it is not working, and I don't want to take input from file. I want to accept a string without specifying string size.

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

char *accept()
{
    char *s;
    s = (char *)malloc(sizeof(char));
    gets(s);
    return s;
}

int main()
{
    char *str;
    printf("\nEnter`enter code here` one string");
    str = accept();
}
Oka
  • 23,367
  • 6
  • 42
  • 53
P.Hajare
  • 17
  • 1
  • 1
  • 2
  • Use `calloc` if you want to read strings without specifying size. Do not use `gets`, instead use `fgets`. – haccks Jan 31 '16 at 05:42
  • 3
    See [Why `gets()` is too dangerous to be used](http://stackoverflow.com/questions/1694036/why-is-the-gets-function-dangerous-why-should-it-not-be-used). Seriously look at POSIX function [`getline()`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getline.html). – Jonathan Leffler Jan 31 '16 at 06:19
  • 2
    Also, `accept()` is not a good name to use — because there is a system function [`accept()`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/accept.html) used by networking code (servers, primarily). – Jonathan Leffler Jan 31 '16 at 06:20

3 Answers3

2

First of all, never use gets(). Use fgets() instead. gets() can't prevent if you overflow the buffer. It has been removed from the C standard C11.

Here,

 s = (char *)malloc(sizeof(char));

you are allocating memory for just a single char which is enough only for the null character to terminate the string. You need to allocate more space to read a line.

 s = malloc(256); //sizeof(char) is always 1. So you don't have to multiply it.
 if( fgets(s, 256, stdin) == NULL )  { /* handle failure */

fgets() also reads the newline if the buffer has sufficient space. So you may want to remove if it's not desired. You can remove it using strcspn():

s[strcspn(s,"\n")] = 0;
P.P
  • 117,907
  • 20
  • 175
  • 238
2

I want to accept string without specifying sting size.

  1. Start with a hard code number as the initial size of the string.
  2. Read characters one by one. Add the characters to the string. If the number of characters in the line exceeds the current size, increase the size of the string.

Here's such a function:

char *accept()
{
   // Initial size of the string.
   int size = 256;
   int c;
   int index = 0;

   char* s = malloc(size);
   if ( s == NULL )
   {
      return NULL;
   }

   while ( (c = getchar()) != EOF && c != '\n')
   {
      // We need one character for the terminating null character
      // Hence, if index is equal to (size-1), we need to resize the
      // string.
      if ( index == size - 1)
      {
         // Resize the string.
         size = size * 2;
         s = realloc(s, size);
         if ( s == NULL )
         {
            return NULL;
         }
      }
      s[index] = c;
      ++index;
   }

   // NUll terminate the string before returning it.
   s[index] = '\0';
   return s;
}

PS Don't ever use gets. See Why is the gets function so dangerous that it should not be used?. Use fgets if you need to read a line of text.

Community
  • 1
  • 1
R Sahu
  • 204,454
  • 14
  • 159
  • 270
  • I think you have an off-by-one problem.. Consider reading 256 characters, then `s[256] = '\0';` --> UB – chux - Reinstate Monica Jan 31 '16 at 05:58
  • @chux, very true. Fixed it. Thanks. – R Sahu Jan 31 '16 at 06:00
  • If size is larger than, say, 1 KiB and there's more than say 256 bytes left over, you might think about a final `realloc()` to shrink the string to size. However, that's a veryminor space optimization, and definitely only relevant if the string is big (and I'm not wholly convinced the numbers given are big enough). – Jonathan Leffler Jan 31 '16 at 06:22
0

Define the approximate size of user input by

#define LENGTH 30

char *accept(){
    char *s = (char*)malloc(sizeof(char)*LENGTH); 
    scanf("%29[0-9a-zA-Z ]", s); 
   //scanf("%[^\n]%*s", s); //or this
    return s;
}

Note that the 29 is the maximum number of characters which will be read, so s has to point to a buffer of size LENGTH-1 at least.

roottraveller
  • 7,942
  • 7
  • 60
  • 65
  • 1
    1) `"%99[0-9a-zA-Z]"` does not "accept a string with spaces". 2) `(char*)` not needed. 3) What does 99 do with `LENGTH`? 4) `scanf()` return value not checked. 5) `sizeof(char)` is always 1, so why is it there? Recommend `fgets()` – chux - Reinstate Monica Jan 31 '16 at 05:54
  • @chux Corrected. `fgets()` better but I just give an alternative. – roottraveller Jan 31 '16 at 06:06