tags:

views:

304

answers:

11

I have a the following code:

#include <iostream>
using namespace std;

void func(char * aString)
{
    char * tmpStr= new char[100];
    cin.getline(tmpStr,100);
    delete [] aString;
    aString = tmpStr;
}

int main()
{
    char * str= new char[100];
    cin.getline(str,100);
    cout<< str <<endl;
    func(str);
    cout<< str <<endl;
    return 0;
}

Why the second cout does not print the second imputed string? How can I change this code to work it?

A: 

assignment to the parameter aString within the function has no effect on str in main()

you might try

    return aString 

and in main

    str = funct(str);

But in fact there's probably no reason to pass str into the function.

djna
A: 

The line aString = tmpStr just changes the value of astring (i.e. an adress/pointer) to another value (i.e. another adress/pointer), but not the content of the momory pointed to by aString.

You could try to change the signature to:

void func(char ** aString)

And changing the last two lines of func to:

delete [] *aString;
*aString = tmpStr;

So the last line causes the program to change the adress stored in the memory pointed to by aString to the adress newly allocated (tmpStr). (I know, it's mind-boggling.)

And then call it via

func(&str);
phimuemue
Do you mean that aString is a copy of str?
Narek
He means that the pointer `aString` in your function is a copy of the pointer `str` in your `main`. A `char *` is not a string, but it may point to a string.
Space_C0wb0y
A: 

You need to pass str as a reference.

Duracell
+6  A: 

Because the second cout will print what is pointed by str. And str, the pointer, in your main function will have the same value before and after the call to func.

Indeed, in the func function, you are changing the value of the aString variable. But this is another variable than str in main.

If you want the value of str to be changed, you have to pass it to func by reference or by pointer. (Note that what you write, is to pass the characters by pointer. I mean you have to pass the pointer by pointer: void func(char **str_ptr), or by reference void func(char *&str_ref))

If you're really doing C++, you should use std::string instead of the old C strings.

An example of passing the pointer by pointer:

func(char ** aString)
{
    char * tmpStr= new char[100];
    cin.getline(tmpStr,100);
    delete [] *aString;
    *aString = tmpStr;
}

Plus you should call it like this: func(&str);

Didier Trosset
If I pass like this: void func(char **str_ptr) how I should implement "func" then?
Narek
+1  A: 

If your aim is to actually read a line from the keyboard, do this:

std::string foo;

std::getline(std::cin, foo);

Otherwise, when you pass a pointer to a function, the pointer is passed by value. This means you cannot change the pointer itself from within the function, but you can change the object it points to. In C++ you could do this as follows:

void bar(std::string & s) {
    std::getline(std::cin, s);
}

// in calling code
    std::string foo;

    bar(foo);

This passes a reference to the string to the function. The function can now change the contents of the string.

If you want to write a function that allocates some memory to store a result in, do it like this:

boost::shared_array<char> foo() {
    boost::shared_array<char> result(new char[100]);
    std::cin.getline(result.get(), 100);
    return result;
}
Space_C0wb0y
`std::cin >> foo;` won't read a line; it'll stop at the first space. You want `std::getline(std::cin, foo);` for that.
Mike Seymour
Thanks, fixed that.
Space_C0wb0y
Also, that should be `shared_array`, not `shared_ptr`, to get the correct deleter.
Mike Seymour
Fixed again - been doing too much Python lately.
Space_C0wb0y
+2  A: 

When func() is called from main() the value of str pointer is passed to the function (this is done by copying it's value to the stack)

The value that was stored on stack when calling func() becomes a local variable aString within func(). You can modify this value but as soon as func() returns all of it's local variables will be discarded. Value of aString won't be copied back to str.

For your code to work you have to either:

  • Use the buffer pointed to by aString to read data: cin.getline(aString ,100); or
  • Pass pointer to pointer: void func(char **aString)
Michał Piaskowski
maxwellb
+2  A: 

Change func to

void func(char * aString) { cin.getline(aString,100); }

and it works, at least it did for me.

Silvae
+1 All the reference/pointer stuff is beside the point. There's no need to create a separate buffer just to assign the results of getline, if all you're doing is copying those results back to the original buffer. Just pass your first buffer into getline. In fact, you really don't need a separate function just to call getline.
John M Gant
(Though you should be using std::string, of course, like everybody else has pointed out.)
John M Gant
+12  A: 

As GregS has said, the simplistic answer is to declare your function using a reference:

void func(char *&aString)

However it is not really the best solution. In C++ you generally avoid simple arrays and use containers.

#include <iostream>
#include <string>

void func(std::string &s)
{
    std::getline(std::cin, s);
}

int main()
{
    std::string str;
    func(str);
    std::cout << str << std::endl;
    return 0;
}
Michael J
+1: There's no reason to use a char* or char[] in C++. That is what std::string is for.
DeadMG
This is a common trip-up I've seen. If only the strem's getline method took a string in the first place!
Owen S.
@Owen S - The way it is designed the streams don't depend on the string. That has its benefits from a design point of view. However it does make it a little harder when teaching beginners. Such is life :-)
Michael J
It's the single most frustrating thing about the standard C++ libraries if you ask me. Show me another OO language where the I/O library holds string objects at arm's length like this! Bleah. :-)
Owen S.
A: 
#include <iostream>

void func(std::istream& is, std::string& aString)
{
    std::getline(is, aString);
}

int main()
{
    std::string str;
    std::getline(std::cin, str);
    if(std::cin)
        std::cout<< str << '\n';
    std::string str;
    func(std::cin, str);
    if(std::cin)
        std::cout<< str << '\n';
    return 0;
}
sbi
+1  A: 

The pointer is passed by value. Yes, you can change the content of what that pointer points to, but the old address itself is preserved when you exit the function. Hence, "aString=tmpStr"; becomes useless and "char * tmpStr= new char[100];" creates a memory leak. You need to pass the pointer by reference:

void func(char*& aString)
{
    char * tmpStr= new char[100];
    cin.getline(tmpStr,100);
    delete [] aString;
    aString = tmpStr;
}
blue scorpion
A: 

The pointer aString which you pass to func() indicates where (at which address) you can read and write the string str. When you then say aString = tempStr, you're replacing its original value (the address of the string pointed to by str) with a new value (the address of the string pointed to by tempStr). This will not cause str to point to the same place as tempStr.

Imagine I give you a piece of paper with my friend's home address it. Then you scratch it out and write the address of your brother (who lives in London) on it. If I then decide to visit my friend, I won't find myself traveling to London, even though you may have a piece of paper that says "Paul's friend: 123 London".

To get main to print out the string you entered in func(), you can either copy the input string to aString (you move your brother to my friend's house), or pass a pointer or reference to str (have me give you my address book, so you can change the entry for my friend to London). Either way, next time I visit "my friend's house", your brother will be there.

Paul Richter