Problem with structs and strings in C

B

Bleakcabal

Keep in mind my program is written in C ( not C++ ).

I have a function which takes two structs as parameters is supposed to
put the values of the source struct in the destination struct. Only
the first character is put into the destination struct for each field.


void AssignValues(info *source, info *destination)
{
*destination->name = *source->name;
*destination->class = *source->class;
*destination->alignment = *source->alignment;
}


Name, class and alignment are defined as
char variableName[20];
In a struct called info.

If my source is : test, TEST example
The destination is : t, T, e

Why is that ?

Thanks for your help.
 
S

Stig Brautaset

Bleakcabal said:
Keep in mind my program is written in C ( not C++ ).

I have a function which takes two structs as parameters is supposed to
put the values of the source struct in the destination struct. Only
the first character is put into the destination struct for each field.

Use strcpy() or similar to copy strings.

Stig
 
P

pete

Bleakcabal said:
Keep in mind my program is written in C ( not C++ ).

I have a function which takes two structs as parameters is supposed to
put the values of the source struct in the destination struct. Only
the first character is put into the destination struct for each field.

void AssignValues(info *source, info *destination)
{
*destination->name = *source->name;
*destination->class = *source->class;
*destination->alignment = *source->alignment;
}


void AssignValues(info *source, info *destination)
{
*destination = *source;
}
 
L

Leor Zolman

Keep in mind my program is written in C ( not C++ ).

I have a function which takes two structs as parameters is supposed to
put the values of the source struct in the destination struct. Only
the first character is put into the destination struct for each field.


void AssignValues(info *source, info *destination)
{
*destination->name = *source->name;
*destination->class = *source->class;
*destination->alignment = *source->alignment;
}


Name, class and alignment are defined as
char variableName[20];
In a struct called info.

If my source is : test, TEST example
The destination is : t, T, e

Why is that ?
A few solutions have been posted, and they're correct given your
context so far [just be careful: if you use strcpy, make sure the
source strings have been initialized properly; if you use structure
assignment, keep in mind that it will cease to work correctly if you
were to change the type of any of your data members from arrays to
pointers...and that may very well end up being your next step ;-) ]

Another hint: if code involving arrays or pointers doesn't work right,
carefully check the /types/ of the expressions involved. In this case,
all six main expressions are of the form:
* array
Remember that array names used in /most/ expressions "decay" to being
a pointer to their first element, so type-wise that equates to:
* (char *)
The *'s cancel leaving "char" as the type. Hence the char-to-char
assignment.

Rule of thumb: There's no single C assignment expression that can
directly copy an array (you'd have to cheat and embed the array in a
structure and copy the structure, which is why Pete's solution works
so nicely in this case.)
-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
 
M

Michael

Hi Pete,
this seems to be similar to a
question I posted earlier. But
won't
*destination = *source;

just copy the adresses of the array,
s.th like a non-deep copy? So both
structs share the strings?
Kind Regards,
Michael
 
L

Leor Zolman

Hi Pete,
this seems to be similar to a
question I posted earlier. But
won't


just copy the adresses of the array,
s.th like a non-deep copy? So both
structs share the strings?

Nope, there's no problem here because we're copying values, not
addresses. If the data members of the structure were pointers, /then/
we'd be copying addresses and inviting all sorts of undefined behavior
down the road when the program begins freeing them (or at least chaos
before that if the program expects the data being pointed to by the
two separate pointers to be distinct.)
-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
 
C

CBFalconer

Michael said:
this seems to be similar to a
question I posted earlier. But
won't


just copy the adresses of the array,
s.th like a non-deep copy? So both
structs share the strings?

You removed context quotations, including all definitions. IIR
you defined the fields within the structures as arrays, not as
pointers, so there is nothing deep to copy.
 
A

Al Bowers

CBFalconer said:
You removed context quotations, including all definitions. IIR
you defined the fields within the structures as arrays, not as
pointers, so there is nothing deep to copy.

The op definitions are a little unclear. There is some evidence
that the members are typedef char array of 20 characters. If this
is the case, struct assignment will be safe as will using function
strcpy.

Example:

#include <stdio.h>
#include <string.h>

typedef char variableName[20];
typedef struct info
{
variableName name;
variableName class;
variableName alignment;
}info;

info init = {"No data","No data", "No data"};

void AssignValues1(const info *source, info *destination)
{
*destination = *source;
}

void AssignValues2(const info *source, info *destination)
{
strcpy(destination->name,source->name);
strcpy(destination->class, source->class);
strcpy(destination->alignment,source->alignment);
return;
}

void PrintInfo(const info *p)
{
char *s = "No Data";
printf("Name: %s\nClass: %s\nAlignment: %s\n\n",
p->name,p->class,p->alignment);
}

int main(void)
{
info myinfo = {"George Washington","Political Science","Junior"};
info newinfo = init;

puts("struct newinfo contents");
PrintInfo(&newinfo);

newinfo = myinfo;
puts("Using simple assignment");
PrintInfo(&newinfo);
newinfo = init;

puts("Using function AssignValues1");
AssignValues1(&myinfo, &newinfo);
PrintInfo(&newinfo);
newinfo = init;

puts("Using function AssignValues2");
AssignValues2(&myinfo, &newinfo);
PrintInfo(&newinfo);

return 0;
}
 
M

Mark L Pappin

Keep in mind my program is written in C ( not C++ ).

Anybody who assumes otherwise is in the wrong newsgroup.
I have a function which takes two structs as parameters is supposed to
put the values of the source struct in the destination struct. Only
the first character is put into the destination struct for each field.

/* You really should post _complete_, _compilable_ examples. I have
inserted my own assumptions of what you meant; I could be wrong. */
typedef struct {
char name[20];
char class[20];
char alignment[20];
} info;
void AssignValues(info *source, info *destination)
{
*destination->name = *source->name;
*destination->class = *source->class;
*destination->alignment = *source->alignment;
}
Name, class and alignment are defined as
char variableName[20];
In a struct called info.

If my source is : test, TEST example
The destination is : t, T, e

Why is that ?

You appear to have misunderstood what all the *s mean. You're
explicitly copying the first character only of each character array -
your first statement above is equivalent to

destination->name[0] = source->name[0];

(Note also that, depending on how the object passed in as destination
is defined, the terminating '\0's that have magically appeared in
destination->name[1] et al may not be guaranteed. If you had shown a
complete compilable program, we would be able to tell.)

Try replacing it (and the other two similarly) with

memchr(source->name, '\0', 20) ||
strcpy(destination->name, source->name);

(You will need to
#include <string.h>
somewhere earlier as well.)

And unadorned magic numbers are bad form.

mlp
 
M

Mark L Pappin

I wrote, moments ago, stuff which included:
(e-mail address removed) (Bleakcabal) writes:
Try replacing it (and the other two similarly) with

memchr(source->name, '\0', 20) ||
/*fix*/ memchr(source->name, '\0', 20) &&
strcpy(destination->name, source->name);

(You will need to
#include <string.h>
somewhere earlier as well.)

(What was I thinking? And where did the _second_ || come from?)

And I suppose I should elaborate: If you can guarantee that each field
in source is properly initialized with a valid ('\0'-terminated) C
string which is no larger than the space allocated, then you can leave
off the memchr() call above. If you can't, then you should use some
mechanism to ensure that you do not merrily write past the end of any
of the arrays in destination - the call to memchr() above does this,
once the correct logical operator is used, but there are other ways
including use of strncpy() although it may write more '\0's than it
needs to.

mlp
 

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

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,014
Latest member
BiancaFix3

Latest Threads

Top