views:

117

answers:

5

This is linked to my previous post

Wher I created a Struct :

struct buffer
{
    char ProjectName[20];
       char ProjectID[20];
};

Now while I am trying to assign values to it:

buffer buf;
buf.ProjectID = "3174";
buf.ProjectName = "NDS";

I am getting this error:

error C2440: '=' : cannot convert from 'char [5]' to 'char [20]'

and to resolve this I tried decreasing the size of structure as below(must not be the way to do it) :

struct buffer
{

    char ProjectName[4];
    char ProjectID[5];
};

and the get error C2106: '=' : left operand must be l-value

+4  A: 

You have to copy the string into the array:

strcpy(buf.ProjectName, "3174");

Be careful with the length of the strings being copied into the arrays

jab
+4  A: 

You can not assign strings like that in C++. You need to use the function such as strcpy to copy the string. Or better still use the class std::string

Naveen
Could you provide a code snipper please
Subhen
@Subhen See response by @jab for an example of using strcpy()
Andy Johnson
+3  A: 

That's normal, you can't really assign values to char tables that way (there are numerous different solutions, sprintf or strcpy for instance). But this is a C problem, not C++.

Since you're coding in C++, you should use std::string to manage your strings (and the c_str() method if you need those strings converted in char tables).

Raveline
+2  A: 

Let's look at the first case:

buffer buf; 
buf.ProjectID = "3174"; 
buf.ProjectName = "NDS"; 

$2.13.4/1 - "An ordinary string literal has type “array of n const char” and static storage duration (3.7)"

The type of "3174" is char const [5] and type of "NDS" is char const [4]. While trying to attempt the assignment to 'buf.ProjectID', the compiler has to essentially convert from 'char const [5]' to 'char const [20]'. This conversion is not allowed by C++ rules. In fact, a more appropriate error message is thrown in your next attempt.

$8.3.4/5 - '[Note: conversions affecting lvalues of array type are described in 4.2. Objects of array types cannot be modified, see 3.10. ]".

In other words it means, that name of an array is non modifiable lvalue (which is what the 2nd compiler message says).

$5.17- "There are several assignment operators, all of which group right-to-left. All require a modifiable lvalue as their left operand, and the type of an assignment expression is that of its left operand."

So here is the summary:

For the assignment expression to work, the left hand side should be a modifiable LValue expression. However an array is a non modifiable Lvalue expression. Hence it can not be assigned to.

Chubsdad
There's no way the poster's going to understand that... :-/.
Tony
@Tony: Thanks for that feedback. Have slightly elaborated it further
Chubsdad
+1  A: 

I'm sorry to say that C++ is a bit unintuitive here. You can say:

char name[10] = "abcd";

and, given your definition above:

buffer buf = { "NDS", "3174" };

The latter relies on a one-to-one correspondence between fields in the structure and values in the list, so I've had to reverse the order used in your assignments.

But, you can't do your

buf.ProjectName = "abcde";

What that actually requests in C++ is that buf.ProjectName be loaded with a pointer to memory containing the character data "abcde". You can't do that though, as ProjectName itself is another buffer for character data, and not of pointer-to-character-data.

So, when you have a source and destination area containing NUL-terminated strings (Google ASCIIZ if necessary), you need to use a support function to copy from one to the other:

strcpy(buf.ProjectName, "name");

If ProjectName's dimension is too small, then your string may overwrite memory that the compiler hasn't reserved for ProjectName, probably causing a crash or erroneous output. You can protect against this - if the relative sizes of the strings isn't obviously ok - using strncpy(buf.ProjectName, "name", sizeof buf.ProjectName). Unfortunately, this means buf.ProjectName may not hold the full expected value, making it of dubious use.

C++ improves over this way of handling textual data - which is inherited from C - with the std::string class. You can simple do this:

#include <string>
struct Buffer
{
    std::string project_name_;
    std::string project_id_;
};
Buffer b;
b.project_name_ = "abcde"; // works with string literals.
b.project_id_ = b.project_name_;  // can copy from std::string to std::string
Tony