这是我改变角色大小写的函数的代码。例如,“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”而不是“?”。是什么导致了这个问题?我该如何解决?
答案 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
测试 - 如果您认为这很重要(可能不是,我认为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));
问题会更加明显。
从长远来看,防御性编码(编写能够捕捉到“麻烦”的额外几个字符)非常值得...
答案 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;
}