Passing Pointers

B

BlindHorse

Help!!!

I need someone to tell me why I am getting the err msg

error C2440: '=' : cannot convert from 'char *' to 'char'



//====================
#include <iostream>
using namespace std;

char *Input();
void Output(char *);

//====================
void main()
{

char *iptr = new char [100];
*iptr = Input();
Output(iptr);

delete [] iptr;

}

//====================

char *Input(void)
{

char *name = new char [100];
cout << "Enter name: ";
cin >> *name;
return name;

}

//====================

void Output(char *input)
{
cout << *input;
cout << endl;
}
 
J

Julie

BlindHorse said:
Help!!!

I need someone to tell me why I am getting the err msg

error C2440: '=' : cannot convert from 'char *' to 'char'

//====================
#include <iostream>
using namespace std;

char *Input();
void Output(char *);

//====================
void main()
{

char *iptr = new char [100];
*iptr = Input();
Output(iptr);

delete [] iptr;

}

//====================

char *Input(void)
{

char *name = new char [100];
cout << "Enter name: ";
cin >> *name;
return name;

}

//====================

void Output(char *input)
{
cout << *input;
cout << endl;
}


Change:
*iptr = Input();

to:
iptr = Input();

and you should be good to go. You don't need to dereference the destination
iptr to char.

Also, you don't need to allocate:

char *iptr = new char [100];

Replace with

char *iptr = NULL;

otherwise you will leak memory when you do the (pointer) assignment to iptr.
 
L

Leor Zolman

Help!!!

I need someone to tell me why I am getting the err msg

error C2440: '=' : cannot convert from 'char *' to 'char'

Before we get started:
char c; // one character
char *cp = "abc"; // a pointer to characters (the 'a' initially)
c = *cp; // copy the 'a' into c
c = cp; // type mismatch: can't copy a pointer into a char
*cp = "abc"; // type mismatch: can't copy a pointer into a char
*cp = 'a'; // ok.

Now, then:
//====================
#include <iostream>
using namespace std;

char *Input();
void Output(char *);

//====================
void main()

int main()
{

char *iptr = new char [100];

You won't be needing that dynamic memory above, so just do:
char *iptr;
*iptr = Input();

Above, you're trying to force a pointer (returned by Input()) into a
character (the type of the expression *iptr). What you want is:

iptr = Input();

And now you know why you didn't want to allocate that 100 char array above:
you'd be leaking it now if you did.
Output(iptr);

delete [] iptr;

those are ok. Note the memory you're deleting was allocated within Input().
That's fine; just be aware of it.

And add, as good style:

return 0;
}

//====================

char *Input(void)
{

char *name = new char [100];

OK, so name now points to a dynamically allocated array of chars.
cout << "Enter name: ";
cin >> *name;

Lose the '*', because the way you wrote it, you're saying to read a single
character from cin and stuff it into the first location of that 100 char
array. without the *:
cin >> name;
you'll read text from cin until you encounter the first white space, and
store it in the memory pointed to by name....even if the input is more than
100 chars (which would have undefined behavior. It could then proceed to
erase your hard disk and be within its rights.) If you want to read white
space as part of that input string, as well as make sure you don't overrun
the buffer, look into various forms of getline, e.g.:

cin.getline(name, 100);
return name;

OK, now it is up to the caller to delete that memory.
}

//====================

void Output(char *input)
{
cout << *input;

Again, lose the *, or you'll be displaying a single character.
cout << endl;
}

HTH,
-leor


Leor Zolman
BD Software
(e-mail address removed)
www.bdsoft.com -- On-Site Training in C/C++, Java, Perl & Unix
C++ users: Download BD Software's free STL Error Message
Decryptor at www.bdsoft.com/tools/stlfilt.html
 
A

Alf P. Steinbach

* (e-mail address removed) (BlindHorse) schriebt:
I need someone to tell me why I am getting the err msg

error C2440: '=' : cannot convert from 'char *' to 'char'


Uhum. There are more serious problems than that in the code.

//====================
#include <iostream>
using namespace std;

char *Input();

Here is one big problem: who is responsible for deallocating the
memory returned by function 'Input'?

That problem leads to directly to a memory leak in your program,
discussed below.

Instead of 'char*', I suggest you make the return type 'std::string'.


void Output(char *);

Here there's a problem in usage. It's only by the good grace of
old C compatibility that this 'Output' function can be used with
a literal string as an argument, because the argument type says
that 'Output' is free to change the string. Instead use e.g.
'char const []' as argument type.


//====================
void main()

This is not allowed by the standard.

Function 'main' must have return type 'int'.

Nothing else.


{

char *iptr = new char [100];
*iptr = Input();

The basic misunderstanding seems to be that you're thinking in
terms of assigning an array, complete, whereas what the code
attempts to do is to assign a pointer.

'*iptr' does not refer to the 100 character array you've just
allocated, as you might think.

Instead, since 'iptr' is a pointer to 'char', '*iptr' is a single
'char'.

Namely, the first character in that array.


Figure.

Draw one box representing the 'iptr' variable.
Draw one hundred small boxes representing the array.
Draw an arrow from within 'iptr' to the first array element.

The compiler only uses what the arrow points directly at.

It doesn't know or care that there's 99 elements further on.


So you're trying to assign the result of function 'Input', which is
a pointer to char, to a single char.

The compiler won't have any of that unless you force it to.

Output(iptr);

delete [] iptr;

}



You can make this _compile_ by removing the dereferencing:


char *iptr = new char [100];
iptr = Input();
Output(iptr);

delete [] iptr;


But then the assignment replaces the address of the one hundred bytes
you allocated.

Then you don't have that address available any longer for deallocation.

And the 'delete' will just deallocate the array allocated by 'Input'.

So here you have the memory leak mentioned earlier on.


//====================

char *Input(void)

Style: 'void' for argument list is a C'ism best a-voided in C++.

{

char *name = new char [100];
cout << "Enter name: ";
cin >> *name;
return name;

}

//====================

void Output(char *input)
{
cout << *input;
cout << endl;
}


Many of the problems will go away simply by using 'std::string'
instead of 'char*'.

The function signatures would then be:


std::string Input();
void Output( std::string const& );


And you then need to #include <string> at the top of the program.

Hth.
 
M

Mike Wahler

BlindHorse said:
Help!!!

I need someone to tell me why I am getting the err msg

error C2440: '=' : cannot convert from 'char *' to 'char'



//====================
#include <iostream>
using namespace std;

char *Input();
void Output(char *);

void Output(const char *);
//====================
void main()

int main()
{

char *iptr = new char [100];
*iptr = Input();

iptr = Input();
Output(iptr);

delete [] iptr;

return 0; /* not mandatory, but I consider it 'good style' */
}

//====================

char *Input(void)
{

char *name = new char [100];

Omit this line. You've already allocated the memory in 'main()'
This function receives a pointer to that memory as its argument.
cout << "Enter name: ";
cin >> *name;

cin >> name;

but this is dangerous, as it does not protect against the user
entering more characters than you've allocated memory for.

Consider dropping the manual memory management and use
a std::string object instead, which handles all that for you.
return name;

}

//====================

void Output(char *input)
{
cout << *input;

cout << input << '\n';
cout << endl;
}

Contrast:

#include <iostream>
using std::cin;
using std::cout;

#include <string>
using std::string;
using std::getline;


/* now we don't need a return type, since we're passing
an argument by reference, the function can modify
the passed object 'in place' */
void Input(string& s)
{
cout << "Enter name: ";
getline(cin, s); /* the string will automatically
size itself as necessary */
}


/* Notice that here the parameter is declared 'const'
since this function does not modify it. This
is a 'safety net' the language gives you for free.
An attempt to modify 's' will produce a compile error */
void Output(const std::string& s)
{
cout << s << '\n';
}

int main()
{
string my_str; /* an empty string */
Input(my_str);
Output(my_str);
return 0;
} /* memory for 'my_str' is automatically released when the
function ends */


/* Note how the way I've ordered the functions obviates
the need for prototypes */


No need to muck around with pointers.

C++ has many features which make life easier and 'safer' for the
programmer. Use 'em. :)

-Mike
 
P

Paavo P

Mike Wahler said:
No need to muck around with pointers.

C++ has many features which make life easier and 'safer' for the
programmer. Use 'em. :)

-Mike

I have similar problem and I cannot get over it because it is exercise with
preconditions (why c++ books has pure c exercises?!)

I guess Horse the Blind is also doing some exercise..;)
 
M

Mike Wahler

Paavo P said:
I have similar problem

What problem exactly?
and I cannot get over it because it is exercise with
preconditions

What's wrong with preconditions? They create a 'formal'
context which helps keep your code correct.
(why c++ books has pure c exercises?!)

There are far more bad C++ books available than good ones.
Perhaps you need better ones. Take a look at the reviews
at www.accu.org

-Mike
 
P

Paavo P

Here's my prob:

function:

char* cat(char* a,char* b){

int size=(strlen(a)+strlen(b)+1);

char* ab=new char[size]; //reserve space with new-operator is in
preconditions
char* x=NULL;

while(*x++=*a++);
cout << "catC 1" << ab <<'\n';
*x--;
while(*x++=*b++);
cout << "catC 2" << ab <<'\n';

*ab=&x[0];
return ab; //return the result is in preconditions

} // end function cat

and the caller:
int main( int argc, char *argv[] )
{

char text1[]="Hallo";
char text2[]="Spaceboy";
char* madcat=NULL;
madcat=cat(text1,text2);

cout << "String " << text1 << " and string " << text2 << '\n';
cout << "" are concatenated as " << madcat <<'\n';

return( EXIT_SUCCESS );

} // end main

I followed the instructions but I cannot get it
 
P

Paavo P

See msg belower inthe thread.
What problem exactly?


What's wrong with preconditions? They create a 'formal'
context which helps keep your code correct.


There are far more bad C++ books available than good ones.
Perhaps you need better ones. Take a look at the reviews
at www.accu.org

-Mike

It was preconditions set by teacher (in this case it was the writer). This
exercise was 6.6.13 of Stroustrup's second edition.
 
M

Mike Wahler

Paavo P said:
Here's my prob:

Where are the headers?
function:

char* cat(char* a,char* b){

int size=(strlen(a)+strlen(b)+1);

Use type 'size_t' for sizes. It's declared by <cstdlib>
char* ab=new char[size]; //reserve space with new-operator is in
preconditions

That's not a 'precondition', but a specification.
char* x=NULL;

while(*x++=*a++);

This produces undefined behavior, because you're dereferencing
a NULL pointer ('x').
cout << "catC 1" << ab <<'\n';

More undefined behavior. 'cout's 'operator<<()' for type char*
will dereference that pointer. But that pointer points to
memory which has never been initialized or given a value.

More undefined behavior. Also, leaving that aside, you
have provided no protection against 'x' running off the
beginning of the array with that decrement.
while(*x++=*b++);

Yet MORE undefined behavior. 'x' still does not point
to memory with a valid value.
cout << "catC 2" << ab <<'\n';

More undefined behavior. 'ab' still doesn't point to anything
with a valid value.
*ab=&x[0];

And again. Twice in one statement.
return ab; //return the result is in preconditions

That's a specification, not a precondition.
} // end function cat

and the caller:
int main( int argc, char *argv[] )
{

char text1[]="Hallo";
char text2[]="Spaceboy";
char* madcat=NULL;
madcat=cat(text1,text2);

cout << "String " << text1 << " and string " << text2 << '\n';
cout << "" are concatenated as " << madcat <<'\n';

return( EXIT_SUCCESS );

} // end main

I followed the instructions but I cannot get it

Well, you either did *not* follow instructions, or
your instructions were very poor. Perhaps you could
post the exact instructions you were given.

What you've posted here will not even compile, let alone work.

Also, if this is exercise is supposed to be teaching you C++,
it's a very poor way to do so. You shouldn't be
being taught to do all this low level memory management
(at least not until much later), but to use the standard
library for string handling. It looks like your instructor
and/or book cannot seem to distinguish C from C++.

-Mike
 
P

Paavo P

Mike Wahler said:
Well, you either did *not* follow instructions, or
your instructions were very poor. Perhaps you could
post the exact instructions you were given.

What you've posted here will not even compile, let alone work.

I followed instructions, but it wouldn't work so I just tried everything
till got totally lost:/
Also, if this is exercise is supposed to be teaching you C++,
it's a very poor way to do so. You shouldn't be
being taught to do all this low level memory management
(at least not until much later), but to use the standard
library for string handling. It looks like your instructor
and/or book cannot seem to distinguish C from C++.

-Mike

I would do it this way:

first two char arrays (a and b) and then

string s;
s.append(a);
s.append(b);
cout << s <<'\n';

simple and elegant with C++ and I like it.
 
M

Mike Wahler

Paavo P said:
I followed instructions, but it wouldn't work so I just tried everything
till got totally lost:/

Will you show us these instructions?
I would do it this way:

first two char arrays (a and b) and then

string s;
s.append(a);
s.append(b);
cout << s <<'\n';

simple and elegant with C++ and I like it.

string s;
s += "Hello";
s += " world";

Hardly worth writing a function for that. :)

I always wonder, why are so many C++ books and
instructors so enamored with C-style strings,
despite the existence of the far superior
std::string type?

-Mike
 
C

Chris \( Val \)

|
|
[snip]

| > I would do it this way:
| >
| > first two char arrays (a and b) and then
| >
| > string s;
| > s.append(a);
| > s.append(b);
| > cout << s <<'\n';
| >
| > simple and elegant with C++ and I like it.
|
| string s;
| s += "Hello";
| s += " world";
|
| Hardly worth writing a function for that. :)

And if we wanted to be cute :):
std::string s( std::string( a ) + b );

| I always wonder, why are so many C++ books and
| instructors so enamored with C-style strings,
| despite the existence of the far superior
| std::string type?

Agreed :).

Cheers.
Chris Val
 
D

Default User

Paavo said:
It was preconditions set by teacher (in this case it was the writer). This
exercise was 6.6.13 of Stroustrup's second edition.

Why is the instructor not using the 3rd edition. That one is up-to-date
with the current standard.


Brian Rodenborn
 
P

Paavo P

Default User said:
Why is the instructor not using the 3rd edition. That one is up-to-date
with the current standard.


Brian Rodenborn

3rd was not available in Finnish.
 
J

John Harrison

Paavo P said:
Here's my prob:

function:

char* cat(char* a,char* b){

int size=(strlen(a)+strlen(b)+1);

char* ab=new char[size]; //reserve space with new-operator is in
preconditions

Good so far.
char* x=NULL;

while(*x++=*a++);

Well you are obviously trying to copy the memory pointed to by a to the
memory pointed to by ab using the pointer x. The problem is that you have
not made x point to the place you want to start copying from (i.e. a). Also
the 'cute' but terse syntax *x++ = *a++ is just too confusing. Try this

char* x = a;
while (*a != '\0') // while not at the end of string
{
*x = *a; // copy one char from a to x
++x; // move x on
++a; // move a on
}

john
 
B

B. v Ingen Schenau

John said:
Paavo P said:
Here's my prob:

function:

char* cat(char* a,char* b){

int size=(strlen(a)+strlen(b)+1);

char* ab=new char[size]; //reserve space with new-operator is in
preconditions

Good so far.
char* x=NULL;

while(*x++=*a++);

Well you are obviously trying to copy the memory pointed to by a to the
memory pointed to by ab using the pointer x. The problem is that you have
not made x point to the place you want to start copying from (i.e. a).

As x represents the target for the copy operation, it should be initialised
to ab.
Also the 'cute' but terse syntax *x++ = *a++ is just too confusing. Try
this

char* x = a;

Change this to
char* x = ab;
while (*a != '\0') // while not at the end of string
{
*x = *a; // copy one char from a to x
++x; // move x on
++a; // move a on
}

john

Bart v Ingen Schenau
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,164
Messages
2,570,901
Members
47,439
Latest member
elif2sghost

Latest Threads

Top