1
typedef struct element element;
struct element{
    dado_t str;
    elemento* preview;
    elemento* next;
};

typedef struct lista2 lista2;
struct lista2{
    elemento* primeiro;
    elemento* ultimo;
    elemento* corrente;
};


void caller(lista2* l){
    char *s = l->corrente->str;
    char *s2 = l->corrente->next->str;
    my_func(&s, &s2);
}

void my_func(char **s, char**s2){
    size_t len = strlen(*s);
    size_t len2 = strlen(*s2);
    char *w = *s;
    char *tmp = realloc(w, len + len2 + 1); //PROBLEM HERE
    if(tmp != NULL)
       *s = tmp;
    else
        *s = NULL;
    strcat(*s, *s2);
}  

When I run my code(before realloc()):

  • *w = "I Like Coffe" with memory adress: 0x605050
  • *s = "I Like Coffe" with memory adress: 0x605050
  • l->corrente->str = "I Like Coffe" with memory adress: 0x605050

All good so far.
Now status after realloc(Before the assign *s = tmp):

  • *w = "" with memory adress: 0x605050
  • *s = "" with memory adress: 0x605050
  • l->corrente->str = "" with memory adress: 0x605050

Still ok, right ? Now what I get after *s = tmp:

  • *w = "" with memory adress: 0x605050
  • *s = "I Like Coffe" with memory adress: 0x605160 CHANGED
  • l->corrente->str = "" with memory adress: 0x605050

What I need:
1) Change l->corrente->str value in my_func();
2) Or somehow, change *s value to the new value after strcat. And keep l->corrente->str the same.

7
  • You make *s NULL and then do strcat(*s ...) why? the whole point is to prevent undefined behavior which you are invoking, rather you should free(*s). Also, I don't get your question, where in your code is *s = "I Like Coffe"? may be you need some Coffe? ;) Commented May 15, 2015 at 2:50
  • *s = l->corrente->str. And l->corrente->str = "I Like Coffe". I just think there is no need to show another function. Commented May 15, 2015 at 2:53
  • Yes there is, there is a huge difference in the assignments you show above, if you use realloc() with "I Like Coffe"'s address then nothing good will happen, but you can't be sure what in fact it will be. Commented May 15, 2015 at 2:54
  • See also realloc() setting pointer to empty for a variant of this code. Commented May 15, 2015 at 4:07
  • dado_t not defined, elemento not defined. Please fix these items then add the required #include statements for the header files. then repost the code. Commented May 16, 2015 at 1:54

1 Answer 1

1

If I understand you correctly and you want to create a concatenated value while keeping *s or l->corrente->str the same, then it would make more sense to have my_func return a pointer to the new concatenated string while keeping both input strings unchanged. If I don't understand what your are attempting to do, please leave a comment.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char *my_func(char *s, char*s2);

int main (void) {

    char *a = strdup ("I like coffee.");
    char *b = strdup ("I like tea.");

    char *c = my_func (a, b);

    printf ("\n a: %s\n b: %s\n c: %s\n\n", a, b, c);

    return 0;
}

char *my_func(char *s, char*s2)
{
    size_t len = strlen(s);
    size_t len2 = strlen(s2);
    char *w = strdup (s);

    char *tmp = realloc(w, len + len2 + 1); //PROBLEM HERE

    if(!tmp) {
        fprintf (stderr, "%s() error: realloc failed.\n", __func__);
        return NULL;
    }

    w = tmp;
    strcat(w, s2);

    return w;
}

Output

$ ./bin/realloc_post

 a: I like coffee.
 b: I like tea.
 c: I like coffee.I like tea.

void - preserving *s, concatenate in *s2

Instead of returning a pointer, this implementation of my_func remains void and takes s and s2, keeping s unchanged, but concatenating "ss2" in s2. If I misunderstood again, let me know.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void my_func(char **s, char **s2);

int main (void) {

    char *a = strdup ("I like coffee.");
    char *b = strdup ("I like tea.");

    my_func (&a, &b);

    printf ("\n a: %s\n b: %s\n\n", a, b);

    free (a);
    free (b);

    return 0;
}

void my_func(char **s, char **s2)
{
    size_t len = strlen(*s);
    size_t len2 = strlen(*s2);
    char *w = strdup (*s);
    char *p = *s2;          /* save start address to free */

    char *tmp = realloc(w, len + len2 + 1);

    if(!tmp) {
        fprintf (stderr, "%s() error: realloc failed.\n", __func__);
        return;
    }

    strcat(tmp, *s2);
    *s2 = tmp;
    free (p);
}

Output

$ ./bin/realloc_post

 a: I like coffee.
 b: I like coffee.I like tea.
Sign up to request clarification or add additional context in comments.

7 Comments

I can't change the void type. And yes I want to concatenate s and s2. Put the whole s2 string in the end of s2.
@PlayHardGoPro, OK, I have rewritten my_func as void to "Put the whole s2 string in the end of s2". If I missed the mark again, let me know. I think I understood you this time.
Nice! Never heard of this strdup(). But one strange thing happen. When I do strdup() it gives w address X then when I make realloc it gives the same X address to char *tmp. Apparently it worked (I'll test), but is that normal ?
Yes. strdup is an allocate, then copy function that duplicates the string in a new address. When you realloc you can get a new address or the same address depending on whether sufficient space exists at the end of the current block of memory. So that may or may not happen. Basically all I did was make a copy of s in w, then realloc'ed w and concatenated s2 on the end, then assigned s2 the new pointer.
You Rock ! Thanks David. Worked Perfect !
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.