【问题标题】:Concatenate two strings with a null in the middle连接两个中间为空的字符串
【发布时间】:2013-10-24 18:02:40
【问题描述】:

我正在尝试构建一个由两个变量组成的字符串,这些变量被一个空终止符分隔。对于我们正在使用的自定义协议,必须以这种方式完成。

const char* vendorChar = "3333-3333-4444-aaa3-3333";
const char* userChar = "someUsername";

char usernameString[strlen(vendorChar) + strlen(userChar) + 1];
char* uPtr = usernameString;

strcpy(uPtr, vendorChar);
strcpy(uPtr+strlen(vendorChar)+1, userChar);

当我运行上面的代码时,它只发送 vendorChar 的值而忽略 userChar。当它工作时,它应该看起来像

4444-2222-3333-1111\0someUsername

到目前为止,我已经了解到str 函数将删除 null,因为它在字符串末尾看到它。我想我必须使用memcpy 来保存它,但我不知道怎么做。

【问题讨论】:

  • 您是否使用调试器来找出 uPtr 的值?那些通常在点击 \0 时停止显示 C 字符串的内容。第二个字符串可能在那里,只是没有显示。
  • 空字符停止字符串读取。
  • 您的代码在我看来是正确的。你确定它因为其他原因不起作用吗?尝试单步调试并打印 uPtruPtr+strlen(vendorChar)+1
  • 您只显示了将字符放入usernameString 的代码。您没有显示“发送”usernameString 内容的代码。显示该代码。
  • 你的代码不是C,而是Objective-C,

标签: c string concatenation


【解决方案1】:

你的假设是对的,strcpy 可能会复制到中间的空字符, 根据thisstrcpy(char *str1, const char *str2) 这样做:

将 str2 指向的字符串复制到 str1。 复制到并包括 str2 的空字符。如果 str1 和 str2 重叠,则行为未定义。

memcpy 应该可以解决这个问题,因为它只是将内存视为一个字节块,而不是一个字符串。

strcpy 签名:

char *strcpy(char *dest, const char *src);

memcpy 签名:

void *memcpy(void *dest, const void *src, size_t n);

所以只需替换名称并添加累积长度(当然是两个空字符)。

编辑

为了消除这里提出的一些疑问,请考虑以下代码:

#include "string.h"
#include "stdio.h"
int main() {

    char x[10] = {0};
    char y[10];
    char z[10];
    x[0] = x[1] = x[5] = 'a';
    memcpy(y,x,10);
    strcpy(z,x);
    printf ("y[5]= %s\n", &y[5]);
    printf ("z[5]= %s\n", &z[5]);
    return 0;
}

结果是:

y[5]= a
z[5]=

所以很明显 memcpy 移动了整个长度,包括字节 [5],而 strcpy 没有,在空终止处停止

【讨论】:

  • @EricPostpischil,如果 strcpy 的行为与上面的引用相同,您能否解释一下它是如何不是问题的?
  • 如果您建议strcpy 是问题,因为它用于稍后复制uPtr,在未显示的代码中,如果这确实是uPtrusernameString 正在被复制。我以为你是在建议我们到目前为止显示的代码中的strcpy 调用是一个问题。他们不是。
  • 我将我的两个strcpys 都更改为memcpy 并使用正确的大小,它可以工作!除了一件事,它还发送了一个字节的垃圾。因此,当我查看数据包时,它看起来像 3333-3333-3333.someUsername.!. . 是空终止符
  • @EricPostpischil,哦,我只是指他的假设,即 strcpy 会在 null 处停止,编辑了一下。克里斯,你会不会计算错误的长度? (比如两次添加空字符?)
  • @Leeor 这清除了它。垃圾字节来自计算错误的长度。我在第二个 memcpy 中添加了 1:memcpy(uPtr, userChar, strlen(userChar) + 1),它可以工作。谢谢! :)
【解决方案2】:
const char* vendorChar = [vendorId cStringUsingEncoding: [NSString defaultCStringEncoding]];
const char* userChar = [dsUsername cStringUsingEncoding: [NSString defaultCStringEncoding]];

char usernameString[strlen(vendorChar) + strlen(userChar) + 2];
char* uPtr = usernameString;

strcpy(uPtr, vendorChar);
memcpy(uPtr+strlen(vendorChar)+1, userChar, strlen(userChar) + 1);

更改:我为结尾的 \0 添加了空格,复制了 userChar 字符串并包含结尾的 \0

【讨论】:

  • strcpy 不是问题所在。它在字符串之后的目标中放置一个空字符。
  • 好答案,但请添加解释。
  • @EricPostpischil 的问题之一是usernameString 的大小。它应该是 strlen(vendorChar) + strlen(userChar) + 2 而不是 strlen(vendorChar) + strlen(userChar) + 1
  • @FilipeGonçalves:这不太可能是问题所在。它会导致最终的空字符被写入数组之外,但这不会导致后续写入或传输usernameString 仅包含供应商文本而不包含用户文本。用于写入或传输usernameString 的方法更有可能在遇到的第一个空字符处停止。
  • @EricPostpischil 是的,我应该改写一下;我的意思是“问题之一”。我认为发送内容的函数在第一个空字符处停止。
【解决方案3】:

首先,你需要 usernameString[] 像 -

char usernameString[strlen(vendorChar) + strlen(userChar) + 3];

因为 1 用于放置“\”,1 用于“0”,另外 1 用于空终止符,因此变为 3。然后使用 strcat() 创建您需要的字符串。如下:

strcpy(uPtr, vendorChar);
strcat(uPtr,"\\");
strcat(uPtr,"0");
strcat(uPtr, userChar);

【讨论】:

  • OP 不希望缓冲区中有文字“\0”;他们想要一个空字符。
  • 嗯...我想在最后一行提问者说,他想保留吗?顺便说一句,OP 是什么意思?
  • @rakib OP = 原始海报
猜你喜欢
  • 2021-09-26
  • 2016-12-30
  • 1970-01-01
  • 2017-03-11
  • 2013-11-05
  • 2013-03-09
  • 2013-08-08
  • 2014-01-20
相关资源
最近更新 更多