我被要求在不使用库和指针的情况下从strcat构建string.h。
到目前为止,我已经知道了,但是不知道怎么做:
void strcatO(char a[], char b[])
{
int i = 0;
for(i = 0; i < strlen(b); ++i)
{
a[strlen(a) + i + 1] = b[i];
}
printf("%s", a);
}
输出:
答案 0 :(得分:2)
在您遇到的问题中,您可以不断地计算 strlen ,而无需编译器会对其进行优化,您可以这样做:
#include <stdio.h>
#include <string.h>
void strcatO(char a[], char b[])
{
size_t i = strlen(a);
size_t j;
for (j = 0; b[j] != 0; ++j)
{
a[i++] = b[j];
}
a[i] = 0;
printf("%s\n", a);
}
int main()
{
char a[20] = "aze";
char b[] = "rtyu";
strcatO(a,b);
return 0;
}
执行:
azertyu
请注意,参数的char a[]
恰好是char *
,没有指针的 为false;-)
并按照Eric Postpischil的要求指出代码中的问题:
a[strlen(a) + i + 1]
在正确位置后写1个字符,必须为a[strlen(a) + 1] = 0; a[strlen(a)] = b[j];
。从某种意义上说,您可能会在结束后写得更多,因为 strlen 不会返回 a 的初始长度,而是一个未定义的值,因为可能缺少null a 答案 1 :(得分:2)
某种程度上不起作用
a[strlen(a) + i + 1] = b[i];
在空字符 之后的 后。
a
void strcatO(char a[], char b[]) {
int i = 0;
for(i = 0; i < strlen(b); ++i) {
a[strlen(a) + i + 1] = b[i]; // Oops: appending position is off-by-one
}
printf("%s", a);
}
将strcatO("ab", "cd")
填充为a
,'a'
,'b'
,'\0'
,'c'
。
使用'd'
打印仅打印printf("%s", a);
,'a'
。
要解决此问题,需要在正确的位置附加代码,但这会覆盖原始的'b'
空字符。因此,对a
的调用是不好的。
相反,对于improve efficiency,请勿重复调用strlen(a)
。
strlen()
细微改进的细节:
void strcatO(char a[], const char b[]) {
size_t ai = 0;
while (a[ai]) { // go to end of a
ai++;
}
size_t bi = 0;
while (b[bi]) { // while not at the end of b ...
a[ai++] = b[bi++];
}
a[ai] = '\0';
printf("<%s>", a);
}
中的 const
暗示const char b[]
引用了该函数不应尝试更改的数据。 1)允许此函数串联b
,如果它是b
2)允许优化,弱编译器可能看不到。
const char []
优于size_t
,而字符串可能长于int
。 INT_MAX
是字符串长度和数组大小的“正确大小”类型。 OP(原始海报)确实具有“不使用库”的功能,并且size_t
来自库,因此代码可以使用size_t
或更好的unsigned
作为替代。
答案 2 :(得分:1)
此行:
a[strlen(a) + i + 1] = b[i];
将字符写到比您想要的位置更远的位置。
在示例中被调用时,例程将通过以下内容传递给a
和b
:
a[0] = 'e'
a[1] = 'g'
a[2] = 'g'
a[3] = 0
b[0] = 's'
b[1] = 'a'
b[2] = 'm'
b[3] = 'p'
b[4] = 'l'
b[5] = 'e'
b[6] = 0
您要产生以下结果:
a[0] = 'e'
a[1] = 'g'
a[2] = 'g'
a[3] = 's'
a[4] = 'a'
a[5] = 'm'
a[6] = 'p'
a[7] = 'l'
a[8] = 'e'
a[9] = 0
但是,由于您的代码写入了a[strlen(a) + i + 1]
,所以它会将第一个字符写入a[strlen(a) + 0 + 1]
,即a[4]
。您需要在a[3]
中使用它。您可以将strlen(a) + i + 1
更改为strlen(a) + i
,但是,当您写入第一个字符时,您将覆盖空终止符,而strlen
将不再能找到长度。要解决此问题,您可以在进入循环之前记住a
的长度。考虑以下代码:
int i = 0;
int LengthOfA = strlen(a);
for (i = 0; i < strlen(b); ++i)
{
a[LengthOfA + i] = b[i];
}
这会将字符写到正确的位置。
但是,它不会在a
的末尾添加空终止符。为此,我们可以在循环后添加另一条语句:
a[LengthOfA + i] = 0;
那时,您的例程将在正常情况下工作。但是,我们还可以进行两项改进。
首先,我们可以使用int
来代替长度和索引,而不必使用size_t
。在C语言中,int
的宽度是灵活的,并且提供size_t
作为处理对象大小时的好类型。要使用它,请首先使用#include <stddef.h>
来获取其定义。然后您的代码可以是:
size_t i = 0;
size_t LengthOfA = strlen(a);
for (i = 0; i < strlen(b); ++i)
{
a[LengthOfA + i] = b[i];
}
a[LengthOfA + i] = 0;
第二,您的代码在每次迭代中名义上都会计算strlen(b)
。这很浪费。最好一次计算长度并记住它:
size_t i = 0;
size_t LengthOfA = strlen(a);
size_t LengthOfB = strlen(b);
for (i = 0; i < LengthOfB; ++i)
{
a[LengthOfA + i] = b[i];
}
a[LengthOfA + i] = 0;
答案 3 :(得分:0)
您不会覆盖第一个字符串 null (\0
)终止符
a[strlen(a) + i + 1] = b[i];
应该是
int len = strlen(a);
for(i = 0; i < strlen(b); ++i)
{
a[len + i] = b[i];
}
a[len+i] = '\0'; //Finally null terminate the new string.