0

Can someone please let me know why one can't take an input in arrays of pointer to strings using input stream as in the following code:

char *names[5];

for(int i=0; i<5; i++)
{
cout<<"enter name "<<i+1;   
cin>>names[i];  
}
6
  • What's ptr? How, if at all, is it related to names? Commented Apr 1, 2017 at 20:55
  • sorry @IgorTandetnik my bad. just edited it, would be great if you could have a look now.. Commented Apr 1, 2017 at 20:57
  • cin>>names[i] expects names[i] to be a valid pointer, pointing to a sufficiently large array of characters where the input can be stored. But in your example, names[i] is an uninitialized pointer containing random garbage. The example exhibits undefined behavior, by way of accessing uninitialized object. Commented Apr 1, 2017 at 20:58
  • Does it have to be a char * ? You might forget to allocate the buffer, forget to delete the buffer or the buffer might not be long enough. Is std::string not an option? Commented Apr 1, 2017 at 21:05
  • could you please edit this code to perfection, which takes 5 names as input to the array of pointer strings. I tried it with allocating the memory to the array dynamically, doesn't seem to work even then.. Commented Apr 1, 2017 at 21:07

2 Answers 2

1

The variable "names" is an undefined array of char pointers. That's your first problem. The pointers are undefined and have no memory allocated for them. In your original code example there are five char pointers with undefined values. This is why the program would crash, because it's trying to access memory of the invalid address in the pointers. Another problem is that there is no memory allocated to hold the array of chars coming in from stdin.

You could do something like this to get your original example working without crash:

#include <iostream>
#include <string.h>

using namespace std;

int main(int argc, char** argv)
{
    char names[5][128];
    memset(names, 0, sizeof(names));

    for (int i = 0 ; i < 5 ; i++ )
    {
        cout << "enter name " << i+1 << ": ";   
        cin >> names[i];  
    }

    for (int i = 0 ; i < 5 ; i++ )
    {
        cout << names[i] << "\n";   
    }
}

This allocates an array of 5 128 character strings. It also clears the arrays with the memset() as well.

Since this is C++ it would seem to make more sense to do it C++ style.

#include <iostream>
#include <string>
#include <vector>

using namespace std;

const int NUM_NAMES = 5;

int main(int argc, char** argv)
{
    vector<string> names;
    names.resize(NUM_NAMES);

    for (int i = 0 ; i < NUM_NAMES ; i++ )
    {
        cout << "enter name " << i+1 << ": ";   
        cin >> names[i];  
    }

    for (int i = 0 ; i < NUM_NAMES ; i++ )
    {
        cout << names[i] << "\n";   
    }
}
Sign up to request clarification or add additional context in comments.

5 Comments

thanks for the alternatives, but does that mean that with my variant, the problem being the allocation of the memory, the array of pointers cannot be taken input into at the runtime? And if that's so, what if we allocate the memory dynamically to the array pointers? @MrJLP
Caveat on the first option. cin >> names[i];. >> has no clue how bit the array is and will gleefully write off the end of the array if given enough input. getline or get may be safer choices and have the added advantage of handling names like "Von Doom".
Yes you could dynamically allocate memory each time in the iteration. In the first C style example the memory is allocated on the stack. In the second C++ example the strings are contained by a vector. The vector.resize() is what creates 5 new strings. When the vector "names" goes out of scope it will automatically delete the string instances in it.
@user4581301 Yes, that's a valid problem. I just got the original code example working without crashing. A well written program would have ways to prevent user input from exceeding the bounds any fixed length buffers.
@mwbee Does this answer explain the problem you had in your original code?
0

Disclaimer: using char* for reading from std::cin is generally a bad idea and I suggest you learn how to use std::string in future.

Also this question would have been better suited for codereview.SE but I'll ignore that for now.

Here is an example of doing what you want to do, but I strongly insist you avoid doing it in any real code.

char * names[5];

// Allocate names
for (int i = 0; i < 5; i++)
{
    // Use 256 characters as a buffer
    // any names longer than that might cause errors
    names[i] = new char[256];
}

// Do IO
for (int i = 0; i<5; i++)
{
    // Append std::endl
    std::cout << "enter name " << i + 1 << std::endl;
    // This isn't very robust since the user can give anything as a name,
    // and they can't use spaces because of how cin works in this example.
    std::cin >> names[i];
}

// Use names
for (int i = 0; i < 5; i++)
{
    // Printing names is just an example
    // you could write the names to somewhere more important
    // you could copy them to a smaller location to use less memory
    std::cout << names[i] << std::endl;
}

// Dispose of names when done
for (int i = 0; i < 5; i++)
{
    // Check pointer isn't null
    if (names[i] != nullptr)
    {
        // Never forget to delete
        delete names[i];
    }
}

2 Comments

if we hardcode the length of the array, there is no point in using pointers as for this matter. So could I conclude that there is no way we could 'stdin' to take input in array pointers b/c there is no memory allocated for it since these pointers will just store addresses somewhere in the memory and later point to the data input. P.S I was just working on with some questions related to the working of working of pointers, hence couldn't use either strings or multidimensional arrays. TIA
@mwbee The example you gave had a hardcoded array length, I am merely adapting the code you presented. I'm not sure what the rest of your comment is supposed to be saying. The pointers aren't redirected to point to the input, the data input is copied into the block of memory that the pointers are pointing to.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.