0

The problem is that I would like to allocate memory dynamically according to the size of user's input.Please note that the user does not specify the size of input. We have to calculate how long it was, and then only allocate the exact amount of memory for it.What I'm looking for is something like this:

char* input_str = NULL; // No initial size whatsoever
cout<<"\nEnter the string: ";
//Determine how long the string entered was, and allocate memory for it
//make input_str point to it. 

May be this can help us write our version of std::string ?

Manjunath Reddy
  • 935
  • 7
  • 10
  • 1
    if you are stuck with char type, you may look at a more C-ish solution : http://stackoverflow.com/a/8164021/420446 – willll Apr 16 '15 at 12:53

4 Answers4

8

Just use a std::string, which does all of this for you:

std::cout << "\nEnter the string: ";

std::string input;

// To get a word:
std::cin >> input;

// To get a line of input:
std::getline(std::cin, input);

You won't need to worry about memory allocation at all.

Internally, these functions will call std::cin.rdbuf() to get access to the underlying stream buffer and read character by character until the stopping condition is met. As it does this, it grows some internal storage than it (de)allocates with new[] and delete[].

An alternative simple (but limited and potentially dangerous) approach you might use, is to allocate a buffer that is as large as you're ever going to need (something like new char[100] and read the input into it (with something like std::cin.read or std::cin.getline, etc.). Then you can determine how many characters were inserted into the buffer, allocate some storage of the correct size, transfer your input into this storage, and then deallocate the old buffer. With this approach, you have to be extra careful to avoid buffer overflows which may introduce security vulnerabilities to your program, and you are of course limited to a particular maximum input size.

Joseph Mansfield
  • 108,238
  • 20
  • 242
  • 324
3

As I understand the question, in particular the “May be this can help us write our version of std::string ”, it's about

  • doing what std::getline from the <string> header does, to see what that involves.

That's already discussed in a good way by Bjarne Stroustrup in his paper “Learning Standard C++ as a New Language”, except that Bjarne discusses input via the >> operator, which only inputs a single whitespace-delimited word.

Bjarne starts with pseudo-code for a hypothetical student's exercise:

write a prompt "Please enter your first name"
read the name
write out "Hello <name>"

He then presents one possible C++ solution:

#include<iostream>      // get standard I/O facilities
#include<string>        // get standard string facilities

int  main()
{
    using namespace std;    // gain access to standard library

    cout << "Please enter your first name:\n";
    string name;
    cin >> name;
    cout << "Hello " << name << '\n';
}

And after some discussion he presents a C style solution, a DIY C style program to do just about the same as the C++ style solution:

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

void quit()  // write error message and quit
{
    fprintf(stderr," memory exhausted\n") ;
    exit(1) ;
}

int main()
{
    int  max = 20;
    char* name = (char*) malloc(max) ;  // allocate buffer
    if (name == 0) quit();
    printf("Please enter your first name:\n");
    while (true) {  // skip leading whitespace
        int c = getchar();
        if (c ==  EOF) break;  // end of file
        if (!isspace(c)) {
            ungetc(c,stdin);
            break;
        }
    }
    int i = 0;
    while (true) {
        int c = getchar() ;
        if (c == '\n' || c ==  EOF) {  // at end; add terminating zero
            name[i] = 0;
            break;
        }
        name[i] = c;
        if (i== max-1) {  // buffer full
            max =  max+max;
            name = (char*)realloc(name, max) ; // get a new and larger buffer
            if (name == 0) quit() ;
        }
        i++;
    }
    printf("Hello %s\n",name);
    free(name) ;  // release memory
    return 0;
}

The two programs are not exactly equivalent: the C++ style first program only reads a single “word” of input, while the C program skips whitespace and then reads a complete line of input. But it illustrates what's involved for doing this yourself. In short, better use C++ style. ;-)

Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331
  • The C version's ability to use realloc is a (nearly fundamental? Due to deficiencies of the C++ allocator model) performance edge that the C++ version lacks. – Yakk - Adam Nevraumont Apr 16 '15 at 13:28
  • @Yakk: Yes. As I recall Howard Hinnant did some experimentation with using `realloc` for a `std::vector` implementation. Might have been someone else though. The upshot: you can't get that formally correct, but you do improve efficiency a lot. ;-) – Cheers and hth. - Alf Apr 16 '15 at 13:29
  • Good job actually noticing that the asker mentioned implementing their own `std::string` in their question. – Joseph Mansfield Apr 16 '15 at 16:39
2

Allocate an array with space for 1 or more characters. Read characters from your input source into the array until the array runs out of space, or you reach your terminating character. If you ran out of space, allocate a new array twice the size, copy the characters over, and deallocate the old array. Then go back to reading characters again. Repeat until you reach your terminating character (or whatever other condition you want to stop at).

Benjamin Lindley
  • 101,917
  • 9
  • 204
  • 274
  • This answer is the only one that, once it gets past the `std::string` solution, describes a correct way to read an unknown stream of characters into memory. The only addition (if you want industrial-quality) is to maybe have a "max length" parameter (in the megabytes) to deal with the possibility of someone trying to exhaust your memory space and cause unexpected shutdown, and/or switching to segmented strings (which deal with extremely large strings much better than contiguous strings). But that is beyond the scope of this problem. – Yakk - Adam Nevraumont Apr 16 '15 at 13:26
0

You need to either store the whole user string in a temporary buffer with a max size, or read the input character by character.

Note that since you are using C++, it probably doesn't make any sense to allocate the memory manually: you could use std::string instead.

Lundin
  • 195,001
  • 40
  • 254
  • 396