C array elements poiting to same location - c

Need some help please. I have the following code.
char *lines[100];
int i;
for (i = 0; i < 100; i++)
{
char temp[10];
_itoa_s(i, temp,10);
char result[10] = "test";
strcat_s(result, temp);
lines[i] = (char*)malloc(sizeof(char));
lines[i] = result;
}
for (i = 0; i < 100; i++)
{
cout << lines[i] << endl;
}
Why does it print :
test99
test99
test99
...
It turns out that char result[10] will point to the
same memory location. Why ? Was expecting something like this :
test1
test2
test3
...

The first line here is a basically NOOP (actually it is creating a memory leak because you throw away the pointer returned by malloc by overwriting it on the next line).
lines[i] = (char*)malloc(sizeof(char)); // this is a basically a NOOP
lines[i] = result;
It's more or less like writing:
foo = 5;
foo = result;
So your code ends up like this:
for (i = 0; i < 100; i++)
{
char temp[10];
_itoa_s(i, temp,10);
char result[10] = "test";
strcat_s(result, temp);
lines[i] = result; // copying just the pointer,
}
So all lines[i] contain the pointer to the same memory location result.
Also the scope of result is limited to the part between {}, so once the for loop is terminated, result is likely to be overwritten at the next occasion.
You need this:
char *lines[100];
for (int i = 0; i < 100; i++)
{
char temp[10];
_itoa_s(i, temp,10);
char result[10] = "test";
strcat_s(result, temp);
lines[i] = (char*)malloc(sizeof(char) * strlen(result) + 1);
// ^string length ^space for NUL terminator
strcpy(lines[i], result); // actually copying the the string (not only the pointer)
}
You also need to free the allocated memory once you're done with it:
for (i = 0; i < 100; i++)
{
free(lines[i]);
}

In your code, due to
lines[i] = result;
all the pointers end up pointing to the same result, the last one.
You may want to use strcpy() if you're interested in the content.
But wait, there's another problem. You're written
lines[i] = (char*)malloc(sizeof(char));
which allocates 1 byte of memory, which is here, good for nothing. Before you use the pointer as destination in strcpy(), you need to make sure that the pointer points to sufficient memory, including the terminating null, to hold the concatenated string.
Advice: The devil is in the details. perform a careful study of the language before performing trial and error.

Related

A simple C exercise going wrong: Trying to return a pointer to an array of two strings

"Return a pointer to an array of two strings. The first is the characters
of string s that are at even indices and the second is the characters from
s that are at odd indices"
char **parity_strings(const char *s) {
char** parity = malloc(sizeof(char*) * 2);
char even_strings[] = "";
char odd_strings[] = "";
int x = 0;
int y = 0;
for (int i = 0; i < strlen(s); i++) {
if ((i % 2) == 0) {
even_strings[x] = s[i];
x++;
}
else {
odd_strings[y] = s[i];
y++;
}
}
parity[0] = even_strings;
parity[1] = odd_strings;
return parity;
}
int main(int argc, char **argv) {
char **r = parity_strings(argv[1]);
printf("%s %s %s", r[0], r[1], argv[1]);
return 0;
}
My logic makes sense but the output is always incorrect. For example, with input ababab I get back ababab while the expected output is aaa bbb ababab. What did I do wrong?
The string named even_strings is a local variable, so its memory will be freed after your function returns, so it is not valid to try to return a pointer to it to the caller.
Try changing this line:
char even_strings[] = "";
to something like this:
char * even_strings = malloc(some_size);
The same goes for your odd_strings string.
Also, be sure to pick a good value for some_size so that your program allocates enough memory for each string so that it can hold all the data you are writing to it.
even_strings and odd_strings are arrays of size 1 each. Your code writes out of bounds (even_strings[x] = s[i], odd_strings[y] = s[i]). Furthermore, they're local variables that cease to exist once parity_strings returns, so the returned pointers are garbage.

copying portions of string, which are stored in a char array, to another array

I wanted to try and copy parts of strings which are already stored in one array of strings to another empty array. (I think called array of pointers to char arrays )
I would like to copy the first 3 characters of each string and store them in the second array and then print them out - like so
AAA
BBB
CCC
DDD
EEE
FFF
Here is my code.
void main()
{
/*ARRAY 1*/
char *line1 = "AAAAA";
char *line2 = "BBBBB";
char *line3 = "CCCCC";
char *line4 = "DDDDD";
char *line5 = "EEEEE";
char *line6 = "FFFFF";
char *array1[6];
array1[0] = line1;
array1[1] = line2;
array1[2] = line3;
array1[3] = line4;
array1[4] = line5;
array1[5] = line6;
int i;
char *array_main[6];
for(i = 0; i<6 ; i++ ) {
array_main[i] = ("%*.*s\n",1,3,array1[i]);
printf("%s", array_main[i]);
printf("\n");
}
}
do i need to do a malloc here ? (for array_main[i]) from what i understand, I am basically just copying the address of the particular characters to array_main's elements.
EDIT - Sorry, I should have made this clearer, I want to collect the strings in array_main and then print them in order outside of the loop which actually copies the data.
You are copying pointers to statically declared strings to an array. That's theoretically fine. Howevery, you want to cut off the remainder of the strings, so you need to prepare memory for the target strings, because if you write to the strings you will invoke undefined behaviour.
This line:
array_main[i] = ("%*.*s\n",1,3,array1[i]);
definitely doesn't do what you want though. I think this shouldn't even compile.
You loop over the array and malloc the appropriate size of bytes (3+1), then copy over the parts of the string that you want (don't forget the 0-byte at the end).
So it should look like this:
for(i = 0; i < 6; i++)
{
array_main[i] = malloc(4);
snprintf(array_main[i], 4, "%.3s", array[i]);
printf("%s\n", array_main[i]);
free(array_main[i]);
}
A simpler version (with unneccessary memeory overhead) would be this:
for(i = 0; i < 6; i++)
{
array_main[i] = strdup(array[i]);
array_main[i][3] = 0;
printf("%s\n", array_main[i]);
free(array_main[i]);
}
#include <stdio.h>
#include <string.h>
int main(void){
const char *array1[6] = {"AAAAA", "BBBBB", "CCCCC", "DDDDD", "EEEEE", "FFFFF" };
char array_main[6][4] = {{0}};//4 : 3 + 1 (+1 for End of string('\0'))
int i;
for(i = 0; i<6 ; i++ ) {
strncpy(array_main[i], array1[i], 3);
printf("%s\n", array_main[i]);
}
return 0;
}

How to empty a 2d char array in C?

I am still new with C and I am trying to empty a 2d char array. Here is the declaration:
char arg_array = (char**)calloc(strlen(buf), sizeof (char**));
for(i = 0; i<(strlen(buf)); i++)
{
arg_array[i] = (char*) calloc (strlen(buf), sizeof(char*));
}
Here is where I try to empty it:
void make_empty(char **arg_array)
{
int i;
for(i = 0; i <= BUFSIZ; i++)
{
arg_array[i][0] = '\0';
}
return;
}
Any help is appreciated
So, am I doing it right because this seems to give me segfaults when I try to add data to the array again and then print it?
Empty is just to have it empty - how can I explain more? lol
Try this:
void make_empty(char **arg_array, int rows, int cols)
{
int i,j;
for(i = 0; i <rows; i++)
{
for(j=0; j<cols;j++)
{
arg_array[i][j] = '\0';
}
}
return;
}
Where rows is number of rows and cols number of cols of your array.
P.S. This function clears the whole array as you should always do. As I commented before, putting '\0' as a first char in string does not clear the whole row, it only makes the rest of it ,,invisible'' for functions like printf. Check this link for more information: http://cplusplus.com/reference/clibrary/cstdio/printf/
There is no need to empty it. Often in C, memory allocation is done with malloc which simply returns to you a block of memory which is deemed owned by the caller. When calloc is called, as well as returning you a block of memory, the memory is guaranteed to be initialized to 0. This means for all intents and purposes it is already 'empty'.
Also I'm not quite sure if your code does what you are intending. Let me explain what it does at the moment:
char arg_array = (char**)calloc(strlen(buf), sizeof (char**));
This line is simply wrong. In C, there is no need to cast pointers returned from calloc because they are of type void *, which is implicitly casted to any other pointer type. In this case, you are storing it in a char type which makes no sense. If you do this:
char ** arg_array = calloc(strlen(buf), sizeof (char**));
Then it allocates an array of pointers of strlen(buf) length. So if buf is "hello" then you have now allocated an array which can store 5 pointers.
for(i = 0; i<(strlen(buf)); i++)
{
arg_array[i] = calloc (strlen(buf), sizeof(char*));
}
Again, I have removed the redundant cast. What this does is populates the array allocated earlier. Each index of the array now points to a char string of strlen(buf) * sizeof(char *) length. This is probably not what you want.
Your question is more clear to me now. It appears you want to remove the strings after populating them. You can do it two ways:
Either free each of the pointers and allocate more space later as you did before
Or set the first character of each of the strings to a null character
To free the pointers:
for(i = 0; i<(strlen(buf)); i++)
{
free(arg_array[i]);
}
To set the first character of each string to a null character:
for(i = 0; i<(strlen(buf)); i++)
{
arg_array[i][0] = '\0';
}
That is the same code as what you have originally and should be fine.
As proof, the following code will run without errors:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main(void)
{
char * buf = "hello";
char ** arg_array = calloc(strlen(buf), sizeof (char**));
unsigned int i;
for(i = 0; i < strlen(buf); i++) {
arg_array[i] = calloc(strlen(buf),
sizeof(char *));
}
for(i = 0; i < strlen(buf); i++) {
arg_array[i][0] = '\0';
}
for(i = 0; i < strlen(buf); i++) {
free(arg_array[i]);
}
free(arg_array);
return EXIT_SUCCESS;
}
If your code is segfaulting, the problem is coming from somewhere else. Did you overwrite the arg_array variable? Are you sure BUFSIZE is equal to strlen(buf)?

How to create a new array but use the same variable in C?

The reason why I am stuck on this is because of how C handles arrays, which is through pointers which I am new at. This is my case(not exactly my problem but a simplistic case):
char *keywords[k_num_of_keywords];
for(int i = 0; i < k_num_of_keywords; i++) {
char temp[] = "float";
keywords[i] = temp;
}
In this case, it would put float in all the indexes, but more importantly, the same address of wherever the string "float" is located. My case is slightly different, because I want to automate initializing a new char array for each index, but still use the same variable, rather than the same address in each index. How can I accomplish this in a for loop?
You should allocate memory for every element for "keywords", for example:
char *keywords[k_num_of_keywords];
for(int i = 0; i < k_num_of_keywords; i++) {
char temp[] = "float";
int len = strlen(temp);
keywords[i] = (char *)malloc(sizeof(char) * (len + 1));
memcpy(keywords[i], temp, len + 1);
}

C dynamic string array

I have char * lines[1000] string that can hold 1000 characters. How to create 100 arrays of that string. I get error with this code down.
char * lines[1000];
lines = (lines*)malloc(100 * sizeof(lines));
main.c:19:20: error: expected expression before ')' token
The simplest way is:
char lines[100][1000];
Alternatively:
char* lines[100];
int i;
for (i = 0; i < 100; i++) {
lines[i] = malloc(1000);
}
...
for (i = 0; i < 100; i++) {
free(lines[i]);
}
The latter is a bit more flexible in that -- with minor modifications -- it permits you to allocate a different amount of memory for every string.
It looks like you want an array strings, each string holding at most 1000 characters. There are some issues with your code.
You've declared an array of char *s but what you really want is a pointer to an array of chars. For that, your declaration should be
char (*lines)[1000];
On the other hand, you shouldn't forget about the NULL bytes at the end of strings, and should probably instead declare
char (*lines)[1001];
To set the pointer, you'll want to use
lines = (char (*)[1001]) malloc(100 * sizeof(char[1001]));
or
lines = (char (*)[1001]) malloc(100 * sizeof(*lines));
the latter working because, with lines a pointer to an array of chars, *lines is a char[1001]. Remember to make sure you didn't get a NULL pointer back.
At the end, you should free the memory you've malloced with
free(lines);
You can write a for-loop as:
char * lines[1000];
int i = 0;
for (i = 0; i < 1000; i++)
{
lines[i] = (char*)malloc(100 * sizeof(lines));
}
Don't forget to free-up the memory pointed by all the pointers
for (i = 0; i < 1000; i++)
{
free(lines[i])
}
Why don't you create a 2 dimensional array?

Resources