我正在开发一个项目,需要将两个字符串“交织在一起”,以便它们交替每个字符。 示例:“Apple”和“BEAR”将变为“ABpEpAlRe”
这是我目前的职能:
void printMessage(char name[], char num[])
{
char eticket[(sizeof(name)/sizeof(char))+((sizeof(num))/sizeof(char))] = ""; //make array with enough space for both strings
int i;
for(i=0;i<(sizeof(eticket)/sizeof(char));i++)
{
char tmp[1] ={name[i]}; // i have to change the char name[i] and num[i] to its own char array so i can use it in strcat
char tmp2[1] ={num[i]};
if(i<(sizeof(name)/sizeof(char))-1) //if name string is finished, don't concatenate
{
strcpy(eticket,strcat(eticket, tmp));
}
if(i<(sizeof(num)/sizeof(char))-1) //if num string is finished, don't concatenate
{
strcpy(eticket,strcat(eticket, tmp2));
}
}
printf("Your name is %s and your flight number is %s.\nYour e-ticket is: %s.\n\n", name, num, eticket);
}
eticket是最后一个字符串。
结果:
Your name is Connor and your flight number is MIA1050.
Your e-ticket is: CMMoIInAAn11o00r550.
*** stack smashing detected ***: ./a.out terminated
Aborted
我知道堆叠粉碎意味着缓冲区正在溢出,但更令我担心的是,由于某种原因我无法弄清楚,num []数组的字符在最终字符串中加倍。 而不是“CMMoII ......”它应该是“CMoI ......” 这可能是缓冲区溢出的副作用吗?
提前致谢。
答案 0 :(得分:2)
功能定义:
void printMessage(char name[], char num[]) { ... }
与
相同void printMessage(char* name, char* num) { ... }
在函数中,sizeof(name)
等于指针的大小。它不会计算字符串的长度。
您需要使用strlen
代替sizeof
。使用strlen
时,需要为终止空字符添加一个附加字符。
// eticket is now a VLA.
// Can't use ... = "";
char eticket[strlen(name)+strlen(num)+1];
您还需要更改使用sizeof
的其他代码行。
答案 1 :(得分:0)
经验丰富的C语言程序员熟知的C语言的怪癖,但是新的C编码器匆匆到来,就是阵列是通过引用传递的#34;。一般来说,大多数表达式中使用的数组名称将衰减到其第一个元素的地址。函数将其带到极端情况,其中函数参数中的数组语法实际上是指针类型本身的别名。
因此,函数中的name
和num
实际上是指针而不是数组,因此sizeof(name)
实际上与sizeof(char *)
相同。
答案 2 :(得分:0)
在C中,当您使用如下语法传递数组时:
void printMessage(char name[], char num[])
有关阵列 size 的信息丢失;你传递的内容基本上是指针到数组的开头。
这意味着在这种情况下像sizeof(name)/sizeof(char)
这样的表达式等同于:
sizeof(char *)/sizeof(char)
是:
(指针大小)/(字符大小)
在32位架构上,这通常评估为4(即4字节/ 1字节)。
因此,您可能希望在运行时获取输入字符串长度,调用strlen()
,并使用malloc()
动态分配输出字符串数组。
e.g。
char * eticket = NULL;
...
/*
* Dynamically allocate memory for output string buffer.
* Note: add +1 to consider the string's NUL-terminator.
*/
eticket = (char *)malloc(strlen(name) + strlen(num) + 1);
/* Check allocation failure */
if (eticket == NULL)
{
/* Error */
...
}
/* Use eticket */
...
/* Don't forget to free memory! */
free(eticket);
/* Avoid dangling pointers */
eticket = NULL;
答案 3 :(得分:0)
其他人指出数组是“通过引用传递的”。所以你不应该使用sizeof(name)
,因为那只是sizeof(char*)
(如果我错了,请纠正我;总是8),而是strlen(name)
。
char tmp[1] ={name[i]};
char tmp2[1] ={num[i]};
这可能会得到你想要的东西,但为一个元素创建一个char数组非常多余。而只是创建一个char并使用&amp; :
传递指向该char的指针char tmp = name[i];
printf("tmp: %s\n", &tmp);
循环可以减少到只有两行:
void printMessage(char* name, char* num){
int len = strlen(name) + strlen(num);
char* eticket = calloc(0,len +1);
int i,j,k;
for(i=0, j=0, k=0; i<len;i++){
if(j < strlen(name)) strncpy(&eticket[i++],&name[j++],1);
if(k < strlen(num) ) strncpy(&eticket[i],&num[k++],1);
}
printf("Your name is %s and your flight number is %s.\nYour e-ticket is: %s.\n\n", name, num, eticket);
free(eticket);
}
这就像你想要的那样,并且更加清洁。我跳过整个strcat(..)
函数,因为它是多余的。我改用strncpy(char * dst, const char * src, size_t len)
。
这个怎么运作:
- i 保持 eticket 中的位置。
- j 保留名称中的位置。
- k 将位置保留在 num 。
&eticket[i++]
这指向 eticket 数组中的 i'th 位置(i后来递增)。这意味着复制到此的内容将从此处开始。
&name[j++]
这是指向 name 数组中 j'th 元素的指针。这意味着strncpy
将在此处开始阅读,并将 1 元素复制到 eticket 数组中。
希望这有帮助。