Re: Invalid conversion from 'char' tp 'char*'

From: Kevin Goodsell (usenet2.spamfree.fusion_at_neverbox.com)
Date: 04/07/04


Date: Wed, 07 Apr 2004 20:23:42 GMT

Tim Johansson wrote:

> 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, but deprecated. <cstring> is the replacement.

>
> 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<std::string> items(array_length + 1);

> 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

-- 
My email address is valid, but changes periodically.
To contact me please use the address from a recent posting.


Relevant Pages

  • Re: char vs int
    ... 'a' is a character constant. ... A variable of type char can ... of them instead of int arrays. ... concept of pointers. ...
    (comp.lang.c)
  • Re: trying to construct an array.....corrected
    ... May I ask why this char is volatile? ... (which points to the string literal in question). ... Arrays are meant for a collection of data of the same type. ... What you're looking for is a struct. ...
    (comp.lang.c)
  • Re: sscanf problem.
    ... I use TCHAR arrays very rarely; most commonly for APIs that want MAX_PATH sized buffers, ... and those tend to fall into the "rare and exotic" for me. ... CString and go on with life. ... char cs; ...
    (microsoft.public.vc.mfc)
  • Re: simple question regarding 5.5 of Ritchie & Kernighan
    ... pointers to char and arrays of char: ... a memory address to hold the value it points to and that memory address ... runtime) multidimensional arrays. ... arrays of pointers to arrays, ...
    (comp.lang.c)
  • Re: anonymous initializer problem
    ... the declaration section (via initializer). ... and has only one public constructor that takes an array of field objects. ... This way I could define my dictionary in the declaration section where it is ... costructor declare custom static arrays that use the dictionary values, ...
    (microsoft.public.dotnet.languages.csharp)