C &引用&引用;变成;1“;将转换为大写和小写时
下面是我的代码,用于更改字符大小写的函数。例如,“ABC”将变成“ABC”,反之亦然C &引用&引用;变成;1“;将转换为大写和小写时,c,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') { //Che
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;}
大多数时候,这对我来说似乎很好。然而,当它被测试为“你好,世界,你好吗?”。我期待着“你好,世界,你好吗?”但我的程序给出了“你好,世界,你好吗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
,直到正确执行为止。虽然这肯定是需要重构的,但这并不是您的bug
注意:重构此代码以使其更干净的一种方法是使用
for
循环,以避免反复编写i++
。我认为您的问题是您的案例正在演变为另一个案例:
// 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
,直到正确执行为止。虽然这肯定是需要重构的,但这并不是您的bug
注意:将此代码重构为更干净的方法之一是使用
for
循环,以避免反复写入i++
。缓冲区分配不正确,导致缓冲区溢出:
output = malloc(sizeof(src));
sizeof
总是返回一个常量(除非应用于VLA),这样就不会得到字符串的长度。您需要的是strlen(src)+1
关于循环因子分解的其他答案在抽象级别上有一点,但您的循环似乎并不正确。它总是转到下一个字符,从不检查同一个字符两次,也从不离开缓冲区的末尾(假设缓冲区在第一个位置是有效的)。控制流有点奇怪。缓冲区分配不正确,导致缓冲区溢出:
output = malloc(sizeof(src));
sizeof
总是返回一个常量(除非应用于VLA),这样就不会得到字符串的长度。您需要的是strlen(src)+1
关于循环因子分解的其他答案在抽象级别上有一点,但您的循环似乎并不正确。它总是转到下一个字符,从不检查同一个字符两次,也从不离开缓冲区的末尾(假设缓冲区在第一个位置是有效的)。控制流有点奇怪。该错误是由循环变量的双倍增量引起的 假设输出[i]是大写,而输出[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”循环。该错误是由循环变量的双倍增量引起的 假设输出[i]是大写,而输出[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”循环。代码中有两个问题 首先,正如其他人指出的,您没有为返回字符串分配正确的内存量
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));
问题会更加明显
从长远来看,防御性编码(编写额外的几个字符会引起“麻烦”)是值得的…您的代码中有两个问题 首先,正如其他人指出的,您没有为返回字符串分配正确的内存量。