Assign values to string array in C - c

I have a struct that looks like this:
struct persons_s
{
size_t count;
char names[MAX_PERSON_COUNT][MAX_PERSON_NAME_LENGTH];
};
When I try to assign values like this, it does not work:
struct persons_s persons;
persons.count = 2;
persons.names = { "test1", "test2" };
But this works:
struct persons_s persons = { 2, { "test1", "test2" } };
I am assuming this has something to do with the names array being constant, but I'm not sure.
So I'm asking:
What is the exact reason the first way does not work?
Is there a better way to accomplish this?
I also tried
char *names[MAX_PERSONS_COUNT];
but this doesn't work either because I have to use it with strcpy (as destination, strcpy(persons.names[i], source);).
Currently I am doing the assignment like this (using the first struct):
struct persons_s persons;
persons.count = 2;
strcpy(persons.names[0], "test1");
strcpy(persons.names[1], "test2");

You are trying to assign a constant to a pointer (char[][], or **char), in C a string is an array of chars, you can either use strcpy or make it yourself with a for loop.
Your way strcpy(persons.names[0], "test1"); works fine and is probably the best option for you.

Related

C string array, assigning and passing etc

I have been rethinking my way of asking. so i edited the question.
i know beforehand how many strings there will be in the array because it is menu text.
suppose i have an array of strings declared as so:char *menu_item[4];
this should give me an array that can hold 4 strings right?
i want to be able to pass the string array to other functions so is this the way to do it?
This array is not declared in main. but in a function that is called from main.
will i have to allocate memory to use fx strcpy(menu_item[1],"some text");
and if yes. what should i allocate??
or is menu_item[0] = "some text"okay??
i have a function in a function to print out the strings which takes a char *string as parameter. and the function itself takes a string array as so char *items[] it looks like this:
void scroll_menu(char *items[], int size){
for(int i = 0; i < size; i++){
print_out(items[i]);
}
}
is the parameter correct for a string array?
i have been looking through a lot of question online. and cant seem to find anything that solves my problem.
if any doubt i will recap what it is i want:
i want to declare an array of strings which holds a known number of strings. sometimes the strings can be initialized in the declaration of the array. and other times i have to look up somewhere and then "assign" or copy the result to the array.
i want to be able to copy or assign strings to it from functions returning a char *string like so strcpy(menu_item[0], some_function_returning_string());
my problem is that i have tried so many different things that i am left confused. and have misunderstood the string array operations.
i have also tried with char menu_items[4][20]; and then strcpy(menu_items[0], "some text"); without any luck. and then there is the issue with how to make the function accept an array declared like this.
any suggestions on how to accomplish what i want would be very nice.
EDIT
i took some time reading the c programming book and found what i was looking for.
if i declare an array of pointers to strings as so char *menu_items[4] i will have an array that can take 4 pointers to strings or char arrays char *string
if i want to assign a string from a function returning a char * i have a function as so:
char *function_returning_string(int x){
static char *strings[3] = {"this","is","strings"};
if(x <= 2){
return strings[0];
}
else if(x > 2){
return string[1];
}
else{
return strings[2];
}
}
the code from where i call this function i have the following:
static char *other_strings = {"yes", "no"};
char *menu_item[3];
menu_item[0] = "ok";
menu_item[1] = other_strings[0];
menu_item[2] = function_returning_string(3);
then i can just pass the entire string array to functions that takes a *string_array[] as parameter as so function_takin_string_array(menu_item); or any string inside to functions taking char *string as parameter as so function_taking_string(menu_item[2]);
the code compiles without errors and works. if anybody think there is something wrong about the code or if have have misunderstood something please let me know.
As MFisherKDX noted this part of a code is incorrect:
static char *addr;
sprintf(addr, "S %d", i + 1);
return addr;
How do you think what are you returning here? It should be failed on sprintf() call because you try to assign some value to unallocated memory. It should be like this:
static char addr[128];
sprintf(addr, "S %d", i + 1);
return addr;
And how PeterJ_01 mentioned above try to use gdb to figure out what is wrong and where you have other mistakes.

Comparing Char* to Enum variable in C

So I'm trying to utilize Enumerated types in C for the first time. So I have an Enumerated "variable?" declared and I also have a struct which has a variable of the Enumerated type(among other things). Finally I have a static array for which there is an element containing each of the enum "types?" in the same order they were declared. I am hoping to use the enum type to act as an index for the array.
So my problem is that I need to somehow relate a char* variable to the enumerated type. If I KNOW that the Char* variable is one of the enum types, is there some way to assert that without having to look at each char to determine which specific enum"option" it is?
Example:
enum example = {abc,def}
struct _strExample {
enum example letters;
....
};
typedef struct _strExample strEx;
static strEx Table[2] = {
{abc,...}
{def,...}
};
//Given char* "abc" , want either example.abc or 0 ( correct index of table)
So given the char* "abc"(does not need to be char*), is there a simple way to get either the correct enum "type?"(abc or def)or the correct index of the table? I know that I could check all the individual chars in the char* and manually determine which enumerated "type?" it is, but I am going to be working with a very large set of enumerated variables and this kind of thing is exactly what I was trying to avoid. any help or advice you guys could give on enumerated types and/or my design would be most appreciated.
Use a an array of strings where the index into the array is the enum value. If the strings are all short, or all about the same length, storing the string in the array makes sense. Otherwise, use a char* pointer.
typedef enum enum_t { plugh, plover, xyzzy, y0 } enum_t;
const char *etable = { "plugh", "plover", "xyxxy", "y0", NULL };
With that, you can convert with a simple search like:
enum_t find_enum(char *sval)
{
enum_t result=plugh; /* value corresponding to etable[0] */
int i=0;
for (i=0; etable[i]!=NULL; ++i, ++result)
if (0==strcmp(sval, etable[i])) return result;
return -1;
}
The enum-to-string converstion is simply etable[e-plugh]. Those allow for a different definition of enum_t where the first meaningful value may not be 0, but the values are sequentially assigned thereafter.
No, you can't lookup any scalar value from a character array. You have to iterate over a set of strings to compare and find the relation to the enum member.
You can use an array of structs
typedef struct { int value; const char * name; } lookup_t;
lookup_t lookup[] = {
{ 1, "One"},
{ 0, NULL} // end tag, alternatively use the _countof(lookup) to get the number of elements
};
and compare your char* with the name member. Then you use the value on match.
Use if :
char *ex = "abc";
strEx strex;
if(!(strcmp("abc",ex))) {
strex.letters = abc;
}
else {
strex.letters = def;
}

C: How to store a string in a structure

So I have a structure, and one of its members is a string.
struct Output {
char *axis;
int value;
};
struct Output Jsoutput;
My question is, how do I store a string in axis?
char whichaxis[4][3] = {"LX","LY","RY","RX"};
// Store which axis and value of the joystick position in Jsoutput
Jsoutput.axis = whichaxis[jse.number];
printf("%s\n",Jsoutput.axis);
I feel like there should be some & somewhere, but not sure where.
Just use strdup
Jsoutput.axis = strdup(whichaxis[jse.number]);
You can copy a String with the function strcpy(destination, source)from string.h
see http://www.cplusplus.com/reference/cstring/strcpy/
Jsoutput.axis = malloc(3);
strcpy(Jsoutput.axis,whichaxis[jse.number]);
You don't have to "store" the string a second time.
char whichaxis[4][3] = {"LX","LY","RY","RX"};
Stores the string.
char *axis;
Says "I'm going to point at a string".
If you wanted a & in there, you could do:
Jsoutput.axis = & (whichaxis[jse.number][0]) ;
But the original designers of C were very pragmatic and let arrays turn into pointers all the time for convenience. See What is array decaying for more details.

Assign values to a record array in C

I've got the following problem. For a homework assignment I'm supposed to create an Heap-Array of the record "student" for 5 students and then assign some values(names etc.).
Now when I try to assign values to the record the way I did it before, i get an "expression expected before {" error.
Edit:
typedef struct student_t {
char hauptfach[128];
char name[64];
int matnr;
} student;
/Edit
student *students;
students = malloc(5*sizeof(student));
students[0] = {"Info", "Max Becker", 2781356};
students[1] = {"Soziologie", "Peter Hartz", 6666666};
students[2] = {"Hurensohnologie", "Huss Hodn", 0221567};
students[3] = {"Info", "Tomasz Kowalski", 73612723};
students[4] = {"Info", "Kevin Mueller", 712768329};
But when I try to assign a single value e.g.
students[0].hauptfach = "Informatik";
the program compiles.
What am I doing wrong?
Thanks in advance,
D.
You haven't shown your structure definition, but I expect that the string is an array of char with some maximum size.
To assign a string, you need to use strncpy. Look that function up.
Basically, assuming that the hauptfach member is MAX_LEN+1 characters long:
strncpy( students[0].hauptfach, "Informatik", MAX_LEN+1 );
students[0].hauptfach[MAX_LEN] = 0; // Force termination if string truncated.
Oops, sorry I misread your question. The above may still hold true.
You cannot copy over a struct like that. You must initialise it at the array definition:
struct mystruct students[5] = {
{"Info", "Max Becker", 2781356},
{"Soziologie", "Peter Hartz", 6666666},
{"Hurensohnologie", "Huss Hodn", 0221567},
{"Info", "Tomasz Kowalski", 73612723},
{"Info", "Kevin Mueller", 712768329}
};
Or you can assign fields individually as you've shown. Another option is you can replace one whole array element like by initialising a single instance and then copying like this:
struct mystruct temp = {"Soziologie", "Peter Hartz", 6666666};
students[0] = temp;
These two statements can't really go together:
1 students = malloc(5*sizeof(student));
2 students[0] = {"Info", "Max Becker", 2781356};
(1) says that you want to dynamically allocate memory at run-time.
(2) says that you want to assign the values you list to a fixed address at compile-time. Unfortunately, the compiler cannot know what the address of students[0] is ahead of time, so it cannot do what you would like.
I'd suggest you create a helper function:
void initstudent(student *s, const char hf[], const char name[], int matnr){
strncpy(s->hauptfach, hf, MAXLEN);
strncpy(s->name, name, MAXLEN);
s->matnr=matnr;
}
and then apply this to each of your students.

Looping a fixed size array without defining its size in C

Some example code to start the question:
#define FOO_COUNT 5
static const char *foo[] = {
"123",
"456",
"789",
"987",
"654"
};
The way this would normally be iterated over, as for one example, is the following:
int i = FOO_COUNT;
while (--i >= 0) {
printf("%s\n", foo[i]);
Is there anyway to do the above without explicitly having the human count the number 5? In the future I might add/remove elements and forget to update the size of the array, thus breaking my app.
int i = sizeof(foo)/sizeof(foo[0]);
Use a sentinel at the end, such as NULL:
static const char *foo[] = {
"123",
"456",
"789",
"987",
"654",
NULL
};
for (char *it = foo[0]; it != NULL; it++)
{
...
}
The usual way to do this is to end the array with NULL and iterate until you hit that.
Yes.
int i = sizeof(foo) / sizeof(char*);
Note: This only applies to statically allocated arrays. It will not work for malloced or newed arrays.
size_t i = sizeof foo / sizeof *foo; // or sizeof foo / sizeof foo[0]
This divides the total number of bytes in the foo array (sizeof foo) by the number of bytes in a single element (sizeof *foo), giving the number of elements in the array.
There's also another method in C99, especially if you want named indexes, allowing for instance localization and such.
enum STRINGS {
STR_THING1,
STR_THING2,
STR_THING3,
STR_THING4,
STR_WHATEVER,
STR_MAX /* Always put this one at the end, as the counting starts at 0 */
/* this one will be defined as the number of elements */
}
static const char *foo[STR_MAX] = {
[STR_THING1] = "123",
[STR_THING2] = "456",
[STR_THING3] = "789",
[STR_THING4] = "987",
[STR_WHATEVER] = "OR Something else",
};
By using named initializer the program still is correct even if an enum value changes.
for (i = STR_THING1; i<STR_MAX; i++)
puts(foo[i]);
or anywhere in the program with the named index
printf("thing2 is %s\n", foo[STR_THING3]);
This technique can be used to simulate ressource bundles. Declare one enum and several string arrays with language variants and use a pointer in the rest of the program. Simple and fast (especially on 64bit machines where getting the address of a constant (string) can be relatively costly.
Edit: the sizeof foo/sizeof *foo technique still works with this.
Yes.
sizeof(foo)/sizeof(char*)
is 5.
For some application, try and Catch would work.

Resources