【问题标题】:Concatenation of two arrays using while loop使用while循环连接两个数组
【发布时间】:2019-10-30 05:44:04
【问题描述】:

代码没有问题。我怀疑我们是否可以连接两个数组。我们了解到,一旦声明了数组,我们就无法增加它的大小。但是下面的代码似乎正在这样做。我们可以使用下面的部分向静态创建的数组添加元素吗?

而(S1[i] = S2[j]) { 我++; j++; }

#include<stdio.h>

char* strcatt(char[], char[]);

int main(void) {
    char S1[] = "University of Colombo";
    char S2[] = "Sri Lanka";
    printf("%s\n", strcatt(S1, S2));
return 0;
}

char* strcatt(char S1[], char S2[]) {
    int i = 0, j = 0;
    while(S1[i]) {
        i++;
    }
    S1[i++] = ' ';
    while(S1[i] = S2[j]) {
        i++;
        j++;
    }
return (S1);
}

我得到这个输出:- 斯里兰卡科伦坡大学

【问题讨论】:

  • 您应该分配一些新内存,然后将字符复制到其中。
  • @Chamika 代码具有未定义的行为,因为尝试写入数组以外的内存。
  • @JeroenvanLangen 感谢评论。但是我的问题是,一旦声明了一个数组,我们如何扩展它?在第一个数组的空值之后,它使用第二个 while 循环获取另一个数组的元素。在这里,第一个数组已经扩展。
  • @Chamika 如果第一个数组被声明为至少像 char S1[32] = "University of Colombo";也就是说,如果第一个数组有足够的内存来容纳第二个数组的元素
  • C 不会控制你的代码,这取决于你!同样,C 不会检查您是否到达数组的末尾,这是您的责任。所以行为真的是不确定的,你只是在写一个没有分配给你的数组的内存位置。

标签: c arrays string while-loop concatenation


【解决方案1】:

您对该函数的调用是错误的,因为您没有足够的空间容纳第二个字符串。通常这样的函数自己分配内存或获取缓冲区作为附加参数。在您下面的两个版本中,一个分配内存,第二个占用缓冲区。如果缓冲区为空,它会为新字符串分配内存。不需要时需要释放它

char *strcpyt(char *dest, const char *str)
{
    char *result = dest;
    if(dest && str)
    {
        while(*dest++ = *src++);
    }
    return result;
}

size_t strlent(const char *str)
{
    const char *start = str;
    size_t length = 0;

    if(str)
    {
        while(*str++);
        length = str - start - 1;
    }
    return length;
}

char *strcatt1(const char *str1, const char *str2)
{   
    char *result = NULL; 
    size_t size;
    if(str1 && str2)
    {
        result = malloc((size = strlent(str1)) + strlent(str2) + 1);
        if(result)
        {
            strcpyt(result, str1);
            strcpyt(result + size, str2);
        }
    }
    return result;
}

char *strcatt2(char *buff, const char *str1, const char *str2)
{   
    char *result = buff; 
    size_t size;
    if(str1 && str2)
    {
        if(!result)
        {
            result = malloc((size = strlent(str1)) + strlent(str2) + 1);
        }
        if(result)
        {
            strcpyt(result, str1);
            strcpyt(result + size, str2);
        }
    }
    return result;
}

【讨论】:

    【解决方案2】:

    函数本身是正确的,只是应该按以下方式更新

    char * strcatt( char s1[], const char s2[] ) 
    {
        size_t i = 0, j = 0;
    
        while ( s1[i] ) i++;
    
        s1[i++] = ' ';
    
        while ( s1[i] = s2[j] ) 
        {
            i++;
            j++;
        }
    
        return s1;
    }
    

    即变量ij的类型int应该更改为size_t类型,因为数组的大小可以大于@类型对象的最大正值987654326@.

    并且第二个参数应该被限定为const,因为它没有被函数改变。否则,至少您将无法调用作为第二个参数传递给函数的常量字符数组的函数,即使它在函数中没有更改。

    但是程序仍然有未定义的行为,因为字符数组S1 没有空间来容纳存储在第二个数组S2 中的字符串。

    如果第一个字符数组至少有 32 个或更多元素,则程序有效

    char S1[32] = "University of Colombo";
    

    即如果数组的大小将等于或大于sizeof( "University of Colombo" ) + sizeof( "Sri Lanka" )

    考虑到未定义的行为意味着一切,甚至包括预期的结果。:)但这也意味着相应的代码是无效的。

    如果您的程序尝试写入超出字符数组S1 的内存。

    编译器会按照 S1 然后 S2 的顺序依次放置两个数组。所以实际上函数 strcatt 自己覆盖了字符数组 S2。

    但是另一个编译器没有必要按照这个顺序放置数组,而且字符数组之间没有间隙。

    【讨论】:

    • “函数本身是正确的,只是它应该按以下方式更新”---这主要是样式建议,对吧?如果是这样,我认为最好说清楚。此外,风格指南可能是主观的。
    • @ImperishableNight 这不是关于风格的问题。对于初学者,如果第二个参数未声明为 const,那么您将无法为常量字符数组调用该函数,尽管它在函数中没有更改。此外,函数的用户不能确定函数死了不会改变第二个参数。而且字符数组的大小可以大于存储在 int 类型对象中的最大值。
    • 我明白了。在这种情况下,澄清一下也可能会很好。可能很难看到这两个变化,尤其是当您还进行样式更改时(特别是,我发现您大量使用空行会分散注意力)。
    猜你喜欢
    • 2019-07-30
    • 2012-10-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-08
    • 2012-12-10
    • 2021-07-07
    • 2020-02-24
    相关资源
    最近更新 更多