【问题标题】:implementing a strcpy() function without using <string.h> in C在 C 中不使用 <string.h> 实现 strcpy() 函数
【发布时间】:2020-08-16 17:23:41
【问题描述】:

我的任务是这样的:我应该在以下约束下实现strcpy函数:

  1. 函数应使用指针表达式 (*(d+i))
  2. 我应该不使用&lt;string.h&gt;来实现它

我正在使用 Visual Studio 2019 进行编程。 我在谷歌搜索了一些源代码并运行它们,但我的程序有一个逻辑错误。程序立即结束,每次。我不知道我做错了什么。 这是我在 Windows 上的 Visual Studio 2019 中的代码。请告诉我有什么问题。

#include <stdio.h>
void strcpy(char*, char*);

int main()
{
    char* sen1 = "Hello";
    char* sen2 = "Friends";

    strcpy(sen1, sen2);

    printf("The result: %s\n", sen1);

    return 0;
}

void strcpy(char* str1, char* str2)
{
    int i = 0;
    while (*(str2 + i) != '\0')
    {
        *(str1 + i) = *(str2 + i);
        i++;
    }
    *(str1 + i) = '\0';
}

【问题讨论】:

  • 嗯...sen1sen2 指向什么可写 存储? (或者它们只是初始化指向不可修改的 String Literals 的指针?)为​​什么不呢,例如char sen1[64] = "Hello"; char sen2[64] = "Friends"; 所以两者都被声明为 arrays?
  • 程序没有扫描字符串并分配sen1和sen2。所以我为他们设置了字符串文字。 (而且我英文不太好……所以请理解!)
  • 当然,您可以使用字符串文字模拟您的 source (sen2) 字符串以进行测试,但您的 sen1 指针必须指向您可以使用的有效存储写入(就像一个足够长的字符数组以容纳 sen1(加上 nul 终止字符)。
  • 我相信这个问题与strcpy using pointers重复
  • @Abra 差不多,但不完全。我相信,关于避免索引和使用 ptr+offset 表示法的要求使其完全不同。

标签: c strcpy


【解决方案1】:

除了需要为sen1 提供可写存储空间之外,您还应该在取消引用str2 之前检查以确保您的函数中有str2 != NULL(否则,即使您修复了所有其他错误——可能会导致段错误)

例如,在您的代码中,您可以定义一个用于设置sen1 大小的常量数组(或者您可以使用malloc()calloc() 或@ 分配存储空间987654327@ - 保存以备后用)。使用数组你可以做,例如

#include <stdio.h>
#include <stdlib.h>

#define MAXC 64     /* if you need a constant, #define one (or more) */
...
int main (void)
{
    char sen1[MAXC] = "Hello";
    char *sen2 = "Friends";

    mystrcpy (sen1, sen2);

    printf ("The result: %s\n", sen1);

}

在你的 strcpy 函数中,在你的函数中使用 str2 之前检查 str2 不是 NULL,例如

char *mystrcpy (char *dest, const char *src)
{
    char *p = dest;

    if (!src || !dest) {            /* ensure src or dest is not NULL */
        fputs ("error: src or dest parameters NULL in mystrcpy().\n", stderr);
        exit (EXIT_FAILURE);
    }

    do                              /* loop */
        *p++ = *src;                /* copy each char in src to dest */
    while (*src++);                 /* (including the nul-termianting char) */

    return dest;                    /* return pointer to dest */
}

现在您将在您的(重命名的)mystrcpy() 函数中将源字符串复制到目标字符串,收到您期望的结果:

使用/输出示例

$ ./bin/mystrcpy
The result: Friends

查看一下,如果您还有其他问题,请告诉我。

【讨论】:

  • 我不确定确保src 不为NULL 的测试是否是个好主意。如果src 为NULL,我会让程序崩溃(这将在几乎所有现有的桌面平台上发生)。我不认为 actual strcpy 实现会做这个检查。
  • 在取消引用之前将指针作为参数的所有函数中,这更像是一种检查/习惯。你有一个很好的观点。 if (!src) { fputs ("error: NULL source pointer in mystrcpy().\n", stderr); exit (EXIT_FAILURE); } 会更干净。谢谢!
  • 有些东西我还没有学过(exit, fputs(可能是printf的一个角色?)),所以我得参考一些。但是感谢您的友好评论!
  • @올리브한개 exit 用于从函数内部停止执行程序。 fputs() 只是 printf() 函数的替代品,尤其是仅用于打印字符串,在这种情况下,是错误流 stderr 独有的,而不是 stdoutprintf 一样。
  • 请检查dest 而不是NULLp 允许我使用 return dest;,否则指针 dest 将位于字符串的末尾,如果我递增它。
【解决方案2】:

至少有两个问题:

  1. 字符串文字在 C 中不可写。症状通常是崩溃 (SIGSEGV)。
  2. 您不能将标识符strcpy 用于您自己的功能。使用其他名称。

至少三个干净的代码问题:

  1. int main() 转换为int main(void) 以使其正确输入。
  2. str1str2 是过于笼统的名称。它们不指示哪个是源指针,哪个是目标指针。 my_strcpy(char *dest, char *src)呢?
  3. 我会使用size_t i 作为索引计数器而不是int,因为这是所有字符串长度函数和sizeof 运算符返回的类型。它也是一个无符号类型,可以复制 really 长字符串 :-) size_t#include &lt;stddef.h&gt; 之后可用。

【讨论】:

  • (合格,至少:)
  • 1.那么我应该扫描 sen1 和 sen2 的字符串文字吗? 2. 我是否使用其他名称,例如“mystrcpy”? (而且我英文不好……所以请大家理解!)
  • @올리브한개 1. 不,只有目的地需要是一个数组,例如char dest[64];。但是可以将两者都制作成一个数组。 2. 是的,没错。
  • @Jens 感谢您的帮助!!!我解决了我的问题。祝你有美好的一天!
  • @올리브한개 太棒了! Stackoverflow 的下一步是通过单击左侧的复选标记接受对您最有帮助的答案。等待一两天以显示更多答案是可以的。
【解决方案3】:

你想要这个:

...
char* source = "Hello";
// or char source[] = "Hello";
char destination[1000];      // destination buffer long enough for playing around

my_strcpy(destination, source);

printf("%s\n", destination);   // should print "Hello" if my_strcpy is corect
...

其余的请阅读 Jens 的回答。

【讨论】:

    【解决方案4】:

    在其他好的答案中,仅关于您的 strcpy 函数的实现而不是对您的实际代码的详细问题分析,另一种方法是:

    char * n_strcpy(char * dest, char const * src)
    {
        if (dest == NULL || src == NULL)
        {
            return NULL;
        }
    
        char *ptr = dest;
    
        while ((*dest++ = *src++));
    
        return ptr;
    }
    

    【讨论】:

    • 我是这样做的,但错误一直在发生。但是我知道问题出在 main() 函数上。谢谢!
    • 这不可能。您正在增加可能未初始化的数据和 const 限定数据。请在发布前测试代码。并且明确规定不使用索引符号的要求。
    • @Jens 你是对的,我这个傻瓜。已更正。但我不明白你试图用未初始化的数据指向我的位置。你是说src/dest本身还是*src*dest,甚至ptr
    • 由于dest[i]++,因为 dest[] 可能在调用中未初始化并且您递增每个未初始化的字符。
    猜你喜欢
    • 2013-10-18
    • 1970-01-01
    • 2021-08-12
    • 2013-01-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-12
    • 2011-05-22
    相关资源
    最近更新 更多