【问题标题】:Implementation of strcpy and strcat that deals with exceptions处理异常的strcpy和strcat的实现
【发布时间】:2013-12-26 19:33:48
【问题描述】:

我必须用 7 行代码编写 strcpy()strcat() 并处理可能出现的任何异常。到目前为止,这是我的代码。有人对我如何减少行数有任何建议吗?

char *mystrcpy(char *dst, const char *src)
{
    char *ptr;
    ptr = dst;
    while(*dst++=*src++);
    return(ptr);
}

void strcat(char *dest, const char *src)
{

    while (*dest!= '\0')
        *dest++ ;
    do
    {
        *dest++ = *src++;
    }
    while (src != '\0') ;
}

【问题讨论】:

  • 如果你愿意,可以写在一行上……
  • 如果它似乎工作,那么这应该去 codereview.stackexchange.com。那么,代码有效吗?如果不是,请问您遇到什么问题?
  • @alk 你一定没看过。它有一些严重的问题。
  • 你真的在一些测试用例上试过这个吗?在做空之前,我会专注于把它做好。
  • @user3082112 在编写自己的实现之前,您需要先了解这一点:dstsrc 可以重叠吗?

标签: c strcpy strcat


【解决方案1】:
char *mystrcpy(char *dst, const char *src){
    return (*dst=*src) ? (mystrcpy(dst+1, src+1), dst) : dst;
}
char *mystrcat(char *dst, const char *src){
    return (*dst ? mystrcat(dst+1, src) : mystrcpy(dst, src)), dst;
}

【讨论】:

  • @BitFiddlingCodeMonkey 它必须被分配。因为需要进行复制。
  • 但我该如何处理可能出现的异常?
  • @user3082112 更好的错误处理冲突,以减少代码。
  • 是的,但是 c 中没有异常。如何在 c 中实现异常?
  • @user3082112 我认为这将是防止正常的预异常,因为它在 C 中不受支持。你说绝对,我认为它会像一个内置的解释器。考虑一下您可以为执行表达式做些什么,例如 E.g ` x = 1/0;`。
【解决方案2】:

您的代码有问题:您正在针对'\0' 测试src 本身,而不是它指向的char

while (src != '\0');

应该是

while (*src != '\0');

先做对,然后做短/快。


您在整个页面上都在写关于异常安全的文章。由于您使用的是 C,因此没有像 exceptions 这样的本地语言概念(与 C++ 相对)。

无论如何,您的代码可能引发的唯一异常类型是硬件异常页面错误堆栈错误对齐check, ...) 无法被普通 C++ try-catch 捕获。由于硬件异常的处理依赖于平台,因此您需要使用特定于平台的机制来捕获它们(例如 SEH 用于 Windows,或 signal handler 用于 Unix)。 我不推荐这种方法,请继续阅读。

比捕获硬件异常更好的是尽可能努力地防止它。在您的代码中,这只是意味着测试!= 0 的输入指针。请注意,您没有机会识别像char* dst = 0xDEADBEEF; 这样的无效指针,并且在访问异常后处理异常的唯一方法是如上所述的平台相关代码。但是像这样的硬错误通常根本不应该由您的程序处理。

例子:

// Returns the new string length, or -1 on error.
int strcat(char* dst, char const* src)
{
    // Check arguments before doing anything.
    if (dst == 0)
        return -1;
    if (src == 0)
        return -1;

    // Store begin of destination to compute length later on.
    char const* const dstBegin = dst;

    // Skip to end of destination.
    while (*dst != '\0')
        *dst++ ;

    // Copy source to destination.
    do
    {
        *dst++ = *src++;
    }
    while (*src != '\0');

    // Return new length of string (excluding terminating '\0').
    return (dst - dstBegin - 1);
}

您可以选择引入dstSize 参数来指示目标缓冲区的大小,以便您可以有效地检测和防止缓冲区溢出。

【讨论】:

  • 好的,我纠正它。但是我能做些什么来确认 func 工作并为每个输入返回输出,即使是例外情况除外?有人可以帮忙吗?谢谢
  • 为什么目的地存储在低位地址时输入无效?
猜你喜欢
  • 2015-08-16
  • 1970-01-01
  • 2016-01-21
  • 1970-01-01
  • 2013-08-23
  • 1970-01-01
  • 2012-11-23
  • 2018-10-02
  • 2013-09-11
相关资源
最近更新 更多