Allocing memory to array of strings - c

So, i'm tring to allocate memory to insert file names in it. I have my struct Estado defined like this:
typedef struct estado{
char modo;
char jogador;
char matriz[8][8];
int pretas;
int brancas;
char *nome[10];
int current;
} Estado;
I tried doing this:
Estado insereFicheiro(Estado estado , char* nome){
estado.nome[estado.current] = malloc(sizeof(char*));
estado.nome[estado.current++] = nome;
return estado;
}
What am i doing wrong ?

There's two problems with the code you show:
With
estado.nome[estado.current] = malloc(sizeof(char*));
you allocate only space for a pointer, not the whole string. This is like you creating an array of one pointer. You need to allocate space for the string itself, whose length you get from strlen, and also for the null-terminator at the end:
estado.nome[estado.current] = malloc(strlen(nome) + 1); // +1 for null-terminator
With
estado.nome[estado.current++] = nome;
you overwrite the pointer you created above. This is equivalent to e.g. int a; a = 5; a = 10; and then be surprised that a is no longer equal to 5. You need to copy the string, not the pointer:
strcpy(estado.nome[estado.current++], nome);
Of course, you need to free the memory you allocate later in your code, once you're finished with it.
And of course you should have some bound-checking to make sure you don't go out of bounds of the estado.nome array (i.e. a check for estado.current < 10).

Related

C - Implementing Queue of Char * Array

I want to implement a queue which holds 10 elements of char * array. I searched on the internet but couldn't find enough solutions.
I have a char array:
char str[50]:
char *arr[5];
And the user enters some string with backspace character e.g "Hello I am computer". The string is in str[] array. I token them with strtok() function and assign it to the arr[].Then it becomes:
//arr[0] = "Hello"
//arr[1] = "I"
//arr[2] = "am"
//arr[3] = "computer"
It is ok until now, I am doing it correctly.
Now my question is how to hold this whole arr array in queue's first node or element. There are lots of examples about queue that holding int values and they are easy to understand, but I couldn't do the char * version.
As far as I understood your question you need to implement a queue of type string.
You can do it as you do with any other queue.But instead of int it would of type char* you would also need to pass length of the word so you could dereference that many number of char starting from the char pointer till length of the word.
void Enqueue(char* x, int len)
{
// if empty
front = rear = 0;
// else
rear = (rear+1);
char ch[100];
for(int i=0;i<len;i++) {
ch[i] = *(x+i);
}
Arr[rear] = ch;
}
First of all you have to be careful when saving an address to a variable that you want to use later. You have to ensure that the address hold by the pointer is still valid when you read from it:
int main()
{
char str[] = "Hello I am computer"; // "Hello I am computer" is stored on the stack
AddStringToQueue(str[0]);
}
// str could be overwritten by another function who allocates local variables
As you said in the comment you should use void* malloc(sizeof("Hello I am computer")) which return the start pointer of your allocated memory.
The other thing is why you want to store the string as tokens? Wouldn't it be easier to store the whole string ("Hello I am computer") and use the first character as your start address for the string? If you need it as tokens you maybe can call strtok() after you read out the queue.
Let me make an example:
#define QUEUE_MAX 10
int QueuePos = 0;
char* Queue[QUEUE_MAX];
memset(Queue, NULL, sizeof(Queue));
// call AddStringToQueue("Hello I am computer"); anywhere
void AddStringToQueue(char* string)
{
char* ptr = (char*)malloc(sizeof(string));
memcpy(ptr, string, sizeof(string));
Queue[QueuePos++] = ptr;
if (QueuePos == QUEUE_MAX) QueuePos = 0; // overwrites Queue if max. is reached
}
I am not sure if you mean this.
Hope it helps.
PS: I didn't compiled this so i am not sure if it works, it should just be an example.

Copy a string from a pointer to an index within an array of pointers

As stated in the title, I wanted to copy a string from a char pointer to location within an array of char pointers. When doing strcpy(), the output results in seg fault, but don't understand why this occurs.
The abbreviated code has the following:
void make_history(char *entry) {
//static char past_entries[10][10];
static char *past_entries[10];
static int index = 0;
static int array_index = 0;
char *input;
if((input = strchr(entry, '\n')) != NULL)
*input = '\0';
if(strcmp(entry, "history") != 0) {
strcpy(past_entries[index], entry);
*past_entries[index] = &entry;
index = (index + 1) % 10;
array_index++;
}
}
Instead of trying to return a 2d array (which is also very tricky), I thought it would be easier to copy the date from entry to the location within the array of pointers past_entries. Again, strcpy does not work, is there a valid reason as to why this occurs, and a possible workaround or solution to this fix?
Thank you
In your example past_entries is just an array of pointers, but you don't allocate any memory to them (initially pointing to NULL). You then try to write to those locations, hence the crash.
To solve this, just allocate some memory before you try to copy your string to it:
past_entries[index] = malloc(strlen(entry) + 1);
Of course you should not forget to free all of this in the end.
Oh and, remove that line: *past_entries[index] = &entry;. It tries to assign a pointer to a character array to a character.

Segfault when assigning to char* in struct

So I have a struct "sequence" that has a char* in it. When I try and create a sequence, whenever I try and change the char* it segfaults. Here is the related code. The struct:
typedef struct _sequence {
unsigned int length;
unsigned char* bytes;
} Sequence;
The constructor:
Sequence* newSequence(unsigned char firstByte) { //Creates new sequence, allocates memory
printf("Creating new Sequence\n");
Sequence* seq = (Sequence*)malloc(sizeof(Sequence));
printf("Have new sequence\n");
seq->length = 1;
printf("Set length\n");
seq->bytes[0] = firstByte;
printf("Set variables\n");
return seq;
}
Now I have a main function here just for testing purposes, this file will in the end not have a main function. But here is what i used to testing:
int main() {
char test[] = "ab";
printf("Testing sequences!\n");
Sequence* newSeq = newSequence(test[0]);
printf("Made new sequence!\n");
outputSequence(newSeq, stdout);
printf(" <-- new Sequence created\n");
return 0;
}
The printfs are again for testing purposes. It always prints out all the way up to "Set length\n" in the constructor, then segfaults. What am I doing wrong? Thank you!
You allocated apace for the structure correctly, but you didn't allocate any space for the buffer pointed to by the bytes element.
This line invokes undefined behavior because bytes is uninitialized:
seq->bytes[0] = firstByte;
You need to also allocate a buffer and point seq->bytes to it.
Sequence* seq = malloc (sizeof(Sequence));
Here you allocate memory space for one char * , and one int, but you need to allocate space for what you want to store on what is pointed at by your char *, this way :
seq->bytes = malloc (my_string_size);
Only then can you start storing characters in your allocated chunk of memory.
Edit : for instance, to store one single character, you could do :
seq->bytes = malloc(1);
seq->bytes[0] = firstByte;
to use it as a single character. But the good habit in C to manipulate string is to always leave one char more, in that fashion :
seq->bytes = malloc(2);
seq->bytes[0] = firstByte;
seq->bytes[1] = '\0';
The 2nd method looks more like a real 'string' in C.

How can heap objects use data from the stack?

I've declared the struct foo like this:
struct foo {
const char* name_lower;
const char* name_caps
//..
};
I dynamically create instances of foo on the heap and want to save a value in the name_lower and name_caps member variable. This is done by the function bar
void bar(foo* entry, const char* str, int delimiter_pos) {
char l[2] = {str[caps_pos-1], '\0'}; // create new string
char c[2] = {str[caps_pos+1], '\0'};
entry->name_lower = &l[0]; // assign these strings the foo instance
entry->name_caps = &c[0];
}
I am worried, because I don't know if this code is going to crash. The temporarily created arrays l and c will be saved on the stack. Once the function terminates the stack will be cleared up and c and l will probably disappear.
Does this mean that the foo instance will lose its names, i.e. its references? If so, how can I solve this problem?
Continuing from the comment, the easiest way to allocate/copy and assign the start address for new blocks of memory for l and c is to use strdup (from string.h):
void bar(foo* entry, const char* str, int delimiter_pos) {
char l[2] = {str[caps_pos-1], '\0'}; // create new string
char c[2] = {str[caps_pos+1], '\0'};
entry->name_lower = strdup (l); // assign these strings the foo instance
entry->name_caps = strdup (c);
}
Don't forget to free the memory allocated to entry->name_lower and entry->name_caps when no longer needed.
You should instead use char *l = (char *)malloc(2 * sizeof(char)); and then initialize it; similarly for char *c. Then set entry->name_lower = l; entry->name_caps = c;
When allocating make sure you check whether the allocation succeeded, i.e. whether malloc returned non-NULL address.
Make sure you free the memory after you don't need it anymore: free(entry->name_lower); free(entry->name_caps);.
It will not lose anything. The pointers in the struct will retain their value, but the content will change and you will eventually get SIGSEGV.
For the char * to persist, you need to allocate it on the heap too.
void bar(foo* entry, const char* str, int delimiter_pos) {
char * l = malloc(2);
char * c = malloc(2);
/* Check l and c for NULLs */
l[0] = str[caps_pos-1];
l[1] = '\0';
c[0] = str[caps_pos+1];
c[1] = '\0';
entry->name_lower = l;
entry->name_caps = c;
}
Remember that you should also free() the struct members when you will no longer need it.
If you have a limit on the length of your strings, you can use char arrays instead of pointers. In your example, all strings have a length of 1. Assuming your strings cannot be longer than that, you can use char[2] instead of char*:
struct foo {
char name_lower[2];
char name_caps[2];
//..
};
void bar(foo* entry, const char* str, int delimiter_pos) {
entry->name_lower[0] = str[caps_pos-1];
entry->name_lower[1] = '\0';
entry->name_caps[0] = str[caps_pos+1];
entry->name_caps[1] = '\0';
}
Historical note:
Because this is so easy to use, people got accustomed to this, and forced artificial limits on string length, leading to buffer overflows. If your strings are not limited, use dynamic allocation instead of char arrays.

Converting a character pointer to uppercase in C

I have a pointer:
char * name;
it contains the string "test:case"
And I'm calling another function with it, and trying to store it in a structure. However, I want to capitalize the entire string first, but It doesn't seem to work.
void func(char * name) {
int i;
List * l;
l = malloc(sizeof(List));
for(i=0; i< strlen(name); i++) {
name[i] = toupper(name[i]);
}
l->name = name;
//CALL A FUNCTION TO LATER FREE ALLOCATED MEMORY
}
Where List is a struct that has a member (char *) named name.
This however, seg faults. I can't go about using non pointers in my case. As I have to use pointers and not character arrays, I'm trying to use toupper in every value of the char pointer, however this doesn't seem to work.
You're getting a segfault because the original string is presumably a literal, and it's not modifiable. You need to make a copy of it first.
void func(char * name) {
List * l;
l = malloc(sizeof(List));
name = strdup(name); // make a copy of name
for (char *p = name; *p; p++) {
*p = toupper(*p);
}
l->name = name;
}
Note that when you later free l, you'll first need to free l->name.
Since you only set the pointer l->name to name, this will crash the moment the original name is no longer there (maybe it was only on the stack?) and l->name is accessed. You need to malloc() space the size of strlen(name)+1, copy name there and set l->name to that address.
You have allocated the List, but not the name string itself.
You need to do:
l=malloc(sizeof(List));
l->name=(char*)malloc(strlen(name)+1); // You need to cater for the the final null char.
There are a few additional issues with your code, here is the correct one (didn't compile it, probably close to okay):
void func(char *name) {
List * l;
l = (List*)malloc(sizeof(List));
l->name = (char*)malloc(strlen(name)+1);
for(char *r=name, char *w=l->name; *r; ++r,++w) {
*w = toupper(*r);
}
*++w='\0';
}
And at every iteration, this code does not evaluate again and again strlen, which would be very bad.
There are two mistakes in the code.
char * name
The variable name contains a pointer to a string (i.e., an array of char).
When you write this:
name[i] = toupper(name[i]);
you are changing the original char itens of the string, if it is not a pointer to a constant string. If that is the case, it is a segmentation fault.
The other mistake is here:
l->name = name;
You are just assigning to the variable within the structure the pointer which was passed on through the variable name to the function. You should make a copy, like this:
strcpy(l->name, name);
This functions copies all the contents from the second argument to the first.
But that's not a good solution. If name contains a pointer to a constant string, it's still segmentation fault.
I'll rewrite your code:
void func(char * name) {
int i;
List * l;
l = malloc(sizeof(List));
char *buffer[strlen(name)]; //buffer of the contents pointed by *name* to upper case, initialized as empty string
for(i=0; i< strlen(name); i++) {
buffer[i] = toupper(name[i]);
}
buffer[i] = '\0'; //closing the string in i = strlen(name)
strcpy(l->name, buffer);
//CALL A FUNCTION TO LATER FREE ALLOCATED MEMORY
}
That way, you manipulate a copy of the original string, and than you make a copy of the buffer to the variable in the structure.
If you do this:
l->name = buffer;
you're only copying a local pointer, which will be gone with the end of the function.
I suggest you learn more about pointers, arrays and strings in C. In essence, a string is a array of char, with a '\0' in the final position. An empty string s has '\0' in s[0].
Edit: if you're used to languages which makes a copy of the string like this:
string1 = string2
you should always have in mind that, in C, that's pointer assignment. So, in C, that code would have to be written like this:
strcpy(string1, string2);
Hope that helps.

Resources