Yogender Singh
Yogender Singh

Reputation: 321

Initialise char* at runtime with user input

I know this is possible

char text[A_BIG_NUMBER];
printf("Enter your name");
scanf("%s",text);

but is there a way to do this? (without using a char array as backup)

char* text;
printf("Enter your name");
scanf("%s",text);

while first way is easy but if A_BIG_NUMBER is not big enough to hold the string entered by user then it will create problems for the rest of the code, on the other hand if we use a large number then it wastes memory!

Thanks

Edit: Sorry for the wrong tag. I am asking about C only.

Upvotes: 0

Views: 765

Answers (5)

tozka
tozka

Reputation: 3451

You can use getchar, here is a sample code:

  int size = 128;
  char *s = (char*)malloc (size);
  char c;
  int i;
  while ((c = getchar ()) != '\n' && c != EOF)
    {
      s[i] = c;
      ++i;
      if (i == size)
        {
          size = size * 2;
          char *tmp = realloc (s, size);
          if (tmp != NULL)
            s = tmp;
          else ; // error, try with malloc and copy or exit or whatever you want
        }
    }
  s[i] = 0;

Upvotes: 0

Kerrek SB
Kerrek SB

Reputation: 477060

Since you say C++, the answer is "yes, string":

std::string name;

std::cout << "Enter your name: ";

if (!std::getline(std::cin, name)) { /* unexpected end of input */ }

// now use "name"

As you discovered, you generally need dynamic allocation to store external data. (Your code is not very general: you can't have very large automatic arrays, and the fixed size adds arbitrary magic numbers and constraints.) C++ is the perfect language for encapsulating the details of dynamic allocation and cleanup, so that you can use simple, automatic variables to do all the work for you.

If you don't like iostreams, you can rig up your own overload bool getline(std::FILE *, std::string &) that loops over calls to std::fgets and += to extract a complete line.

Upvotes: 3

pmg
pmg

Reputation: 108938

Use a small(ish) buffer with fgets() in a loop. Inside the loop realloc() the final destination.

/* UNTESTED */
char smallish[1000];
char *destin = NULL;
size_t destin_size = 1;
while (fgets(smallish, sizeof smallish, stdin)) {
    destin_size += strlen(smallish);
    char *tmp = realloc(destin, destin_size);
    if (!tmp) /* deal with error */;
    destin = tmp;
    strcat(destin, smallish);
    if (smallish[strlen(smallish) - 1] == '\n') break;
}
/* use destin */
free(destin);

Upvotes: 0

Apeirogon Prime
Apeirogon Prime

Reputation: 1238

char* does not allocate memory for storing the user input string and that is the reason the second code does not work.

If you are worried about the memory usage / wastage, you can overcome these limitations using program specific stack/heap.

Upvotes: 1

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726599

You can certainly use dynamically allocated memory instead of the array, but the fundamental issue of the overrun remains there:

char *text = malloc(A_BIG_NUMBER*sizeof(char));
printf("Enter your name");
scanf("%s",text);

You need to tell scanf that the space is limited, like this:

char text[201];
printf("Enter your name");
scanf("%200s",text);

Note that text[201] has an extra character space for the terminator: %200s limits the input to 200 "real" characters, so you need to provide an extra char for the '\0'.

Upvotes: 1

Related Questions