Reputation: 11
Hello I am new to c programming and while trying structs with different data types in my code
#include <stdio.h>
#include <string.h>
struct myType
{
int imInteger;
float imFloat;
char imChar;
char imString[33];
};
int main()
{
struct myType example;
example.imInteger = 4;
example.imFloat = 3.141592;
example.imChar = "h";
char exampleChar = "g";
example.imString = "Hello World";
char exampleString[33] = "Goodbye World";
printf("My data types are:\n");
printf("\t Int: %d\n", example.imInteger);
printf("\t Float: %.4f\n", example.imFloat);
printf("\t Char: %c\n", example.imChar);
printf("\t Example: %c\n", exampleChar);
printf("\t String: %s\n", example.imString);
printf("\t Example: %s\n", exampleString);
return 0;
}
I get the following error
,,error copy.c: In function 'main':
error copy.c:18:20: warning: assignment to 'char' from 'char *' makes integer from pointer without a cast [-Wint-conversion]
18 | example.imChar = "h";
| ^
error copy.c:19:24: warning: initialization of 'char' from 'char *' makes integer from pointer without a cast [-Wint-conversion]
19 | char exampleChar = "g";
| ^~~
error copy.c:20:22: error: assignment to expression with array type
20 | example.imString = "Hello World";
| ^
My expected output would be:
My data types are:
Int: 4
Float: 3.1416
Char: h
Example: g
String: Hello World
Example: Goodbye World
In previous codes without structs I didn't have any troubles when declaring char and using strings, so if anyone could bring me help it would be really appreciated.
Thanks
Upvotes: 1
Views: 856
Reputation: 10028
There are two ways to store a string in a struct
:
struct myType
{
int imInteger;
float imFloat;
char imChar;
char imString[33]; // strings may not be more than 32 characters long
};
Strings must be copied to the struct:
struct myType example = {0};
strncpy( example.imString, "Hello world", sizeof(example.imString) );
example.imString[sizeof(example.imString)-1] = '\0'; // make sure it is null-terminated
struct myType
{
int imInteger;
float imFloat;
char imChar;
char * imString; // strings may be any size, but must be managed
};
This is where strdup() is useful:
struct myType example = {0};
example.imString = strdup( "Hello world" );
You must be careful to free()
it every time you touch it, though:
free( example.imString );
example.imString = strdup( "Goodbye world" );
free( example.imString );
// destroy example
Notice that both times I explicitly initialized the struct to zeros? This is a good thing: for the first example you get an empty fixed-length string; for the second example you get a NULL
pointer — both of which are good because they provide a consistent, observable state at all times (and let that free()
work without error).
Life is easy if you create a constructor:
struct myType create_myType()
{
...
}
or:
struct myType * create_myType()
{
...
}
void free_myType( struct myType * x )
{
free( x->imString );
free( x );
}
Every time you create one, use the explicit constructor:
struct myType example = create_myType();
or:
struct myType * example = create_myType();
...
free_myType( example );
You can even specialize constructors for different types:
struct myType * create_int_myType( int x );
struct myType * create_float_myType( float x );
struct myType * create_string_myType( const char * s )
{
struct myType * result = create_myType();
result->imString = strdup( s );
return result;
}
And so on.
Upvotes: 4