“?”转换为大写和小写时变为“1”

时间:2013-11-07 00:25:19

标签: c

这是我改变角色大小写的函数的代码。例如,“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,你好吗?”进行测试时。我期待“你好,你怎么样?”但是我的节目给了“你好,你怎么样” 注意最后的“1”而不是“?”。是什么导致了这个问题?我该如何解决?

5 个答案:

答案 0 :(得分:3)

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

output = malloc(sizeof(src));

sizeof总是返回一个常量(除非应用于VLA),因此它不会得到字符串的长度。你想要的是strlen( src ) + 1

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

答案 1 :(得分:1)

我认为你的问题是你遇到了另一起案件:

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

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

因此,似乎有一个逻辑错误,其中i的某些值只到达逻辑块的一半。使用else if可以解决这个问题。但是,您的控制流(是一个while循环)将继续迭代而不会递增i,直到它正确为止。虽然这绝对是重构的东西,但这不是你的错误。

注意:重构此代码的一种方法是使用for循环来避免不得不一遍又一遍地写i++

答案 2 :(得分:0)

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

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

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

现在,因为我现在已经增加并具有“原始”i的值,循环的以下部分也会执行,导致i的双倍增量:

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

这样的错误是每当索引变量或迭代器变量可用时,“for”循环通常优先于“while”循环的主要原因之一。仅当循环条件的控制超出本地代码控制(例如读取文件或套接字)时,才使用“while”循环;其他一切都使用“for”循环。

答案 3 :(得分:0)

您的代码中存在两个问题。

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

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

请注意,您必须释放在某些时候分配的内存(在使用完结果后),否则会出现内存泄漏(每次调用该函数时都会创建新的内存块)。

第二个问题出在你的while循环中。虽然您正确地测试了输入字符串的结尾,但实际上是在循环内递增i,然后查看下一个字符。下一个字符未经isalpha测试 - 如果您认为这很重要(可能不是,我认为touppertolower应该足够聪明)那么您就不应该这样做。添加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));

问题会更加明显。

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

答案 4 :(得分: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;
}