LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (http://www.linuxquestions.org/questions/programming-9/)
-   -   dynamic memory allocation - malloc, scanf! (http://www.linuxquestions.org/questions/programming-9/dynamic-memory-allocation-malloc-scanf-513402/)

cpd05 12-24-2006 12:06 PM

dynamic memory allocation - malloc, scanf!
 
Hello,

I'm learning C at the moment and am confused about how to dynamically allocate memory at runtime.
If I wanted to read a variable sized string from stdin, how could I do that? I assume I can use scanf but what do I use as the variable for scanf. How can I allocate the memory for the scanf variable before I know how long the string is, but how can find out the size of the string before I've read it in.
Does that make sense? Am I getting things totally wrong?

Thanks

chris.

kaz2100 12-24-2006 12:32 PM

Hi,

Your penguin can do whatever you CAN tell (describe) to do. If there is no way for you to know what you want to do, you do not know what you want to do.

So,
Quote:

Does that make sense?
makes sense. So that, you already know the answer.

One way of doing your job is, 1) decide whatever size, 2) read that many data from stdin, 3) do what you want 4) repeat 2-3 while you have input.

Happy Penguins!

theNbomr 12-24-2006 01:47 PM

You are asking two separate questions. How to limit the amount of data input, to avoid buffer overflows and other BAD THINGS. And, how to allocate memory for said buffers at runtime. The answer is that you can allocate memory with the malloc/calloc/alloca family of functions (and then free() the memory when done). The amount of memory allocated can then be used as an argument in a call to 'fread()'. The data thus acquired can be parsed using sscanf(), or strtok(), or any number of other ways, depending upon your requirements.

Hope this helps.

--- rod.

paulsm4 12-24-2006 07:48 PM

Hi, cpd05 -

Like the previous posters said, you simply have to guess the biggest string you're likely to encounter ... and then make sure you can deal with it if the actual string turns out to be bigger.

It doesn't matter if you use "malloc()" or simply declare an array (I chose to use an array in the example below).

Unfortunately, there is usually no way to determine the size a priori, then allocate enough space on-the-fly.

Here's an example:
Code:

#include <stdio.h>

#define MAX_BUF 8

int
main(int argc, char *argv[])
{
  char buf[MAX_BUF];
  char *s;

  s = fgets (buf, sizeof (buf), stdin);
  printf ("buf= %s, strlen (buf)= %d, s= %s...\n",
    buf, strlen (buf), s);
  return 0;
}

Quote:

./x
123456789
buf= 1234567, strlen (buf)= 7, s= 1234567...
<= YOU'LL NOTICE THAT "FGETS" AUTOMATICALLY TRUNCATES THE
STRING TO THE LENGTH YOU SPECIFIED (INCLUDING ONE BYTE FOR
THE '\0' STRING TERMINATOR)
'Hope that helps .. PSM

introuble 12-25-2006 01:45 AM

A bit on paulsm4's solution above. Notice that he uses a call to fgets. This function makes sure the buffer isn't overflown, unlinke it's sister/cousin/whatever function gets(). Always make sure you use the former and not the latter.

Also note that in the above example, paulsm4 uses buf and s; which have the same value and thus seem (are?) unneeded. He did this to show you what the return value of fgets() is. You should check out `man fgets` (check out the portion of gets() too; also make sure to read the "return value" section).

I suppose what you want to do is allocate exactly as much memory as you need in order to store the string. There is no real way of doing this, as you have no control on the user's input. Here's something you could do:

Code:

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

#define MAX_INPUT_SIZE 1024

int main(int argc, char **argv)
{
        char *p, *q;

        if ((p = malloc(MAX_INPUT_SIZE)) == NULL) {
                perror("malloc");
                return EXIT_FAILURE;
        }

        if (fgets(p, MAX_INPUT_SIZE, stdin) == NULL) {
                perror("fgets");
                return EXIT_FAILURE;
        }

        if ((q = malloc(strlen(p) + 1)) == NULL) {
                perror("malloc");
                return EXIT_FAILURE;
        }

        strcpy(q, p);
        free(p);
        printf("%s", q);
        return EXIT_SUCCESS;
}


Dan04 12-25-2006 04:37 PM

Code:

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

#define INITIAL_BUFFER_SIZE 16

char *readline(FILE *input) {
  char *buffer;
  int byteRead;
  int count = 0;
  int capacity = INITIAL_BUFFER_SIZE;

  if ((buffer = malloc(capacity)) == NULL) {
      perror("malloc");
      return NULL;
  }

  while ((byteRead = fgetc(input)) != '\n') {
      buffer[count++] = byteRead;

      if (count >= capacity) {
        capacity *= 2;

        if ((buffer = realloc(buffer, capacity)) == NULL) {
            free(buffer);
            perror("realloc");
            return NULL;
        }
      }
  }

  buffer[count] = '\0';
  return buffer;
}

int main() {
  char *str;

  printf("Enter a string: ");
  str = readline(stdin);
  printf("You typed: %s\n", str);
  free(str);
  return 0;
}


cpd05 12-28-2006 06:11 PM

cheers people, I think I get it now :)


All times are GMT -5. The time now is 01:07 AM.