Создать вектор символов из функции

#c #string #function #malloc

#c #строка #функция #malloc

Вопрос:

Предположим, я хочу создать новую строку из заданной строки (в качестве параметра функции) и вернуть новую строку.

Когда метод вызывается в main, новая строка никогда не создается, и я не понимаю почему.

Вот мой код в функции вне main:

 char* new_name(char* name)
{
  char* res = (char*)malloc(strlen("recv")   strlen(name));
  if(res == null)
  {
    return null;
  }

  else
  {
    memcpy(amp;res, "recv_", strlen("recv_"));
    strcat(res, name);
  }
    return res;
}
  

И в основном у меня есть:

 char * result = new_name(name);
  

Где определено и задано «имя».

Комментарии:

1. Вы должны передавать res как есть, а не его адрес.

2. malloc Достаточно ли у вас места для вашей новой строки? Похоже, что это слишком коротко.

Ответ №1:

в

   char* res = (char*)malloc(strlen("recv")   strlen(name));
  

вам нужно выделить «recv_», а не «recv» из-за кода после, и выделить еще 1, чтобы было место для завершающего символа null, поэтому

 char* res = (char*)malloc(strlen("recv_")   strlen(name)   1);
  

В

  if(res == null)
 {
   return null;
 }
  

null должно быть NULL

В

 memcpy(amp;res, "recv_", strlen("recv_"));
  

должно быть

 memcpy(res, "recv_", strlen("recv_")   1);
  

в противном случае вы изменяете не выделенный массив, а стек по адресу переменной res, и вам также нужно поместить завершающий символ null, поэтому я просто добавляю 1 к количеству символов для копирования

обратите внимание, является ли это более простым в использовании strcpy : strcpy(res, "recv_")


Пример :

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

char* new_name(char* name)
{
  char* res = (char*)malloc(strlen("recv_")   strlen(name)   1);

  if(res == NULL)
  {
    return NULL;
  }

  else
  {
    memcpy(res, "recv_", strlen("recv_")   1); /* or strcpy(res, "recv_"); */
    strcat(res, name);
  }
  return res;
}

int main()
{

  char * result = new_name("foo");

  printf("'%s'n", result);
  free(result);
  return 0;
}
  

Компиляция и выполнение :

 pi@raspberrypi:~ $ gcc -pedantic -Wall -Wextra m.c
pi@raspberrypi:~ $ ./a.out
'recv_foo'
  

Выполнение в valgrind :

 pi@raspberrypi:~ $ valgrind ./a.out
==22335== Memcheck, a memory error detector
==22335== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==22335== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==22335== Command: ./a.out
==22335== 
'recv_foo'
==22335== 
==22335== HEAP SUMMARY:
==22335==     in use at exit: 0 bytes in 0 blocks
==22335==   total heap usage: 2 allocs, 2 frees, 1,033 bytes allocated
==22335== 
==22335== All heap blocks were freed -- no leaks are possible
==22335== 
==22335== For counts of detected and suppressed errors, rerun with: -v
==22335== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 6 from 3)
  

Комментарии:

1. Большое вам спасибо! У меня возникли проблемы с функцией memcpy. С strcpy это намного лучше!

2. @Xyz да, когда вы работаете со строкой, лучше использовать функцию для строки, а не для «памяти»

Ответ №2:

Альтернативное решение могло бы гласить:

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

char *new_name(char *name) {
    char const prefix[] = "recv_";
    // Figure out size needed
    int sz = snprintf(NULL, 0, "%s%s", prefix, name);
    sz  ; // make room for '' at end
    char *res = malloc(sz);
    if (res == NULL) {
        return NULL;
    }
    (void) snprintf(res, sz, "%s%s", prefix, name);
    return res;
}
  

Или, чтобы избежать подсчета длины name более одного раза,

 char* new_name(char* name)
{
  char const prefix[] = "recv_";
  size_t const pre_len = sizeof prefix - 1U;
  size_t const name_len = strlen(name)   1U;
  char* res = (char*)malloc(pre_len   name_len);
  if(res)
  {
    memcpy(res, prefix, pre_len);
    memcpy(res   pre_len, name, name_len);
  }
  return res;
}