首页 > 解决方案 > 输出根据程序中函数调用的位置而变化

问题描述

我目前正在学习 C。为了变得更好,我想做的一件事是模仿标题中的“strcat”函数。为了制作更精确的副本,我将自己函数的输出与原始函数的输出进行了比较。它们使用相同但不同的字符数组。但是,如果在原始函数之后调用它,我自己的函数的输出会发生变化。以下是两种代码变体:

在第一个中,原始的输出是"1234567890123456",正如预期的那样,我自己的输出是"123456789123456"。经过几十次不同的检查后,我发现:一旦将'0'字符作为参数传递给函数,它就会从src[0]中消失:

int main()
{

    char dest[10] = "123456789";
    char src[70] = "0123456";
    printf ("Concatenate |%s| and |%s|\n", dest, src); 


    char dest1[10] = "123456789";
    char src1[70] = "0123456";
    printf ("Normal people do: %s\n", strcat(dest1, src1));    
    printf ("Your filthy code: %s\n",  ft_strcat(dest, src));


    return 0;
}

但是,如果我像这样简单地重新定位我的函数的 printf:

int main()
{

    char dest[10] = "123456789";
    char src[70] = "0123456";
    printf ("Concatenate |%s| and |%s|\n", dest, src);     
    printf ("Your filthy code: %s\n",  ft_strcat(dest, src));


    char dest1[10] = "123456789";
    char src1[70] = "0123456";
    printf ("Normal people do: %s\n", strcat(dest1, src1));    
    return 0;
}

这两个函数都将返回“1234567890123456”作为输出。

问题是:这怎么可能?我很好奇,因为这些函数针对两组不同的数组,因此不应该相互影响。由于某种原因,我的函数的行为取决于它在int main()的主体中被调用的时间。

请注意,我特意将 dest[] 数组设置为 10 个字符大,因为我也想在意外情况下模仿原始“strcat”的行为。虽然这可能是问题的核心,如果我改变它,代码在上述两种情况下都可以正常工作。正如我所说,我对问题的性质感兴趣,而不是解决问题的方法。

我不确定我的函数文本是否与此问题相关,但在这里,以防万一:

char *ft_strcat(char *dest, char *src)
{
    int dest_end;
    int src_count;

    dest_end = 0;
    src_count = 0;
    while (dest[dest_end])
        dest_end++;
    while (src[src_count])
    {
        dest[dest_end] = src[src_count];        
        src_count++;
        dest_end++;
    }
    dest[dest_end + 1] = '\0';
    return dest;
}

谢谢你的任何答案。

标签: cstringstrcatstring.h

解决方案


char dest[10] = "123456789";
char src[70] = "0123456";
printf ("Your filthy code: %s\n",  ft_strcat(dest, src));

char dest1[10] = "123456789";
char src1[70] = "0123456";
printf ("Normal people do: %s\n", strcat(dest1, src1)); 

在这两种情况下,使用您自己的函数ft_strcat(dest, src))strcat()其中任何一种,您都会调用未定义的行为,因为char目标指向的数组无法保存初始化的字符串以及源指向的附加字符串。当超出数组范围写入时,程序的行为是未定义的。


解决方案:

数组destdest1需要至少18总共有元素,10用于保存 "0123456789",用于终止空字符7的附加"0123456"+元素:1\0

char dest[18] = "123456789";
char dest1[18] = "123456789";

char src[70] = "0123456";
char src1[70] = "0123456";

printf ("Your filthy code: %s\n",  ft_strcat(dest, src));
printf ("Normal people do: %s\n", strcat(dest1, src1));

旁注:

  1. 该数组scr1是多余的,因为它仅用于提供附加字符串,并且它的内容与 .in 中的字符串完全相等src。您也可以src用于第二个附加过程:
printf ("Normal people do: %s\n", strcat(dest1, src));
  1. srcsrc1持有每个70元素,这是不必要的。他们都只需要有8元素,而不是70
src[8] = "0123456";
src1[8] = "0123456";

一种更方便的方法是省略元素的数量,让编译器自动检测所需的元素数量,这也确保您不会忘记计数时的空字符:

src[] = "0123456";
src1[] = "0123456";
  1. 由于指针src及其指向的对象都应在ft_strcat()declare srcas中进行修改char const * const src

dest也可以制作const,但不要让它成为指向constchar:的指针char * const dest

ft_strcat()关于指针,您还可以调整 的返回类型dest

结果是:

char * const ft_strcat(char * const dest, char const * const src)

推荐阅读