соединяя две строки с Malloc - PullRequest
0 голосов
/ 09 января 2019

Я работал над проблемой C для начинающих, чтобы попытаться изучить основы C. Я заметил, что нижеприведенная проблема будет начинаться с индекса, где взлетает последняя строка, и заканчивает эту строку, но то, что я пытаюсь сделать, это соединить две строки вместе.

Кто-нибудь может указать мне правильное направление? Я пытаюсь сделать это без realloc для изучения XP.

char *string_dup(char *src)
{
  int len = strlen(src);
  char *src2 = malloc(len + 1);
  int i;
  for(i = 0; i < len; i++){
    *(src2 + i) = *(src + i);
  }
  *(src2 + len )='\0';
  return src2;
}

void *resize_memory(void *ptr, int old_size, int new_size)
{
    char *d = (char*)ptr;
    d = malloc(new_size);
}


char *url = string_dup("http://");
char *path = string_dup("website.com/");
int url_length = string_length(url);
int path_length = string_length(path);

int new_length = url_length - 1 + path_length;
char *new_url = resize_memory(url, url_length, new_length);
char *p = new_url + url_length;


while (*path != '\0') {
    *p = *path;
    p++;
    path++;
}

printf("Full path string: %s\n", new_url);

Ответы [ 3 ]

0 голосов
/ 09 января 2019

Я немного поэкспериментировал с вашим кодом, затем придумал это решение. Это позволяет вам избавиться от этой функции string_dup() и создать одну функцию, которая может выделять / назначать новую строку и добавлять существующую строку с большим количеством данных.

int
append_string(char **append_to, char *append_this) {
    char    *tmp;

    // You might want to check that append_this is not
    // NULL...

    if (*append_to == NULL) {
        *append_to = malloc(strlen(append_this) + 1);
        strcpy(*append_to, append_this);
    }
    else {
        // Some data already exists on the append_to buffer...
        //
        // If you want to only use malloc() then make a temporary
        // storage area and copy the append_to string there
        //
        if ((tmp = malloc(strlen(*append_to) + 1)) == NULL)
            return -1;
        strcpy(tmp, *append_to);

        // Free up and re-allocate append_to.
        //
        free(*append_to);
        *append_to = malloc(strlen(tmp) + strlen(append_this) + 1);

        if (! append_to) {
            fprintf(stderr, "Malloc error...");
            exit(EXIT_FAILURE);
        }

        // Do it with realloc
        //
        // No temporary buffer required:
        //
        //      *append_to = realloc(
        //          *append_to,
        //          (strlen(append_to) + strlen(*append_this) + 1)
        //      );
        //      if (! eppend_to) ...realloc error

        // Copy the data to the buffer and clean up.
        //
        sprintf(*append_to, "%s%s", tmp, append_this);
        free(tmp);
    }
}


/* In your main() or whatever... */

    char *url = NULL;
    char *path = NULL;

    // Since url and path are both NULL the
    // append string function will act like
    // your string_dup() function...
    append_string(&url, "http://");
    append_string(&path, "website.com/");

    // And not that url is not null it will be
    // resized and the path appended.
    append_string(&url, path);

    fprintf(stdout, "URL: %s\n", url);

    // Some housekeeping....
    if (url) free(url);
    if (path) free(path);
}

Надеюсь, что это полезно, я знаю, что это немного отличается от того, что у тебя было изначально, но я подумала, что буду подыгрывать!

0 голосов
/ 09 января 2019

Проблема с кодом ОП:

Неправильный размер

Предположим, string_length() похоже на strlen().

// int new_length = url_length - 1 + path_length;
int new_length = url_length + 1 + path_length;

Неэффективное изменение размера

void *resize_memory(void *ptr, int old_size, int new_size) {
    char *d = (char*)ptr; // assign `d`
    d = malloc(new_size); // Why re-assigned `d`???
    // No use of old_size, new_size
    // No copying of existing data 
    // No freeing of old allocation  
}

Я бы ожидал что-то вроде

// return failure status
bool resize_memory(void **ptr_addr, size_t old_size, size_t new_size) {
  void *new_ptr = NULL;
  if (new_size > 0) {
    new_ptr = malloc(new_size);
    if (new_ptr) {  // Out of memory, leave *ptr_addr alone
      return true;
    }
    size_t min_size = old_size < new_size ? old_size : new_size;
    memcpy(new_ptr, *ptr_addr, min_size);
  }
  free(*ptr_addr);
  *ptr_addr = new_ptr;  
  return false;
}

Способы объединения строк с realloc() с выделением.

  1. Найти длину.
  2. Выделить память.
  3. В случае успеха скопируйте первую, а затем вторую строку. Добавить \ 0.

Пример кода:

// s1, s2 may be NULL.  A NULL is treated as if ""
char *JoinStrings(const char *s1, const char *s2) {
  size_t len1 = s1 ? strlen(s1) : 0;
  size_t len2 = s2 ? strlen(s2) : 0;
  char *joined = malloc(len1 + len2 + 1);
  if (joined) {
    memcpy(joined, s1, len1);
    memcpy(joined + len1, s2, len2);
    joined[len1 + len2] = '\0';
  }
  return joined;
}

или через snprintf()

char *JoinStrings(const char *s1, const char *s2) {
  size_t sz = (s1 ? strlen(s1) : 0) + (s2 ? strlen(s2) : 0) + 1;
  char *joined = malloc(sz);
  if (joined) {
    int len = snprintf(joined, sz, "%s%s", s1, s2);
    assert(len >= 0 && (unsigned) len < sz);  // Failure is very unexpected here.
  }
  return joined;
}

Для объединения вроде (* s1) + = s2

// *s1 is a prior allocated string, or NULL
 void ConcatenateString(char **s1, const char *s2) {
  char *joined = JoinStrings(*s1, s2);
  free(*s1);
  *s1 = joined;
}
0 голосов
/ 09 января 2019

Попробуйте что-то вроде

char *url = string_dup("http://");
char *path = string_dup("website.com/");
size_t sTotal = strlen(url) + strlen(path) + 1u;
char *pStr = malloc(sTotal);
snprintf(pStr, sTotal, "%s%s", url, path);
free(url);
free(path);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...