Invalid conversion from 'char' tp 'char*'

T

Tim Johansson

I'm new to C++, and tried to start making a script that will shuffle an
array. Can someone please tell me what's wrong?

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

int main () {
srand(time(0));
int array_length;
int count;
int randm;
char temp[30];
cout << "How many items in array? ";
cin >> array_length;
char items [30][array_length + 1];
for (count = 0; count <= array_length; count++) {
if (count != 0) {
cout << "\nWhat shall item " << count << " be?\n\t";
}
cin.getline (items[count], 30);
}
for (count = 0; count < array_length; count++) {
randm = rand() % array_length;
strcpy (temp[30], items[30][count]);
//ERROR
strcpy (items[30][count], items[30][randm]); //ERROR
strcpy (items[30][randm], temp[30]); //ERROR
}
return 0;
}


Can someone please tell me what is wrong? The errors I get are:
21: error: invalid conversion from 'char' to 'char*'
21: error: invalid conversion from 'char' to 'const char*'
22: error: invalid conversion from 'char' to 'char*'
22: error: invalid conversion from 'char' to 'const char*'
23: error: invalid conversion from 'char' to 'char*'
23: error: invalid conversion from 'char' to 'const char*'
 
P

Petec

Tim said:
I'm new to C++, and tried to start making a script
^^^^^^
FYI, C++ programs are not "scripts", they're programs.
that will shuffle
an array. Can someone please tell me what's wrong?
<snip>

I'm not sure what was wrong (I couldn't understand it) but here's a little
shuffle program:

int main()
{
// a vector of strings to hold the items
std::vector<std::string> items;

// get items
std::cout << "Enter items, or blank to finish:" << std::endl;
for(;;)
{
std::string item;
std::getline(std::cin, item);
if(item == "")
break;
items.push_back(item);
}


std::cout << std::endl << "Shuffled items:" << std::endl;

// use the random_shuffle algorith in <algorithm> to shuffe the sequence
std::random_shuffle(items.begin(), items.end());

// copy the shuffled vector to std::cout
std::copy(items.begin(), items.end(),
std::eek:stream_iterator<std::string>(std::cout, "\n"));
}

Also, I suggest you read the free & legal "Thinking in C++" book by Bruce
Eckel, availible at the author's website, www.mindview.net.

- Pete
 
R

Ragemare

Tim Johansson said:
I'm new to C++, and tried to start making a script that will shuffle an
array. Can someone please tell me what's wrong?

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

int main () {
srand(time(0));
int array_length;
int count;
int randm;
char temp[30];
cout << "How many items in array? ";
cin >> array_length;
char items [30][array_length + 1];
for (count = 0; count <= array_length; count++) {
if (count != 0) {
cout << "\nWhat shall item " << count << " be?\n\t";
}
cin.getline (items[count], 30);
}
for (count = 0; count < array_length; count++) {
randm = rand() % array_length;
strcpy (temp[30], items[30][count]);
//ERROR
strcpy (items[30][count], items[30][randm]); //ERROR
strcpy (items[30][randm], temp[30]); //ERROR
}
return 0;
}


Can someone please tell me what is wrong? The errors I get are:
21: error: invalid conversion from 'char' to 'char*'
21: error: invalid conversion from 'char' to 'const char*'
22: error: invalid conversion from 'char' to 'char*'
22: error: invalid conversion from 'char' to 'const char*'
23: error: invalid conversion from 'char' to 'char*'
23: error: invalid conversion from 'char' to 'const char*'

Not that I'm a expert but you appear to be trying to pass a single segment
of the array instead of all of the array, get rid of the '[30]'. Also I
don't think you can pass a two dimentional array to strcpy.
 
K

Kevin Goodsell

Tim said:
I'm new to C++, and tried to start making a script that will shuffle an
array. Can someone please tell me what's wrong?

#include <iostream.h>

This is not a standard header. Standard C++ uses <iostream>. This
suggests that you are learning from a source that is either very
outdated, inaccurate, or (most likely) both.
#include <string.h>

This is standard said:
int main () {
srand(time(0));

Where did srand() and time() come from? You haven't #included the
appropriate headers for these. Those headers are <cstdlib> and <ctime>,
respectively. Alternatively, the old deprecated versions are <stdlib.h>
and <time.h>.

If you use the first, non-deprecated versions, the functions will be in
namespace std::, and you need to account for that. So, for example, you
could do this:

std::srand(std::time(0));

Note also, that seeding the random number generator isn't always a good
idea. You are debugging your program -- consistency is good during this
phase. If you don't seed the random number generator (or seed it with
some constant value, like 7), then you'll get the same sequence of
numbers on each run, which makes debugging much easier.
int array_length;
int count;
int randm;
char temp[30];

Consider using std::strings instead of char arrays. They are safer, more
flexible, easier, and less error-prone.

Don't declare everything up front. Declare things where you use them. It
makes the code more clear, and someone reading the code does not need to
search as much for the declaration of an object.
cout << "How many items in array? ";

cout, cin, etc. are all in namespace std::, and you need to account for
this somehow. So, for example, you could use this:

std::cout << "some output" << std::endl;
std::cin >> some_var;
cin >> array_length;

What if this input operation fails? You should check for success. If it
fails, array_length will have an undefined value. Using it for anything
other than giving it a defined value would be bad.
char items [30][array_length + 1];

This is illegal. Your compiler should reject it. If it doesn't, check
the documentation about how to invoke it in standards-compliant mode.

The problem is that array sizes must be compile-time constants.
array_length + 1 is not known at compile-time.

You should also prefer standard containers to arrays. std::vector is
almost a drop-in replacement for arrays, and is more flexible and
potentially safer.

It appears that a good replacement for this would be

std::vector said:
for (count = 0; count <= array_length; count++) {

Not a major issue, but prefer pre-increment to post-increment when the
end result is the same. pre-inc may be faster, and is almost certainly
not slower, than post-inc. This probably makes no difference with
built-in types, but it's a good habit nonetheless.
if (count != 0) {
cout << "\nWhat shall item " << count << " be?\n\t";
}
cin.getline (items[count], 30);

This is wrong. What happens when 'count' is 500? The first index of
'items' only goes to 29, so you are potentially overflowing your array
bounds and invoking undefined behavior. Also, 30 may be more characters
than can fit in 'items[count]'. Basically, you reversed your indices in
the declaration (which, as I mentioned, was illegal anyway because one
of the sizes was not a compile-time constant).

After fixing all this, you still need special handling for when the line
is longer than your maximum string size.

If you used std::strings instead of char arrays, you could do this:

std::getline(items[count]);

Easier, safer, almost impossible to get wrong, not limited to some
arbitrary length.
}
for (count = 0; count < array_length; count++) {
randm = rand() % array_length;

For various reasons, this is a poor way to limit rand()'s range. The
comp.lang.c FAQ has information on this. But for simple cases, it rarely
matters much.
strcpy (temp[30], items[30][count]);

This is wrong. temp[30] doesn't exist, nor does
items[30][any_value_here]; Array bounds in C++ go from 0 to array_size-1.

Besides that, there is a type mismatch. strcpy() expects arguments of
type char* (const char* in the case of the source string), and you are
passing char. This is precisely what your error message says. You
probably wanted something like:

std::strcpy(temp, items[count]);

This assumes a few other changes in the code:

1) The std:: qualification assumes #include <cstring> instead of
#include <string.h>.

2) items[count] is only valid if you reverse the indices in the
declaration of items.

Better still, get rid of the arrays and use vectors and strings like
I've mentioned a few times:

std::string temp;
std::vector<std::string> items;

//...

// No need for special functions when dealing with
// std::string -- the normal operators work fine:
temp = vector[count];
//ERROR
strcpy (items[30][count], items[30][randm]); //ERROR
strcpy (items[30][randm], temp[30]); //ERROR

Same basic problems here.
}
return 0;
}

Finally, the standard library provide the function std::random_shuffle()
that does what you want.
Can someone please tell me what is wrong? The errors I get are:
21: error: invalid conversion from 'char' to 'char*'
21: error: invalid conversion from 'char' to 'const char*'

The errors could hardly be more clear. The function you are calling
expects char* and const char* arguments, you passed char arguments.

-Kevin
 
K

Kevin Goodsell

Ragemare said:
Not that I'm a expert but you appear to be trying to pass a single segment
of the array instead of all of the array, get rid of the '[30]'.

"Single element", not "single segment", but basically that's correct
(though there are several other problems).
Also I
don't think you can pass a two dimentional array to strcpy.

You can't pass any array (directly) to a function ever, regardless of
dimensions. Arrays aren't "first-class citizens" in C++. Any function
that appears to take (or return) an array actually takes (or returns) a
pointer.

A function may, however, take (or return) a class that contains an
array, or a reference to an array.

-Kevin
 
C

Christopher Benson-Manica

Tim Johansson said:
#include <iostream.h>

It's called said:
#include <string.h>
int main () {
srand(time(0));
int array_length;
int count;
int randm;
char temp[30];
cout << "How many items in array? ";
cin >> array_length;
char items [30][array_length + 1];
^^^^^^^^^^^^
I assume this is legal in C++, but I'd love it if a real C++ person
stated something authoratative. As an aside, if you're making the
array array_length+1 items long, then array_length isn't really, is
it?
for (count = 0; count <= array_length; count++) {
if (count != 0) {
cout << "\nWhat shall item " << count << " be?\n\t";
}
cin.getline (items[count], 30);
^^
Why not lose the magic number? Your code looks like C, so why not
keep the theme going and use

cin.getline( items[count], sizeof(items)/sizeof(*items) );

? That way if you change the number of items, you don't have to
remember to change the call to getline.
}
for (count = 0; count < array_length; count++) {
randm = rand() % array_length;
strcpy (temp[30], items[30][count]);

Here's the problem (well, besides that you're using C-style strings at
all): strcpy is prototyped as

char *strcpy( char *s, const char *t );

What is temp[30]? It's a char, of course. And what is
items[30][count]? It's a char, too. No wonder it doesn't compile,
eh?

And any particular reason you're ignoring the last string in items? If you
had made array_length the actual length of the array, you'd be fine (in this
snippet, at least), but you didn't.
strcpy (items[30][count], items[30][randm]); //ERROR
strcpy (items[30][randm], temp[30]); //ERROR
}
return 0;
}

Either read a C book or learn how to use std::strings and std::vectors
- I recommend the latter.
 
P

Petec

Christopher said:
Tim Johansson <[email protected]> spoke thus:
cin >> array_length;
char items [30][array_length + 1];
^^^^^^^^^^^^
I assume this is legal in C++, but I'd love it if a real C++ person
stated something authoratative. <snip>

Nope, it's not legal. You'd either have to use arrays dynamically allocced
with new, or std::vectors or another appropriate standard container.

- Pete
 
C

Christopher Benson-Manica

Petec said:
Nope, it's not legal. You'd either have to use arrays dynamically allocced
with new, or std::vectors or another appropriate standard container.

Well, that's what *I* would have done, but I didn't want to say "NO!"
and then have to wipe more egg off my face than usual :)
 
K

Kevin Goodsell

Christopher said:
It's called <iostream> - the .h headers are deprecated.

It's true that those headers which are part of the standard and which
end in .h are deprecated, but <iostream.h> is not even part of the
standard, therefore cannot be deprecated.

-Kevin
 
C

Christopher Benson-Manica

Kevin Goodsell said:
It's true that those headers which are part of the standard and which
end in .h are deprecated, but <iostream.h> is not even part of the
standard, therefore cannot be deprecated.

Clearly my answer was deprecated - sorry :)
 
J

Jack Klein

Tim Johansson said:
#include <iostream.h>

It's called said:
#include <string.h>
int main () {
srand(time(0));
int array_length;
int count;
int randm;
char temp[30];
cout << "How many items in array? ";
cin >> array_length;
char items [30][array_length + 1];
^^^^^^^^^^^^
I assume this is legal in C++, but I'd love it if a real C++ person
stated something authoratative. As an aside, if you're making the
array array_length+1 items long, then array_length isn't really, is
it?

No, it is not legal in C++. It is legal in C under the
not-widely-implemented C99 version of the standard, where arrays with
automatic storage class can be VLAs (Variable Length Arrays). It is
also a non-standard extension provided by GNU and perhaps other
compilers.
 
O

Old Wolf

Christopher Benson-Manica said:
Tim Johansson said:
char items [30][array_length + 1];
^^^^^^^^^^^^
I assume this is legal in C++, but I'd love it if a real C++ person
stated something authoratative. As an aside, if you're making the
array array_length+1 items long, then array_length isn't really, is
it?

Well it isn't the array length anyway: he would have declared an array
of 30 items, each item of which has length (array_length+1), if the
syntax were legal.
for (count = 0; count < array_length; count++) {
randm = rand() % array_length;
strcpy (temp[30], items[30][count]);

Here's the problem (well, besides that you're using C-style strings at
all): strcpy is prototyped as

char *strcpy( char *s, const char *t );

What is temp[30]? It's a char, of course. And what is
items[30][count]? It's a char, too. No wonder it doesn't compile,
eh?

Not to mention that both are undefined behaviour (reading a char
from past the end of the array). God knows what he was trying to do there.
Either read a C book or learn how to use std::strings and std::vectors
- I recommend the latter.

Seeing code like this is what moved me from the "Learn C then C++" camp
to the "Learn C++ then C" camp. Petec's replacement program is
excellent.
 
J

John Harrison

Tim Johansson said:
I'm new to C++, and tried to start making a script that will shuffle an
array. Can someone please tell me what's wrong?

You've been give lots of good advice, but clearly the best advice is to find
better material for your learning.

1) Get a good book, one that doesn't say that <iostream.h> is the right
thing to do. Also one that mentions standard library templates such as
string and vector (these are what you should be using for this program).

2) Get a better compiler. The compiler you are using is allowing you to get
away with illegal code. What sort of way to learn C++ is that? Now I'm
guessing here but if you are using gcc or g++ then you should compile with
the -ansi and -pedantic options. This will make your compiler much closer to
the real C++ language.

john
 
K

Kevin Goodsell

John said:
Kevin, someone should be paying you.

john

Well, I certainly think so. ;) But not for what I'm doing here. I think
we all do this for basically the same reason: because learning is hard,
because we want to see the overall quality of programmers improve, and
because we want to give back to the group that is always here to help us
when we need it.

-Kevin
 
C

Christopher Benson-Manica

Kevin Goodsell said:
Well, I certainly think so. ;) But not for what I'm doing here. I think
we all do this for basically the same reason: because learning is hard,
because we want to see the overall quality of programmers improve, and
because we want to give back to the group that is always here to help us
when we need it.

You forgot some reasons: learning is fun, writing elegant code is fun,
and engaging in arcane pedantry is fun ;)
 

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
473,769
Messages
2,569,581
Members
45,056
Latest member
GlycogenSupporthealth

Latest Threads

Top