为什么这不连接两个字符串?
Why does this not concatenate two strings?
这是我的代码的要求:
This function appends the src
string to the dest
string, overwriting the terminating null byte ('[=14=]'
) at the end of dest
, and then adds a terminating null byte.
Returns a pointer to the resulting string dest
.
这是我得到的输出:
Hello
World!
Hello World!
Hello
这是我的代码:
char *_strcat(char *dest, char *src) {
int lengthd = 0;
int lengths = 0;
int i = 0;
int j = 0;
int k = 0;
char tmp[10];
while (dest[i] != '[=11=]') {
lengthd++;
i++;
}
while (src[k] != '[=11=]') {
tmp[lengths] = src[k];
lengths++;
k++;
}
for (; j < lengths - 1; j++) {
dest[lengthd + 1] = tmp[j];
}
dest[lengthd + 1] = '[=11=]';
return (dest);
}
int main(void) {
char s1[98] = "Hello ";
char s2[] = "World!\n";
char *ptr;
printf("%s\n", s1);
printf("%s", s2);
ptr = _strcat(s1, s2);
printf("%s", s1);
printf("%s", s2);
printf("%s", ptr);
return (0);
}
至少由于字符数组 tmp
与幻数 10
的声明
char tmp[10];
函数没有意义。
而且在这个 while 循环中
while (src[k] != '[=11=]')
{
lengths++;
k++;
tmp[lengths] = src[k];
}
跳过数组 tmp
的第一个元素。
也在这个for循环中
for (; j < lengths-1; j++)
{
dest[lengthd + 1] = tmp[j];
}
循环条件不正确。表达式 dest[lengthd + 1]
也会跳过指针 dest
指向的字符串的终止零字符。并且所有的字符都写在同一个位置 lengthd + 1
.
除此之外,main 中使用的名称 s1
、s2
和 ptr
未声明。
函数可以通过以下方式声明和定义
char * my_strcat( char *dest, const char *src )
{
char *p = dest;
while ( *p ) ++p;
while ( ( *p++ = *src++ ) != '[=13=]' );
return dest;
}
可以这样称呼
char s1[13] = "Hello ";
const char *s2 = "World!";
puts( my_strcat( s1, s2 ) );
使用与您的方法类似的方法定义函数的另一种方法如下
char * my_strcat( char *dest, const char *src )
{
size_t i = 0;
while ( dest[i] != '[=15=]' ) ++i;
for ( size_t j = 0; src[j] != '[=15=]'; j++ )
{
dest[i++] = src[j];
}
dest[i] '[=15=]';
return dest;
}
您的代码因多种原因而失败:
- 您使用临时数组复制源字符串:此数组
tmp
的固定长度为 10 个字节,如果源字符串长于 10 个字节,则该数组太小。否则,当您超出此数组的末尾写入时,您将有未定义的行为。
- 反正这个临时数组真的没必要。
- 最终循环在
lengths - 1
处停止,因此您在副本的最后一个字节之前停止。
- 您将所有字节复制到同一位置
dest[lengthd + 1]
。
- 你终于在同一位置再次设置了空终止符。
- 您从未更改
dest[lengthd]
处的空终止符,因此该函数似乎对 dest
. 没有影响
main()
中的测试无法生成您发布的输出,可能是因为 "%s\n"
中的错字。
- 避免使用以
_
. 开头的标识符
这是修改后的版本:
#include <stdio.h>
#include <string.h>
char *my_strcat(char *dest, char *src) {
int i = 0;
int k = 0;
/* find the offset of the null terminator in dest */
while (dest[i] != '[=10=]') {
i++;
}
/* copy the bytes from the src string there */
while (src[k] != '[=10=]') {
dest[i] = src[k];
i++;
k++;
}
/* set the null terminator */
dest[i] = '[=10=]';
/* return the pointer to the destination array */
return dest;
}
int main(void) {
char s1[98] = "Hello ";
char s2[] = "World!";
char *ptr;
printf("%s\n", s1);
printf("%s", s2);
ptr = my_strcat(s1, s2);
printf("%s", s1);
printf("%s", s2);
printf("%s", ptr);
return 0;
}
请注意,源字符串未被修改,偏移量应具有类型 size_t
并且可以作为赋值的副作用递增:
char *my_strcat(char *dest, const char *src) {
size_t i = 0;
size_t k = 0;
/* find the offset of the null terminator in dest */
while (dest[i] != '[=11=]') {
i++;
}
/* copy the bytes from the src string there */
while (src[k] != '[=11=]') {
dest[i++] = src[k++];
}
/* set the null terminator */
dest[i] = '[=11=]';
/* return the pointer to the destination array */
return dest;
}
您也可以使用指针代替偏移量:
char *my_strcat(char *dest, const char *src) {
/* use a working pointer to preserve dest for the return value */
char *p = dest;
/* find the offset of the null terminator in dest */
while (*p != '[=12=]') {
p++;
}
/* copy the bytes from the src string there */
while (*src != '[=12=]') {
*p++ = *src++;
}
/* set the null terminator */
*p = '[=12=]';
/* return the pointer to the destination array */
return dest;
}
最后一个更改:您可以结合读取源字节、复制到目标和测试空终止符,它已经被复制了:
char *my_strcat(char *dest, const char *src) {
/* use a working pointer to preserve dest for the return value */
char *p = dest;
/* find the offset of the null terminator in dest */
while (*p != '[=13=]') {
p++;
}
/* copy the bytes from the src string there */
while ((p++ = *src++) != '[=13=]') {
/* nothing */
}
/* the null terminator was copied from the source string */
/* return the pointer to the destination array */
return dest;
}
这是我的代码的要求:
This function appends the
src
string to thedest
string, overwriting the terminating null byte ('[=14=]'
) at the end ofdest
, and then adds a terminating null byte.Returns a pointer to the resulting string
dest
.
这是我得到的输出:
Hello
World!
Hello World!
Hello
这是我的代码:
char *_strcat(char *dest, char *src) {
int lengthd = 0;
int lengths = 0;
int i = 0;
int j = 0;
int k = 0;
char tmp[10];
while (dest[i] != '[=11=]') {
lengthd++;
i++;
}
while (src[k] != '[=11=]') {
tmp[lengths] = src[k];
lengths++;
k++;
}
for (; j < lengths - 1; j++) {
dest[lengthd + 1] = tmp[j];
}
dest[lengthd + 1] = '[=11=]';
return (dest);
}
int main(void) {
char s1[98] = "Hello ";
char s2[] = "World!\n";
char *ptr;
printf("%s\n", s1);
printf("%s", s2);
ptr = _strcat(s1, s2);
printf("%s", s1);
printf("%s", s2);
printf("%s", ptr);
return (0);
}
至少由于字符数组 tmp
与幻数 10
char tmp[10];
函数没有意义。
而且在这个 while 循环中
while (src[k] != '[=11=]')
{
lengths++;
k++;
tmp[lengths] = src[k];
}
跳过数组 tmp
的第一个元素。
也在这个for循环中
for (; j < lengths-1; j++)
{
dest[lengthd + 1] = tmp[j];
}
循环条件不正确。表达式 dest[lengthd + 1]
也会跳过指针 dest
指向的字符串的终止零字符。并且所有的字符都写在同一个位置 lengthd + 1
.
除此之外,main 中使用的名称 s1
、s2
和 ptr
未声明。
函数可以通过以下方式声明和定义
char * my_strcat( char *dest, const char *src )
{
char *p = dest;
while ( *p ) ++p;
while ( ( *p++ = *src++ ) != '[=13=]' );
return dest;
}
可以这样称呼
char s1[13] = "Hello ";
const char *s2 = "World!";
puts( my_strcat( s1, s2 ) );
使用与您的方法类似的方法定义函数的另一种方法如下
char * my_strcat( char *dest, const char *src )
{
size_t i = 0;
while ( dest[i] != '[=15=]' ) ++i;
for ( size_t j = 0; src[j] != '[=15=]'; j++ )
{
dest[i++] = src[j];
}
dest[i] '[=15=]';
return dest;
}
您的代码因多种原因而失败:
- 您使用临时数组复制源字符串:此数组
tmp
的固定长度为 10 个字节,如果源字符串长于 10 个字节,则该数组太小。否则,当您超出此数组的末尾写入时,您将有未定义的行为。 - 反正这个临时数组真的没必要。
- 最终循环在
lengths - 1
处停止,因此您在副本的最后一个字节之前停止。 - 您将所有字节复制到同一位置
dest[lengthd + 1]
。 - 你终于在同一位置再次设置了空终止符。
- 您从未更改
dest[lengthd]
处的空终止符,因此该函数似乎对dest
. 没有影响
main()
中的测试无法生成您发布的输出,可能是因为"%s\n"
中的错字。- 避免使用以
_
. 开头的标识符
这是修改后的版本:
#include <stdio.h>
#include <string.h>
char *my_strcat(char *dest, char *src) {
int i = 0;
int k = 0;
/* find the offset of the null terminator in dest */
while (dest[i] != '[=10=]') {
i++;
}
/* copy the bytes from the src string there */
while (src[k] != '[=10=]') {
dest[i] = src[k];
i++;
k++;
}
/* set the null terminator */
dest[i] = '[=10=]';
/* return the pointer to the destination array */
return dest;
}
int main(void) {
char s1[98] = "Hello ";
char s2[] = "World!";
char *ptr;
printf("%s\n", s1);
printf("%s", s2);
ptr = my_strcat(s1, s2);
printf("%s", s1);
printf("%s", s2);
printf("%s", ptr);
return 0;
}
请注意,源字符串未被修改,偏移量应具有类型 size_t
并且可以作为赋值的副作用递增:
char *my_strcat(char *dest, const char *src) {
size_t i = 0;
size_t k = 0;
/* find the offset of the null terminator in dest */
while (dest[i] != '[=11=]') {
i++;
}
/* copy the bytes from the src string there */
while (src[k] != '[=11=]') {
dest[i++] = src[k++];
}
/* set the null terminator */
dest[i] = '[=11=]';
/* return the pointer to the destination array */
return dest;
}
您也可以使用指针代替偏移量:
char *my_strcat(char *dest, const char *src) {
/* use a working pointer to preserve dest for the return value */
char *p = dest;
/* find the offset of the null terminator in dest */
while (*p != '[=12=]') {
p++;
}
/* copy the bytes from the src string there */
while (*src != '[=12=]') {
*p++ = *src++;
}
/* set the null terminator */
*p = '[=12=]';
/* return the pointer to the destination array */
return dest;
}
最后一个更改:您可以结合读取源字节、复制到目标和测试空终止符,它已经被复制了:
char *my_strcat(char *dest, const char *src) {
/* use a working pointer to preserve dest for the return value */
char *p = dest;
/* find the offset of the null terminator in dest */
while (*p != '[=13=]') {
p++;
}
/* copy the bytes from the src string there */
while ((p++ = *src++) != '[=13=]') {
/* nothing */
}
/* the null terminator was copied from the source string */
/* return the pointer to the destination array */
return dest;
}