1

这是我更改字符大小写的函数的代码。例如“ABC”会变成“abc”,反之亦然。

char *flipCase(const char *src){

char *output;
output = malloc(sizeof(src));
//Copy source to output
strcpy(output,src);
int i = 0;
//Check if the case is lower or upper
while(output[i] != '\0')
{
    //Check if it's alphabetic
    if (isalpha(output[i]))
    {
        //if it's upper case
        if (isupper(output[i]))
        {
            //Convert to lower case and increment i
            output[i]= tolower(output[i]);
            i++;
        }
        //if it's lower case
        if (islower(output[i]))
        {
            //Convert to upper and increment i
            output[i]=toupper(output[i]);
            i++;
        }

    }
    //Else, skip it
    else 
    {
        i++;
    }

}
return output;}

大多数时候,这对我来说似乎很好。然而,当它用“Hello World, How are you?”进行测试时。我期待“你好,世界,你好吗?” 但是我的程序给出了“你好,世界,你好吗1” 注意最后的“1”而不是“?”。是什么导致了问题?我该如何解决?

4

5 回答 5

3

缓冲区分配不正确,导致缓冲区溢出:

output = malloc(sizeof(src));

sizeof始终返回一个常量(除非应用于 VLA),因此它不会为您提供字符串的长度。你想要的是strlen( src ) + 1.

关于循环分解的其他答案在抽象级别上有一点,但您的循环似乎并不正确。它总是转到下一个字符,它从不检查同一个字符两次,并且它永远不会离开缓冲区的末尾(假设缓冲区首先是有效的)。控制流有点奇怪。

于 2013-11-07T00:36:58.590 回答
1

I think your problem is you have a case falling through to another case:

// Case IS_UPPER
// Some code
// i++;

// Case IS_LOWER (is reached by the same iteration but i is one higher!
// Some code
// i++;

Thus, you seemed to have a logic bug where some values of i are only reaching half of your logic block(s). Using else if could fix this. However, your control flow (being a while loop) will continue to iterate without incrementing i until it is correct to do so. While this is definitely something to refactor, it isn't your bug here.

Note: One way to refactor this code to be cleaner would be by using a for loop to avoid having to write i++ over and over again.

于 2013-11-07T00:28:15.880 回答
0

您的代码中有两个问题。

首先 - 正如其他人指出的那样,您没有为返回字符串分配正确的内存量。sizeof(src)是指针在您的平台中的大小(可能是 8 个字节)。你需要

output = malloc(strlen(src) + 1);

请注意,您必须在某个时候释放如此分配的内存(在您使用完结果之后),否则您将遇到内存泄漏(每次调用函数时都会创建新的内存块)。

第二个问题在你的while循环中。尽管您正确测试了输入字符串的结尾,但实际上您是i在循环内递增,然后查看下一个字符。下一个角色没有经过测试isalpha- 如果您认为这很重要(可能不是,我认为toupper并且tolower应该足够聪明),那么您不应该这样做。添加一个else将清除它:

if(isalpha(output[i])) {
    if (isupper(output[i]))
    {
        //Convert to lower case and increment i
        output[i]= tolower(output[i]);
        i++;
    }
    //if it's lower case
    else {
        if (islower(output[i]))
        {
            //Convert to upper and increment i
            output[i]=toupper(output[i]);
            i++;
        }
    }
}

作为一般规则,如果您使用strncpy而不是strcpy您将避免“复制超出允许范围”(只要您n正确使用参数:“我为复制分配的空间”)。在你的情况下,你分配sizeof(src)了,如果你已经完成了

strncpy(output, src, sizeof(src));

问题会更加明显。

从长远来看,防御性编码(编写额外的几个字符会捕获“麻烦”)非常值得......

于 2013-11-07T01:10:36.120 回答
0

该错误是由循环变量的双倍增量引起的。

假设 output[i] 为大写,而 output[i+1] 为小写。然后循环的以下部分执行并递增 i:

    if (isupper(output[i]))
    {
        //Convert to lower case and increment i
        output[i]= tolower(output[i]);
        i++;
    }

现在,因为 i 现在已经被递增并且具有“原始” i 的值,所以循环的以下部分也将执行,导致 i 的双倍递增:

    if (islower(output[i]))
    {
        //Convert to upper and increment i
        output[i]=toupper(output[i]);
        i++;
    }

此类错误是每当索引变量或迭代器变量可用时“for”循环通常优于“while”循环的主要原因之一。只有在循环条件的控制超出本地代码控制的情况下才使用“while”循环,例如读取文件或套接字;对于其他所有内容,请使用“for”循环。

于 2013-11-07T00:50:31.527 回答
0

最重要的是 malloc 大小是错误的(你总是 malloc 指针的大小)其次,逻辑是混乱的 WRT 上下,你的输出会错过 2 个随后的大写字母等。更不重要的是,当您可以随时复制数据时,没有理由复制数据然后对其进行操作。

char *flipCase(const char *src){
char *output=malloc(strlen( src ) + 1);
int i;

for(i=0; *src; src++,i++){
    if (isupper(*src)){
        output[i]=tolower(*src);
    }else if (islower(*src)){
        output[i]=toupper(*src);
    }else{
        output[i]=*src;
    }
}
return output;
}
于 2013-11-07T01:16:59.090 回答