I have two char pointers:
char *temp;
char *saveAlias;
I want to assign saveAlias with whatever is stored in temp; saveAlias is currently empty while temp has a string of an unknown size saved from user input.
Note that I don't want saveAlias to point to where temp points; I want the content of temp and assign (get pointed) it to saveAlias.
I have attempted using strcat and strcpy but to no avail.
Assuming that your temp variable points to a character string that is suitably nul-terminated (as strings in C should be), then you can just use the strdup() function to make a copy of it and store a pointer to that in saveAlias. This function will duplicate the given string into newly-allocated memory; that memory should be released, using the free function, when no longer needed:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
char* temp = "source string";
char* saveAlias = strdup(temp);
printf("Temp is <%s> (at %p).\n", temp, (void*)temp);
printf("Alias is <%s> (at %p).\n", saveAlias, (void*)saveAlias);
free(saveAlias);
return 0;
}
The strdup function effectively combines malloc and strcpy into a single function call, with the call shown above being the equivalent of:
char* saveAlias = malloc(strlen(temp) + 1);
strcpy(saveAlias, temp);
If you want to allocate memory for a copy of the string currently pointed to by temp, use strdup():
#include <stdio.h>
#include <string.h>
int main() {
char buf[128];
char *temp;
char *saveAlias = NULL;
if ((temp = fgets(buf, sizeof buf, stdin)) != NULL) {
saveAlias = strdup(temp);
if (saveAlias == NULL) {
fprintf(stderr, "allocation failed\n");
} else {
printf("saveAlias: %s\n", saveAlias);
}
}
free(saveAlias);
return 0;
}
You can basically point the saveAlias to temp; Thus you would have:
saveAlias = temp;
As noted by Chris. This will make one pointer point to another.
Correcting my answer. I suggest you define de size of saveAlias with malloc, and then use the memcpy function. You will have:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(){
char *temp = "your_char";
//with malloc you make sure saveAlias will have the same size as temp
//and then we add one for the NULL terminator
char *saveAlias = (char*) malloc(strlen(temp) + 1);
//then just
strcpy(saveAlias, temp);
printf("%s\n", temp);
printf("%s", saveAlias);
return 0;
}
Thank you chqrlie for the explanation also. I was mistaken about the memcpy.
Related
I'm trying to make a replace function in C. I know there are many out there that I could copy, but I decided to make my own function in order to practice.
However, I'm stuck at this:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void replace_content(char *rep, char *with, char **text) {
int len_rep = strlen(rep);
int len_with = strlen(with);
char *p = *text;
int new_text_size = 0;
char *new_text = malloc(new_text_size);
do {
if (!strncmp(p, rep, len_rep)) {
new_text_size += len_with;
new_text = (char *) realloc(new_text, new_text_size + 1);
strcat(new_text, with);
p += len_rep;
} else {
new_text_size++;
new_text = (char *) realloc(new_text, new_text_size);
new_text[new_text_size-1] = *p;
p++;
}
} while (*p != '\0');
*text = malloc(new_text_size);
strcpy(*text, new_text);
}
int main() {
printf("Testing a replace function:\n");
char *text =
"<serviceName>\n"
" <label1>a</label1>\n"
" <label2>b</label2>\n"
" <label3>c</label3>\n"
"</serviceName>\n";
printf("Before replace:\n%s", text);
replace_content("serviceName>", "serviceNameResponse>", &text);
printf("After replace:\n%s", text);
return 0;
}
This is the output I'm seeing so far:
Testing a replace function:
Before replace:
<serviceName>
<label1>a</label1>
<label2>b</label2>
<label3>c</label3>
</serviceName>
After replace:
<0�serviceNameRespons
<label1>a</label1>
<label2>b</label2>
<label3>c</label3>
</serviceNameResponse>
My guess is that I'm doing something wrong with dynamic memory, but the more I look into my code the more confused I am.
These two statements are problematic:
new_text = (char *) realloc(new_text, new_text_size + 1);
strcat(new_text, with);
The first problem is that you should never assign back directly to the pointer you reallocate. That is because realloc may fail and return NULL, making you lose the original pointer.
The second problem is that new_text doesn't initially point to a null-terminated string, which makes the call to strcat undefined behavior.
There is also a problem in the else branch:
new_text = (char *) realloc(new_text, new_text_size);
new_text[new_text_size-1] = *p;
Besides the same problem with reassigning back to the pointer being reallocated, you don't terminate the string in new_text.
May the reason is malloc(0) in line 10 char *new_text = malloc(new_text_size);.
The malloc() function allocates size bytes and returns a pointer to
the allocated memory. The memory is not initialized. If size is 0,
then malloc() returns either NULL, or a unique pointer value that
can later be successfully passed to free().
I suggest using char *new_text = NULL; instead.
When I allocate an array using malloc, is there a way to only free the first element(s) of the array?
A small example:
#include <stdlib.h>
#include <string.h>
int main() {
char * a = malloc(sizeof(char) * 8);
strcpy(a, "foo bar");
// How I would have to do this.
char * b = malloc(sizeof(char) * 7);
strcpy(b, a+1);
free(a);
free(b);
}
Is there a way to free just the first char of a, so that I can use the rest of the string using a+1?
If you want to remove the first character of a, you could use memmove() to move the remainder of the characters in the string to the left by 1, and you could use realloc() to shrink the allocation if desired:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char * a = malloc(sizeof(char) * 8);
strcpy(a, "foo bar");
puts(a);
size_t rest = strlen(a);
memmove(a, a+1, rest);
/* If you must reallocate */
char *temp = realloc(a, rest);
if (temp == NULL) {
perror("Unable to reallocate");
exit(EXIT_FAILURE);
}
a = temp;
puts(a);
free(a);
return 0;
}
Update
#chux has made a couple of good points in the comments.
First, instead of exiting on a failure in realloc(), it may be better to simply continue without reassigning temp to a; after all, a does point to the expected string anyway, the allocated memory would just be a little larger than necessary.
Second, if the input string is empty, then rest will be 0. This leads to problems with realloc(a, rest). One solution would be to check for rest == 0 before modifying the string pointed to by a.
Here is a slightly more general version of the above code that incorporates these suggestions:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char *s = "foo bar";
char *a = malloc(sizeof *a * (strlen(s) + 1));
strcpy(a, s);
puts(a);
size_t rest = strlen(a);
/* Don't do anything if a is an empty string */
if (rest) {
memmove(a, a+1, rest);
/* If you must reallocate */
char *temp = realloc(a, rest);
if (temp) {
a = temp;
}
}
puts(a);
free(a);
return 0;
}
Is there a way to free just the first char of a
No. You can not free the first character of a because it is of char type. Only pointer returned by malloc family function can be freed.
You can do this though.
char * a = malloc(sizeof(char) * 8);
strcpy(a, "foo bar");
char * b = malloc(strlen(a));
strcpy(b, a+1);
free(a);
I am trying to take input from a user and I don't the exact length of input so therefore I am using malloc and I am splitting char by space between them and just need to print an array but I am getting warning i.e assignment makes integer from pointer without a cast on the following line:
array[i++] = p;
and my whole program is as follows:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main ()
{
char buf[] ="abc qwe ccd";
int i;
char *p;
char *array=malloc(sizeof(char));
i = 0;
p = strtok (buf," ");
while (p != NULL)
{
array[i++] = p;
p = strtok (NULL, " ");
}
for (i=0;i<3; ++i)
printf("%s\n", array[i]);
return 0;
}
Can anyone please tell me what is wrong with my code.
Thank you.
The following assignment is not right.
array[i++] = p;
array[i++] evaluates to type char. p is of type char*.
That's what the compiler is complaining about.
Judging by the way you are using array, it needs to be of type char**.
char **array = malloc(sizeof(*array)*20); // Make it large enough for your needs.
I guess you wanted to create array of pointers to char instead of array of char.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main (void)
{
char buf[] ="abc qwe ccd";
int i;
char *p;
/* change type of array from char* to char** */
char **array=malloc(sizeof(char*) * sizeof(buf)); /* allocate enough memory */
i = 0;
p = strtok (buf," ");
while (p != NULL)
{
array[i++] = p;
p = strtok (NULL, " ");
}
for (i=0;i<3; ++i)
printf("%s\n", array[i]);
free(array); /* it is good to free whatever you allocated */
return 0;
}
I am currently trying to write a simple C program that creates a struct with a char* field and assigns it to have the same value as argv[1]. I then want to create another char* with the same length as argv[1], but for some reason the data inside already contains the same value as argv[1]. Here is my code so far:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
struct example{
char *str;
};
struct example* create(char *s){
struct example *p = (struct example*)malloc(sizeof(struct example));
char * copy = (char*)malloc(strlen(s));
strcpy(copy, s);
p->str = copy;
free(copy);
return p;
}
void new_char(struct example * t){
printf("original: %s\n", t->str);
char *w = (char *)malloc(strlen(t->str));
printf("why is this a copy? %s\n", w);
free(w);
}
void clean(struct example *t){
free(t);
}
int main(int argc, char **argv){
struct example * p = create(argv[1]);
new_char(p);
clean(p);
return 0;
}
Then when I compile and run this program using GCC 6.1, I get this out put
> gcc -Wall -g -o test test.c
> ./test "test value here"
> original: test value here
> why is this a copy? test value here
this code is wrong
struct example* create(char *s){
struct example *p = (struct example*)malloc(sizeof(struct example));
char * copy = (char*)malloc(strlen(s));
strcpy(copy, s);
p->str = copy;
free(copy);
return p;
}
first you need to allocate strlen + 1
Second you cannot free 'copy' here, p->str points at it, you now have a dangling pointer. To copy and malloc use strdup http://linux.die.net/man/3/strdup
struct example* create(char *s){
struct example *p = (struct example*)malloc(sizeof(struct example));
p->str = strdup(s);
return p;
}
The reason you got the same string is because you released your string back to the heap and then got it back again when you called malloc, this is purely luck, another time you might crash, get garbage,...
Look at this lines:
char * copy = (char*)malloc(strlen(s));
...
p->str = copy;
free(copy);
return p;
You alloc a block of memory, initialize it, store a pointer to it in your structure, and then free it! From that free() on, the p->str pointer points to freed memory, that is memory that must not be used.
What happens next? You do another:
char *w = (char *)malloc(strlen(t->str));
which, by chance, gets get memory just freed from the previous code, and since malloc() does not initialize the returned memory in any way, it happens to have the same string you just used.
What you see is actually garbage (uninitialized memory) that just happens to take the shape of a recent used text.
Summing up, your code has three problems:
You free the string you are returning in create()
You do not free the string in clean() before freeing the struct.
You try to print an uninitialized chunk of memory and wonder what the garbage means.
Hrre is the problem:
char * copy = (char*)malloc(strlen(s));
strcpy(copy, s);
p->str = copy;
free(copy);
You allocated a copy of original string and immediately free it.
char *w = (char *)malloc(strlen(t->str));
This line reuses previously freed memory and that's why you get the same content - the pointer is the same.
Note this happens in very simple scenarios and is specific to c library you use.
malloc doesn't initialize the memory it allocates. The second call to malloc happened to assign the same block of memory the first call to malloc has allocated (seeing as it had become unallocated when you called free). You cannot count on this.
Errors:
You need to allocate space for the NUL too. malloc(strlen(s)) should be malloc(strlen(s)+1).
You may not access unallocated memory, as you when you print t->str and when you try to find its length. You probably didn't mean to deallocate it. free(copy); should be moved to clean as free(t->str);.
Casting the value returned by malloc is necessary in C++, but is needless in C.
Tips:
strdup is a convenient shortcut for strlen+malloc+strcpy.
If you write
typedef struct { ... } example;
instead of
struct example { ... };
you can use example instead of struct example.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
typedef struct {
char *str;
} example;
example* create(char *s){
example *p = malloc(sizeof(example));
p->str = strdup(s);
return p;
}
void new_char(example * t){
printf("original: %s\n", t->str);
char *w = strdup(t->str);
printf("%s\n", w); // Prints uninitialized memory.
free(w);
}
void clean(example *t){
free(t->str);
free(t);
}
int main(int argc, char **argv){
example * p = create(argv[1]);
new_char(p);
clean(p);
return 0;
}
Bear with me. I have not coded in c in 8 years and am totally baffled why my string manipulation is not working. I am writing a program that loops forever. In the loop I initialize two char pointers each is passed to a function that add text to the char pointer (array). When the functions are done I print the char pointer and free the two char pointers. However the program dies after 7 iterations with the following error message
* glibc detected * ./test: double free or corruption (fasttop): 0x0804a168 ***
#include sys/types.h
#include sys/stat.h
#include fcntl.h
#include string.h
#include stdio.h
#include stdlib.h
#include errno.h
#include time.h
char *SEPERATOR = "|";
void getEvent (char* results);
void getTimeStamp(char* timeStamp, int timeStampSize);
void stringAppend(char* str1, char* str2);
int main (int argc, char *argv[])
{
int i = 0;
while(1)
{
i++;
printf("%i", i);
char* events= realloc(NULL, 1);
events[0] = '\0';
getEvent(events);
char* timestamp= realloc(NULL, 20);
timestamp[0] = '\0';
getTimeStamp(timestamp, 20);
printf("%s", events);
printf("timestamp: %s\n", timestamp);
free(events);
free(timestamp);
}
}
void getEvent (char* results)
{
stringAppend(results, "a111111111111");
stringAppend(results, "b2222222222222");
}
void getTimeStamp(char* timeStamp, int timeStampSize)
{
struct tm *ptr;
time_t lt;
lt = time(NULL);
ptr = localtime(<);
int r = strftime(timeStamp, timeStampSize, "%Y-%m-%d %H:%M:%S", ptr);
}
void stringAppend(char* str1, char* str2)
{
int arrayLength = strlen(str1) + strlen(str2) + strlen(SEPERATOR) + 1;
printf("--%i--",arrayLength);
str1 = realloc(str1, arrayLength);
if (str1 != NULL)
{
strcat(str1, SEPERATOR);
strcat(str1, str2);
}
else
{
printf("UNABLE TO ALLOCATE MEMORY\n");
}
}
You are reallocating str1 but not passing the value out of your function, so the potentially changed pointer is leaked, and the old value, which has been freed by realloc, is freed again by you. This causes the "double free" warning.
The problem is that while stringAppend reallocates the pointers, only stringAppend is aware of this fact. You need to modify stringAppend to take pointer-to-pointers (char **) so that the original pointers are updated.
This line in stringAppend:
str1 = realloc(str1, arrayLength);
changes the value of a local variable in stringAppend. This local variable named str1 now points to either the reallocated memory or NULL.
Meanwhile local variables in getEvent keep the values they had before, which now usually point to freed memory.
All the comments where very helpfull. Of course it makes total sense why the error was happening. I ended up solving it by making the following changes.
For both the getEvent and stringAppend I return the char pointer.
e.g.
char* stringAppend(char* str1, char* str2)
{
int arrayLength = strlen(str1) + strlen(str2) + strlen(SEPERATOR) + 1;
printf("--%i--",arrayLength);
str1 = realloc(str1, arrayLength);
if (str1 != NULL)
{
strcat(str1, SEPERATOR);
strcat(str1, str2);
}
else
{
printf("UNABLE TO ALLOCATE MEMORY\n");
}
return str1;
}
This isn't an answer to your question (and you don't need one, since the error has been pointed out), but I do have some other comments about your code:
char* events= realloc(NULL, 1);
events[0] = '\0';
You don't test that realloc successfully allocated memory.
char* timestamp= realloc(NULL, 20);
timestamp[0] = '\0';
Same problem here. In this case, you don't need realloc at all. Since this is a fixed-size buffer, you could use just:
char timestamp[20] = "";
And don't do this:
str1 = realloc(str1, arrayLength);
because if realloc fails, you'll orphan the memory that str1 was pointing to before. Instead:
char* temp = realloc(str1, arrayLength);
if (temp != NULL)
{
str1 = temp;
...
}
Note that since you're modifying stringAppend to return the new string, you should do similar checks in the calling functions.
Also, "separator" is spelled with two As, not with two Es.