【问题标题】:C - create a string "from" struct parameterC - 创建一个字符串“来自”结构参数
【发布时间】:2013-07-17 02:05:59
【问题描述】:

有一个

typedef struct person {
    char name[20]
    char surname[20]
} person_t;

我需要创建一个类似XXXXXX:YYYYYY 的字符串,其函数如下 char* personToString(person_t *p)。我试着做到了:

char* personToString(person_t* p) {

  int n1,n2;
  n1=strlen(p->name);
  n2=strlen(p->surname);
  char *p = (char*) malloc((n1+n2+2)*sizeof(char));
  strcat(p,puser->name);
  strcat(p,":");
  strcat(p,puser->surname);

  return p;
}

这给了我一个合理的输出,但我在使用 valgrind 测试时遇到了一些错误!我也认为有一种更优雅的方法来编写函数!

【问题讨论】:

  • 包括与问题相关的错误。
  • 你可以用sprintf代替strcat,比如sprintf(p, "%s:%s", p->name, p->surname);,加上你覆盖p,你把它作为参数,然后将它声明为char *而你没有@987654330 @你的char *
  • sizeof(char) 不是必需的,因为它总是1
  • 不应该是struct person *p而不是person_t,因为person_t是一个对象而不是typedef
  • 我是 addinf 也是 char ':' 所以我想我需要 +2!我尝试 +1 并给我错误

标签: c string strcat


【解决方案1】:

这对我来说很好,

char* personToString( struct person_t *p )
{
  int len = strlen(p->name) + strlen(p->surname) + 2; // holds ':' + NULL 
  char *str = malloc( len ); // Never cast malloc's return value in C

  // Check str for NULL
  if( str == NULL )
  {
      // we are out of memory
      // handle errors
      return NULL;
  }

  snprintf( str, len, "%s:%s", p->name, p->surname);

  return str;
}

注意:

  1. 永远不要在 C 中转换 malloc 的返回值。
  2. 当需要多个strcat 时使用snprintf,它很优雅。
  3. free返回值str在调用者这里。

修复了 structchar 变量

【讨论】:

  • 不应该是struct person *p而不是person_t,因为person_t是一个对象而不是typedef
  • 不错的答案其实我有建议将评论 Never cast malloc's return value 更改为 Never cast malloc's return value in C
  • 不需要 snprintf,sprintf 就足够了,因为您确保缓冲区足够大。顺便说一句,它是 p,而不是 puser。而且 snprintf 行中的右大括号太多了。
  • 检查 p 是否为 NULL,而不是我可能设置 errno 的值?赞:if(p==NULL) { errno = EINVAL; return NULL; }好不好?
  • @WernerHenze snprintf() 这里不需要(因为分配正确),但它更可取且安全。
【解决方案2】:

首先你应该调用字符串复制,然后是strcat:

strcat(p,puser->name);

应该是:

strcpy(p,puser->name);

因为使用 malloc 函数分配的内存将值保留为垃圾,所以首先执行 strcat 是在垃圾之后连接 - 它还会在代码中带来未定义的行为。

你可以用void* calloc (size_t num, size_t size);代替malloc(),calloc函数用0初始化分配的内存(然后strcat()没问题)。 同样动态分配的内存,您应该明确使用void free (void* ptr);) 解除分配内存块。

【讨论】:

  • 只是为了补充答案,Valgrind 可能会抱怨没有 freeing 内存
【解决方案3】:

你需要

strcpy(p,puser->name);

不是

strcat(p,puser->name);

malloc 不会将缓冲区初始化为零,因此 strcat 会首先在 p 中搜索一个空字节,并且可能找不到一个空字节,读取到缓冲区的末尾并因此崩溃。

您也可以编写一个对 sprintf 的调用,而不是一个 strcpy 加两个 strcat:

sprintf(p, "%s:%s", puser->name, puser->surname);

【讨论】:

  • 你是对的 :D 非常感谢! (st**id 对我来说是错误的)即使它运行良好,你是否认为有一种更优雅的方式来编写代码?
  • Werner,你打败了我们,你的方法更适合连接多个字符串。 +你的答案。不错
  • @user2590319 我会使用 sprintf。 VoidPointer 的实现在我看来相当不错。
【解决方案4】:

当您为p 分配内存时,内存将保存垃圾值。 strcat 将在空字符后附加一个字符串,但在未初始化的字符串中将保存随机值。

将第一个 strcat 替换为 strcpy。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-07
    相关资源
    最近更新 更多