预测C代码中的缺陷

时间:2015-08-13 08:36:21

标签: c

最近我参加了一次采访,有几个问题,我必须找到代码中的缺陷。以下是问题。

void fun(char *p)   
{    
    int a = 0;

    int b = strlen(p) - 1;

    int d = 0;

    while(d == 0)
    {
        if(a == b)
        {
            d = 1;
        }
        else
        {
            char t = *(p + a);
            *(p + a) = *(p + b);
            *(p + b) = t;

            a += 1;
            b -= 1;
        }
    }
}

我的回答是:

  1. NULL检查p
  2. 错误的条件if(a == b)。如果字符串的长度是偶数,则这种情况永远不会满足。
  3. 如果有人发现任何其他缺陷,请告诉我,并且欢迎对我给出的答案发表任何评论。

3 个答案:

答案 0 :(得分:5)

代码的目的是在分配字符串的位置反转字符串。问题是:

<强>错误

  • 正如您已经指出的那样,a==b仅适用于奇数长度的字符串。可能是面试问题所寻求的。

    (检查p是否为NULL可能是必要的。你无法从发布的代码中看出来:它取决于函数的文档。对于通用函数,最好留下它检查来电者。)

编码风格

  • 无意义的变量和函数名称。
  • p[a]*(p + a)之前的首选,因为它更具可读性。
  • 循环终止条件非常难看且多余。我更希望while(a < b),这也将修复上述错误。
  • 应使用
  • size_t代替int
  • 没有评论或源代码文档。

应该将代码重写为类似的内容(未经测试):

#include <string.h>

void str_reverse (char* str)   
{    
  size_t start = 0;
  size_t end = strlen(p) - 1;

  while(start < end)
  {
    char tmp   = str[start];
    str[start] = str[end];
    str[end]   = tmp;

    start++;
    end--;
  }
}

请注意,现在实际上不再需要注释,因为变量和函数名称使代码自我记录。

答案 1 :(得分:4)

第一次转化:d只能是01。它只能在while循环条件下读取。实际上,循环条件,函数体可以重写为:

int a = 0;
int b = strlen(p) - 1;

while(a != b)
{
    char t = *(p + a);
    *(p + a) = *(p + b);
    *(p + b) = t;

    a += 1;
    b -= 1;
}

三线区块肯定是交换。在C ++中你可以使用实际的std::swap函数,但是在没有泛型函数和重载的情况下,我猜这样做是很好的。让我们对它进行评论并使用索引表示法:

// Swap p[a] and p[b]
char t = p[a];
p[a] = p[b];
p[b] = t;

a += 1b -= 1也可以重写为++a--b

现在很明显,这个函数使用两个索引ab,它们从两端开始并在中心相交,在路上交换索引字符。它是一个就地字符串反转功能,所以我们将其重命名(和p)。 ab也可以重命名,但IMO足够清楚。

void reverse(char *str)

(从Lundin的答案中删除),ab是数组中的索引,其选择类型应为size_t

size_t a = 0u;
size_t b = strlen(str) - 1u;

现在,你发现的错误:的确,如果strlen(str)是偶数,ab将在中间相互超越,永远不会相等。让我们改变条件来解释这个问题:

while(a < b)

最后,处理str == NULL:这个功能非常低级。对空指针做出反应没有什么用处,所以只要添加一个可理解的失败条件:

assert(str && "Please provide a non-null pointer.");

最终产品:

void reverse(char *str)   
{
    assert(str && "Please provide a non-null pointer.");

    size_t a = 0u;
    size_t b = strlen(str) - 1u;

    while(a < b)
    {
        // Swap str[a] and str[b]
        char t = str[a];
        str[a] = str[b];
        str[b] = t;

        ++a;
        --b;
    }
}

Live on Coliru

答案 2 :(得分:0)

哇,这几乎和以下一样糟糕:

void reverse(char *s){
  for(char *end=s+strlen(s)-1; s<end; ++s,--end)
    *s^=*end^=*s^=*end; //xor swap
}

除了:

  • 它是奇怪的长度和空字符串的错误
  • 不要做指针算法索引 - 选择一个
  • 不必要的复杂性,但简化它1级显示更多气味
    • 删除不必要的d:while(1) { ... if (a==b) break; else...}
    • 现在修复忙循环:while(a!=b){...}
    • 现在修复奇怪的字符串错误:while(a<=b)
    • 空指针错误:while(a<b)...
  • fun,p,a,...意思是确实。