【问题标题】:C - Copy a String without a library functionC - 复制没有库函数的字符串
【发布时间】:2021-12-29 19:45:52
【问题描述】:

我想创建一个函数,它接受一个字符串文字和一个数组,并将字符串文字的字符复制到数组中。您能否告诉我以下代码中的问题是什么? 此代码的输出只是带有一些空格(“D”)的大写 D,所以我认为以某种方式访问​​了随机位置。

#include <stdio.h>

int main(void)
{
    //Function Prototypes:
    void CopyAString(const char * s1, char s2[]);
    
    // Initialize the string literal str1 and an array s2 of size 12.
    const char *str1 = "Hello World";
    char s2[12];
    // In the function i pass the address of str1 and the array s2.
    CopyAString( &str1, s2 );

    for (int i = 0; i <= 12; i++){
        printf("%c", s2[i]);
    }

}

void CopyAString(const char * s1, char s2[])
{
    const char * p1 = s1;
    int index = 0;

    while (*p1 != '\0') {
        s2[index] = *p1;
        index++;
        p1++;
    }
}

【问题讨论】:

  • 您忘记将 NUL 终止符 '\0' 写入字符串。此外,最好按照标准库函数strcpy() 的方式对参数进行排序。
  • 您还使用CopyAString( &amp;str1, s2 ); 错误地调用了该函数,因为编译器会发出警告。请打开编译器警告。另外:您输出的字符太多(超出了数组范围)。
  • 感谢您的评论!但是,NULL 终止符是编译器在赋值后自动放置的 const char *str1 = "Hello World";
  • 不,你停在那个不复制它。
  • 编译器会在str1指向的字符串末尾放置一个NUL终止符。确实如此。但是,负责将数据写入数组s2[]。编译器无法知道您的函数 CopyAString 是否故意不在那里放置 NUL 字符。在某些情况下不需要 NUL 字符...

标签: arrays c copy c-strings function-definition


【解决方案1】:

你的程序有两个错误:

首先

您的函数CopyAString 没有在字符串末尾写入'\0' 字符。这意味着字符串s2[] 没有'\0' 字符,您将无法将s2[] 传递给printf() 或其他期望“输入”字符串以'\0' 结尾的函数。

但是,在您的程序中,这不是问题,因为for 循环需要一个固定长度的字符串。

第二

在你的程序中,下面的问题比较重要:

您将&amp;str 作为第一个参数传递给CopyAString 而不是str

这意味着s1CopyAString的第一个参数)不指向"Hello world"的字符'H',而是指向存储在变量str中的值的第一个字节。 .

注意变量str是一个指针:它不存储一个“值”(这里是字符串"Hello world"),但它存储一个值的地址!

如果字符串 "Hello world" 存储在 RAM 中的地址 0x20 44 00 40(这意味着:0x40004420 在 x86 或 ARM 计算机上或 0x20440040 在 PowerPC 上),则变量 str 将包含值0x20 44 00 40.

s1[0] 将是 0x20(这是空格字符)。 s1[1] 将是 0x44(即 'D')...

【讨论】:

  • 首先你说没有问题,但是有 UB。 s2 中的第 12 个字符从不初始化,因此程序可以输出任何内容作为第 12 个字符。
  • 无话可说,感谢您的详细解释!
  • @Cheatah 好的。你是对的:循环应该运行到 10 而不是 11。但是,将 '\0' 传递给 putchar() 可能也不是 OP 想要的......
【解决方案2】:

对于初学者,您应该像这样声明函数

char * CopyAString( char *s1, const char *s2 );

类似于标准的字符串函数strcpy

在这个函数调用中

CopyAString( &str1, s2 );

表达式&amp;str1 的类型为const char ** 并产生指针str1 的地址,但该函数需要一个类型为const char * 的参数表达式,它指向字符串的第一个元素(字符串文字)。

在函数中,您不会复制终止零字符

while (*p1 != '\0') {
    s2[index] = *p1;
    index++;
    p1++;
}

所以目标字符数组一般不会包含字符串。

函数可以通过以下方式定义

char * CopyAString( char *s1, const char *s2 )
{
    for ( char *p = s1; ( *p++ = *s2++ ); );

    return s1;
}

在调用未定义行为的条件中,在 main 而不是这个 for 循环中使用幻数 12

for (int i = 0; i <= 12; i++){
    printf("%c", s2[i]);
}

最好写

for ( char *p = s2; *p != '\0'; ++p ){
    printf("%c", *p );
} 
putchar( '\n' );

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-07-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-27
    • 1970-01-01
    • 2019-07-24
    相关资源
    最近更新 更多