10 Replies - 11722 Views - Last Post: 21 March 2010 - 02:08 PM Rate Topic: -----

#1 Tapas Bose  Icon User is offline

  • D.I.C Regular
  • member icon

Reputation: 23
  • View blog
  • Posts: 472
  • Joined: 09-December 09

How to take string input in C dynamically

Posted 21 March 2010 - 08:51 AM

Today while teaching a question arose in my mind that how can we take string input in C dynamically, I mean in a dynamic array?
Suppose we have the following code :
#include <stdio.h>
#include <stdlib.h>

int main()
{
     char name[100];

     printf("\n  Enter your name : ");
     gets(name);
     printf("\n  Your name is : ");
     puts(name);

     return (EXIT_SUCCESS);
}



Now is it possible to declare char name[100] as char *name? I am getting run-time error.

Is This A Good Question/Topic? 0
  • +

Replies To: How to take string input in C dynamically

#2 JackOfAllTrades  Icon User is offline

  • Saucy!
  • member icon

Reputation: 6066
  • View blog
  • Posts: 23,526
  • Joined: 23-August 08

Re: How to take string input in C dynamically

Posted 21 March 2010 - 08:56 AM

gets(name);


No, no, no. You are too far along in your academic career to even CONSIDER using gets. You should have forgotten that it even exists five minutes after your lecturer told you about it and said "DON'T USE THIS FUNCTION!"
Was This Post Helpful? 1
  • +
  • -

#3 erik.price  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 485
  • View blog
  • Posts: 2,690
  • Joined: 18-December 08

Re: How to take string input in C dynamically

Posted 21 March 2010 - 09:02 AM

gets is a big no no. It can overflow the without warning and wreak havoc. Just use scanf.

As for declaring it as char * name, yes you can do that. to allocate it, make a call to malloc: char * name = malloc(length * sizeof(char)); where length is the number of chars you want it to be able to hold.

When you don't know how large the input size will be, it's best to use a loop to get the chars one at a time, to give you a chance to resize the array if you need to:

int length = 100; //initial size
char * name = malloc(length * sizeof(char)); //allocate mem for 100 chars
int count = 0; //to keep track of how many chars have been used
char c; // to store the current char

while((c = getchar()) != '\n'){ //keep reading until a newline
   if(count >= length)
      name = realloc(name, (length += 10) * sizeof(char)); //add room for 10 more chars
   name[count++] = c
}


When you use malloc and family to dynamically allocate pointers, remember to call the free function on them when you are done with them, so that the memory is released
Was This Post Helpful? 1
  • +
  • -

#4 JackOfAllTrades  Icon User is offline

  • Saucy!
  • member icon

Reputation: 6066
  • View blog
  • Posts: 23,526
  • Joined: 23-August 08

Re: How to take string input in C dynamically

Posted 21 March 2010 - 09:14 AM

Example code which continues to take input into a string until the user hits Ctrl-D (in Unix, Ctrl-Z in Windows I think):
Removed bad code...see below

This post has been edited by JackOfAllTrades: 21 March 2010 - 09:58 AM

Was This Post Helpful? 1
  • +
  • -

#5 Tapas Bose  Icon User is offline

  • D.I.C Regular
  • member icon

Reputation: 23
  • View blog
  • Posts: 472
  • Joined: 09-December 09

Re: How to take string input in C dynamically

Posted 21 March 2010 - 09:23 AM

@ JackOfAllTrades, actually I was teaching how to use gets and puts. I know gets is insecure, and I told my student this point and beside this I told him how to use gets_s in VC++. But thank you for your suggestion.
@ erik.price, thank you very much. This is really helpful.
Was This Post Helpful? 0
  • +
  • -

#6 JackOfAllTrades  Icon User is offline

  • Saucy!
  • member icon

Reputation: 6066
  • View blog
  • Posts: 23,526
  • Joined: 23-August 08

Re: How to take string input in C dynamically

Posted 21 March 2010 - 09:36 AM

You're teaching someone this? In an academic setting? I thought you were IN school.
Was This Post Helpful? 0
  • +
  • -

#7 Tapas Bose  Icon User is offline

  • D.I.C Regular
  • member icon

Reputation: 23
  • View blog
  • Posts: 472
  • Joined: 09-December 09

Re: How to take string input in C dynamically

Posted 21 March 2010 - 09:42 AM

@ JackOfAllTrades, thank you. But unfortunately this code is not working well. Here is the output :
tapas@My-Child:~/Programming$ ./test9.o
Enter data: tapas bose
Entered data: tapas bose
This is okay. After Ctrl+D it is giving the output. But if I give input like
tapas tapas tapas tapas, it is giving runtime error. Here is the errors :

tapas@My-Child:~/Programming$ ./test9.o
Enter data: tapas tapas tapas tapas
Entered data: tapas tapas tapas tapas
*** glibc detected *** ./test9.o: free(): invalid next size (fast): 0x08957008 ***
======= Backtrace: =========
/lib/tls/i686/cmov/libc.so.6[0x34bff1]
/lib/tls/i686/cmov/libc.so.6[0x34d6f2]
/lib/tls/i686/cmov/libc.so.6(cfree+0x6d)[0x3507cd]
./test9.o[0x804877a]
/lib/tls/i686/cmov/libc.so.6(__libc_start_main+0xe6)[0x2f7b56]
./test9.o[0x80485c1]
======= Memory map: ========
00110000-0012c000 r-xp 00000000 08:09 5225 /lib/libgcc_s.so.1
0012c000-0012d000 r--p 0001b000 08:09 5225 /lib/libgcc_s.so.1
0012d000-0012e000 rw-p 0001c000 08:09 5225 /lib/libgcc_s.so.1
001ef000-002d5000 r-xp 00000000 08:09 5221 /usr/lib/libstdc++.so.6.0.13
002d5000-002d9000 r--p 000e6000 08:09 5221 /usr/lib/libstdc++.so.6.0.13
002d9000-002da000 rw-p 000ea000 08:09 5221 /usr/lib/libstdc++.so.6.0.13
002da000-002e1000 rw-p 00000000 00:00 0
002e1000-0041f000 r-xp 00000000 08:09 1370 /lib/tls/i686/cmov/libc-2.10.1.so
0041f000-00420000 ---p 0013e000 08:09 1370 /lib/tls/i686/cmov/libc-2.10.1.so
00420000-00422000 r--p 0013e000 08:09 1370 /lib/tls/i686/cmov/libc-2.10.1.so
00422000-00423000 rw-p 00140000 08:09 1370 /lib/tls/i686/cmov/libc-2.10.1.so
00423000-00426000 rw-p 00000000 00:00 0
004d2000-004ed000 r-xp 00000000 08:09 3953 /lib/ld-2.10.1.so
004ed000-004ee000 r--p 0001a000 08:09 3953 /lib/ld-2.10.1.so
004ee000-004ef000 rw-p 0001b000 08:09 3953 /lib/ld-2.10.1.so
00935000-00959000 r-xp 00000000 08:09 1396 /lib/tls/i686/cmov/libm-2.10.1.so
00959000-0095a000 r--p 00023000 08:09 1396 /lib/tls/i686/cmov/libm-2.10.1.so
0095a000-0095b000 rw-p 00024000 08:09 1396 /lib/tls/i686/cmov/libm-2.10.1.so
00d94000-00d95000 r-xp 00000000 00:00 0 [vdso]
08048000-08049000 r-xp 00000000 08:0a 20260 /home/tapas/Programming/test9.o
08049000-0804a000 r--p 00000000 08:0a 20260 /home/tapas/Programming/test9.o
0804a000-0804b000 rw-p 00001000 08:0a 20260 /home/tapas/Programming/test9.o
08957000-08978000 rw-p 00000000 00:00 0 [heap]
b7600000-b7621000 rw-p 00000000 00:00 0
b7621000-b7700000 ---p 00000000 00:00 0
b7773000-b7775000 rw-p 00000000 00:00 0
b7791000-b7795000 rw-p 00000000 00:00 0
bf7ec000-bf801000 rw-p 00000000 00:00 0 [stack]
Aborted

View PostJackOfAllTrades, on 21 March 2010 - 09:06 PM, said:

You're teaching someone this? In an academic setting? I thought you were IN school.

Yes sir, I am student now, perusing MCA (Masters Of Computer Application). Beside this I am a private tutor. Teach mathematics and programming in graduation level. :)

This post has been edited by Tapas Bose: 21 March 2010 - 09:42 AM

Was This Post Helpful? 0
  • +
  • -

#8 JackOfAllTrades  Icon User is offline

  • Saucy!
  • member icon

Reputation: 6066
  • View blog
  • Posts: 23,526
  • Joined: 23-August 08

Re: How to take string input in C dynamically

Posted 21 March 2010 - 09:53 AM

OUCH...I failed...will be back :(

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

int main()
{
    /* A temporary buffer for holding data from stdin.
     
       NOTE: this 16 should really be BUFSIZ, a constant from stdio.h
       but I intentionally made the buffer smaller as a demonstration. */
    char buf[16] = { 0 };

    /* A pointer to all of the data entered, and a temp for reallocation
       as we receive more data. */
    char *enteredData = NULL, *temp = NULL;

    /* A boolean as to whether we've written anything into our entered data. */
    int dataWritten = 0;

    printf("Enter data: ");

    /* We will continue reading data from the stdin buffer 
       until the stream has been closed via Ctrl-D or Ctrl-Z */
    while (fgets(buf, sizeof(buf), stdin) != NULL)
    {
        /* The length of the data actually input in this fgets call */
        size_t len = strlen(buf);

        /* If we've already created our dynamic buffer, we will re-allocate
           that buffer here; otherwise we will allocate the initial buffer
           with malloc.

           We use a temporary pointer in the event that realloc fails; if
           this happens we won't lose the data already allocated and can
           free that up, although in this minimal program that's not a big
           deal. */
        if (enteredData)
        {
            /* Re-allocate with enough size for the new data. */
            temp = realloc(enteredData, strlen(enteredData) + len + 1);
        }
        else
        {
            /* Allocate a new memory block for writing our buffered data. */
            temp = malloc(len + 1);
        }

        /* If the allocation failed, and we've already allocated memory
           then free the old memory and exit. */
        if (!temp)
        {
            if (enteredData)
                free(enteredData);
            return -1;
        }

        /* Set the pointer to point to our newly-allocated memory. */
        enteredData = temp;

        /* If the last non-null char is NOT a new line,
           there's more in the stdin buffer to be read                         
           that won't fit in our fgets buffer;                                  
           otherwise remove the newline that fgets leaves in
           the stream. */
        if (buf[len - 1] == '\n')
        {
            /* Remove newline */
            buf[len - 1] = 0;
        }

        if (dataWritten)
        {
            /* If we've already written data to the our dynamic memory, then
               we will concatenate the new data to it from the buffer. */
            strcat(enteredData, buf);
        }
        else
        {
            /* Copy the buffer to our newly-allocated memory. */
            strcpy(enteredData, buf);

            /* Set the boolean that we've already written to memory. */
            dataWritten = 1;
        }
    }

    /* If we've actually read any data from stdin, then write it out
       and free the dynamically-allocated memory. */
    if (enteredData)
    {
        printf("Entered data: %s\n", enteredData);
        free(enteredData);
    }


    return 0;
}


OK, that should be better.

This post has been edited by JackOfAllTrades: 21 March 2010 - 02:07 PM
Reason for edit:: Fixed code.

Was This Post Helpful? 1
  • +
  • -

#9 Tapas Bose  Icon User is offline

  • D.I.C Regular
  • member icon

Reputation: 23
  • View blog
  • Posts: 472
  • Joined: 09-December 09

Re: How to take string input in C dynamically

Posted 21 March 2010 - 09:56 AM

View PostJackOfAllTrades, on 21 March 2010 - 09:23 PM, said:

OUCH...I failed...will back :(

Its okay sir. :)

This post has been edited by Tapas Bose: 21 March 2010 - 09:56 AM

Was This Post Helpful? 0
  • +
  • -

#10 Tapas Bose  Icon User is offline

  • D.I.C Regular
  • member icon

Reputation: 23
  • View blog
  • Posts: 472
  • Joined: 09-December 09

Re: How to take string input in C dynamically

Posted 21 March 2010 - 10:20 AM

View PostJackOfAllTrades, on 21 March 2010 - 09:23 PM, said:

OK, that should be better.

Not better its perfect. Thank you very much sir. :)

So here Ctrl+D defines NULL sir?

Can you please explain this code sir?
Was This Post Helpful? 0
  • +
  • -

#11 JackOfAllTrades  Icon User is offline

  • Saucy!
  • member icon

Reputation: 6066
  • View blog
  • Posts: 23,526
  • Joined: 23-August 08

Re: How to take string input in C dynamically

Posted 21 March 2010 - 02:08 PM

I commented the code to explain more. Note that this isn't particularly optimized, but is just meant to serve as an example of what was asked in the subject of this topic.
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1