Thread: Dynamic memory allocation. Very simple question.

  1. #1
    Registered User
    Join Date
    May 2017
    Posts
    101

    Dynamic memory allocation. Very simple question.

    Hi. I am trying to understand dynamic memory allocation. Now I am learning by myself, so any advice will be appreciated and taken into account in the code since nobody but me will see it.

    I am trying to solve an exercise, quite simple. The program should asks the number characters that a user should input. Using dynamic memory allocation, the output should be all the characters inserted by user according to the number of characters the user put previously.

    I tried to solve by myself but failed. This is my code:

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    int main()
    {
        int num;
        char *ptr;
    
        printf("Insert the number of characters: ");
        scanf("%d", &num);
    
        ptr=(char*) malloc(num*sizeof(char));
        if (ptr==NULL) {
            printf("No memory available");
        } else {
            printf("Insert the characters: ");
            fflush(stdin);
            scanf("%s", ptr);
            for (int i=0; i<num; i++) {
                printf("%s", ptr);
            }
        }
        free(ptr);
        return 0;
    }
    I insert hello, the output is hello 10 times. I want all the characters until reaching the number of characters previously declared.

    Thank you in advance.
    Last edited by JorgeChemE; 06-09-2017 at 05:28 AM. Reason: Fixed C++ libraries, I am using C

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    So is this C or C++, or just a random mix of both - whatever tastes good at the moment?

    printf("%c\n", ptr[i] );
    is how you print individual characters.

    Also, lose the fflush(stdin). See the FAQ.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    May 2017
    Posts
    101
    Sorry, I forgot to remove usingnamespacestd;. This is C, I am trying to solve it in C. I will fix the code, see now.

    Thank you for the printf. I used the fflush(stdin) because the program skipped the Insert characters sentence, so the easiest remedy was using fflush(stdin). Is there any other alternative?

  4. #4
    Programming Wraith GReaper's Avatar
    Join Date
    Apr 2009
    Location
    Greece
    Posts
    2,738
    Remove iostream and "using namespace std;", you aren't using C++ at all.

    Don't flush stdin.
    Use this simple code before your "%s" scanf. It's necessary only when you've used scanf before and haven't discarded the newline character. It does exactly that, loops through all inputted characters until it reaches newline.
    Code:
    while (getchar() != '\n')
        continue;
    Don't use "%s" with printf, you obviously don't know how it works (no offense). Use "%c" with the loop instead. Same for scanf, use " %c" (notice the extra space) with a loop, but don't forget to add '\0' at the end.

    You could also remove the loop you use entirely, since you don't really need it. Also, there's another slightly more difficult method for getting the input, I'll demonstrate it here but I don't recommend it for you yet (I don't even know if it's compilable).
    Code:
    char inputQuery[16];
    ...
    sprintf(inputQuery, "%%%ds", num);
    scanf(inputQuery, ptr);
    Last edited by GReaper; 06-09-2017 at 05:51 AM.
    Devoted my life to programming...

  5. #5
    Registered User
    Join Date
    May 2017
    Posts
    101
    Hi guys,

    After messing up the code, according to your recommendations, I changed the loop "for" for "while". This is the code right now:

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    
    int main()
    {
        int num, i=1;
        char c, *ptr;
    
    
        printf("Insert the number of characters to input: ");
        scanf("%d", &num);
    
    
        ptr=(char*) malloc(num*sizeof(char));
        if (ptr==NULL) {
            printf("There is no enough memory to allocate");
        } else {
            printf("Insert the text: ");
            scanf(" %c", ptr);
            while (c!='\n') {
                c=getc(stdin);
                ptr=(char*) realloc(ptr, num*sizeof(char));
                ptr[i]=c;
                i++;
            }
        }
        printf("\nThe characters inserted are: %s", ptr);
        free(ptr);
        return 0;
    }
    Just before you yell at me, printf("\nThe characters inserted are: %s", ptr); I know is %s, you told me to change into %c but doesn't work with %c. I want to read all the characters until the number of characters allowed. Now if you read this, you can yell at me, don't worry, I get used to be bullied...

  6. #6
    Registered User
    Join Date
    May 2009
    Posts
    4,183
    Why are you using realloc ?

    Edit: Figured out you were using scanf to skip the input and ignore first character.
    But, I think is is wrong solution.

    Tim S.
    Last edited by stahta01; 06-09-2017 at 08:47 AM.
    "...a computer is a stupid machine with the ability to do incredibly smart things, while computer programmers are smart people with the ability to do incredibly stupid things. They are,in short, a perfect match.." Bill Bryson

  7. #7
    Registered User
    Join Date
    May 2017
    Posts
    101
    Quote Originally Posted by stahta01 View Post
    Why are you using realloc ?

    Edit: Figured out you were using scanf to skip the input and ignore first character.
    But, I think is is wrong solution.

    Tim S.
    I'm not conviced with the results... Program works with small words but if I put a num=10 and write a large word, crashes...

  8. #8
    Programming Wraith GReaper's Avatar
    Join Date
    Apr 2009
    Location
    Greece
    Posts
    2,738
    I'm not bullying you, I just pointed out that you were using it incorrectly. Now it's fine though.

    There's no reason to use realloc, the user has already told you how many characters they would input and you have already allocated the required space. Additionally, I think you should move "c=getc(stdin);" to the end of the while loop, otherwise you discard that first character you get. Oh, and please terminate the string correctly, with a '\0' character.

    Finally, note that a user can still input more characters that they said they would... You may want to check for that, so as to not cause a crash or even allow other parts of the memory to be read without your consent.

    EDIT: I forgot that you need an extra character for the string terminator, therefore your allocation should be like
    Code:
    ptr=malloc((num+1)*sizeof(char));
    Oh, and in C, there's no point in casting a void pointer to another type, this is done automatically.
    Last edited by GReaper; 06-09-2017 at 09:02 AM.
    Devoted my life to programming...

  9. #9
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    > I'm not conviced with the results... Program works with small words but if I put a num=10 and write a large word, crashes...
    The condition in your loop needs to be
    while ( i < num-1 )

    Otherwise, there is nothing to stop you roaming off the end of your memory.

    It's num-1 so you also have room to append a \0 - which is necessary if you use %s to print it later.


    Also, arrays start at index 0, so initialise i appropriately.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  10. #10
    Registered User
    Join Date
    May 2017
    Posts
    101
    This is the best code I have until now, works good, do what should be doing. Since I am not enrolled in the course (finished) I am open to improvements.

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    
    int main()
    {
        int num, i=1;
        char c, *ptr;
    
    
        printf(Insert the number of characters: ");
        scanf("%d", &num);
    
    
        ptr=(char *) malloc((num)*sizeof(char));
        if (ptr==NULL) {
            printf("There is no memory to allocate");
        } else {
            printf("Insert the text: ");
            scanf(" %c", ptr);
            while (c!='\n' && i<=num) {
                c=getc(stdin);
                ptr[i]=c;
                i++;
            }
        }
        ptr[i]='\0';
        printf("\nThe characters inserted are: %s", ptr);
        free(ptr);
        return 0;
    }
    Output:

    Insert the number of characters: 4
    Insert the text: laparoscopia

    The characters inserted are: lapar

  11. #11
    Programming Wraith GReaper's Avatar
    Join Date
    Apr 2009
    Location
    Greece
    Posts
    2,738
    Right now, you get one extra character. This happens because you start counting from 1, while in C arrays start counting from 0.
    Devoted my life to programming...

  12. #12
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    > while (c!='\n' && i<=num)
    I guess the < num-1 I said went straight in one ear and out the other.

    Explain how <= leaves room for a \0 to be appended.

    > ptr=(char *) malloc((num)*sizeof(char));
    If you want to store 3 characters, then you need to allocate 4 bytes (you need +1 for the '\0' at the end).
    Also, remove the cast on the result of malloc. This will probably reveal that you're still using a C++ compiler to compile your C code.
    Perhaps you should save your source code as prog.c rather than prog.cpp
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  13. #13
    Registered User
    Join Date
    May 2017
    Posts
    101
    This is the code that does the work:

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    int main()
    {
        int num, i=1;
        char c, *ptr;
    
        printf("Insert the number of characters: ");
        scanf("%d", &num);
    
        ptr=(char *) malloc((num+1)*sizeof(char));
        if (ptr==NULL) {
            printf("There is not enough memory");
        } else {
            printf("Insert the text: ");
            scanf(" %c", ptr);
            while (c!='\n' && i<=num-1) {
                c=getc(stdin);
                ptr[i]=c;
                i++;
            }
        }
        ptr[i]='\0';
        printf("\nCharacters inserted are: %s", ptr);
        free(ptr);
        return 0;
    }

    Output:

    Insert the number of characters: 4
    Insert the text: laparoscopia

    The characters inserted are: lapa

    If I initialize i=0 -> The characters inserted are: apar (I am always missing the first character, in this case l, and get the next character instead).

    If I put while (c!='\n' && i<num-1) the output is: lap (I am missing the last character, print 3 instead f 4) so I decided to try with i<=num-1 and I get all the characters needed.

  14. #14
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    If there's not enough memory, then you shouldn't be dereferencing ptr or printing the non-existent string. I would also do a bit of error checking on the value entered, e.g., make sure that it is positive (and perhaps set an upper bound). For actually reading the string, you might as well use fgets instead of writing a loop with getc. Combining these ideas, I might rewrite your program to something like this:
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    int main(void)
    {
        int num;
        int c;
        char *ptr;
    
        printf("Insert the number of characters: ");
        if (scanf("%d", &num) != 1)
        {
            fprintf(stderr, "There was an input error, please try again.\n");
            return EXIT_FAILURE;
        }
        if (num <= 0)
        {
            fprintf(stderr, "The number of characters must be positive, please try again.\n");
            return EXIT_FAILURE;
        }
    
        /* discard characters remaining on the standard input stream */
        while ((c = fgetc(stdin)) != '\n' && c != EOF);
    
        ++num; /* account for the null character */
        ptr = malloc(num * sizeof(*ptr));
        if (!ptr)
        {
            fprintf(stderr, "There is not enough memory.\n");
            return EXIT_FAILURE;
        }
    
        printf("Insert the text: ");
        if (!fgets(ptr, num, stdin))
        {
            fprintf(stderr, "There was an input error, please try again.\n");
            free(ptr);
            return EXIT_FAILURE;
        }
    
        ptr[strcspn(ptr, "\n")] = '\0'; /* get rid of newline character, if it exists */
        printf("Characters inserted are: %s\n", ptr);
        free(ptr);
    
        return 0;
    }
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  15. #15
    Registered User
    Join Date
    Sep 2014
    Posts
    364
    Quote Originally Posted by JorgeChemE View Post
    This is the code that does the work:

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    int main()
    {
        int num, i=1;
        char c, *ptr;
    
        printf("Insert the number of characters: ");
        scanf("%d", &num);
    
        ptr=(char *) malloc((num+1)*sizeof(char));
        if (ptr==NULL) {
            printf("There is not enough memory");
        } else {
            printf("Insert the text: ");
            scanf(" %c", ptr);
            while (c!='\n' && i<=num-1) {
                c=getc(stdin);
                ptr[i]=c;
                i++;
            }
        }
        ptr[i]='\0';
        printf("\nCharacters inserted are: %s", ptr);
        free(ptr);
        return 0;
    }

    Output:

    Insert the number of characters: 4
    Insert the text: laparoscopia

    The characters inserted are: lapa

    If I initialize i=0 -> The characters inserted are: apar (I am always missing the first character, in this case l, and get the next character instead).

    If I put while (c!='\n' && i<num-1) the output is: lap (I am missing the last character, print 3 instead f 4) so I decided to try with i<=num-1 and I get all the characters needed.
    Error messages should be outputed on stderr, insteed of stdout.
    Also, if a program stops because of error, it should return a value other than zero to reflect this issue to the caller.
    You miss the first character because of the 'scanf(" %c", ptr)' on line 17.
    I think you wrote this line to drop the newline from stdin.
    It is nice that you don't use 'fflush(stdin)', realy good.
    But you can write your own flush function for stdin.
    Code:
    void flush_stdin(void) {
        char x;
        while ((x = getc(stdin)) != '\n' && x != EOF);
    }

    Now, every time you want clear the stdin, you call 'flush_stdin()'.


    Next, your malloc:
    Other members on this forum have say (more than one time) that you should NOT cast the returned value of malloc.
    What nobody have say until now, 'sizeof(char)' is allways 1, this garantied the c-standard.
    So, you don't must write 'malloc((num+1)*sizeof(char))'. You need only 'malloc(num + 1)'.


    stdout is (like stdin) line buffered. If you print out enything without a newline at the end,
    it can be that nothing is shown on the console. The OS is forced to output the text if there is a newline at the end,
    but otherwise it can output it, but it dont must.
    To force the OS to output the text, flush stdout.


    So this leeds to the following code and now it works with 'i=0' and 'i < num'.


    Code:
    #include <stdio.h>
    #include <stdlib.h>
     
    void flush_stdin(void) {
        char x;
        while ((x = getc(stdin)) != '\n' && x != EOF);
    }
    
    
    
    
    int main(void)
    {
        int num, i=0;
        char c, *ptr;
     
        printf("Insert the number of characters: ");
        fflush(stdout); // no newline at the end of last output - flush it!
        scanf("%d", &num);
    
    
        ptr = malloc(num + 1); // sizeof(char) is allways 1, so nobody need it
        if (ptr==NULL) {
            fprintf(stderr, "There is not enough memory! exit.\n"); // error goes to stderr
            return 1; // return a non zero value to reflect a problem
        }
        flush_stdin(); // clear the buffer of stdin
        printf("Insert the text: ");
        fflush(stdout); // no newline at the end of last output - flush it!
        while ((c = getc(stdin)) != '\n' && i < num) {
            ptr[i++] = c;
        }
        ptr[i]='\0';
        printf("\nCharacters inserted are: '%s'\n", ptr);
        free(ptr);
        return 0;
    }
    Other have classes, we are class

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Dynamic Memory Allocation - A Simple DOS Text Game
    By pavil in forum C++ Programming
    Replies: 15
    Last Post: 05-12-2014, 06:32 AM
  2. Dynamic memory allocation question.
    By peripatein in forum C Programming
    Replies: 14
    Last Post: 05-24-2013, 02:03 PM
  3. Question about dynamic memory allocation
    By dayanike in forum C Programming
    Replies: 2
    Last Post: 12-11-2012, 08:35 AM
  4. Dynamic Memory Allocation Question
    By somniferium in forum C Programming
    Replies: 6
    Last Post: 10-12-2012, 07:51 PM
  5. Dynamic Memory Allocation Question
    By Piknosh in forum C++ Programming
    Replies: 1
    Last Post: 04-14-2004, 01:55 PM

Tags for this Thread