在没有库且没有指针的情况下构建strcat

时间:2019-01-26 12:30:57

标签: c 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);
}

输出:

a

4 个答案:

答案 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)允许优化,弱编译器可能看不到。

对于 long 字符串,

const char []优于size_t,而字符串可能长于intINT_MAX是字符串长度和数组大小的“正确大小”类型。 OP(原始海报)确实具有“不使用库”的功能,并且size_t来自库,因此代码可以使用size_t或更好的unsigned作为替代。

答案 2 :(得分:1)

此行:

a[strlen(a) + i + 1] = b[i];

将字符写到比您想要的位置更远的位置。

在示例中被调用时,例程将通过以下内容传递给ab

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.