转换字符串中每个字母的大小写

3
#include <stdio.h>

int main() {
    int i;  
    char arr[100];

    for (i = 0; i < 100; i++)  
        scanf("%c", &arr[i]);  
    for (i = 0; i < 100; i++) {  
        if ('a' <= arr[i] && arr[i] <= 'z')  
            arr[i] =-32;  
        else
        if ('A' <= arr[i] && arr[i] <= 'Z')  
            arr[i] =+32;  
    }  
    printf("%s", arr);  
    return 0;   
}

问题如下:

您收到了一个字符串,包含大写和小写英文字母。您需要更改此字符串中每个字母的大小写。也就是说,所有大写字母都应转换为小写字母,而所有小写字母都应转换为大写字母。然后,您需要将结果字符串打印到输出。

上面的代码有什么问题?它已经成功编译,但出现了运行时错误。


1
运行时错误是什么?你输入了什么字符串? - Dave Costa
一个“显而易见”的问题是你没有终止字符串。 - Some programmer dude
1
把编译器的警告级别调高一些。我相信它至少会给你一些警告。 - Mike Sherrill 'Cat Recall'
我正在使用一个在线评测系统,输入是'abcdE',但输出结果是ABCDe{@ÿÿÿÿðÿÿ¨ÑdËÀ4¢ËÈA¢Ëý@ ïÿÿ°@,显然是错误的。 - Karan Singh
运行时错误是因为%s期望arr有一个终止的'\0',但它没有。此外,在转换大小写时,您的代码假定ASCII编码(或兼容),这实际上并不保证。查找标准头文件<ctype.h>中声明的函数isupper()islower()toupper()tolower(),它们被保证可以工作。 - Peter
显示剩余9条评论
6个回答

4
你的代码存在多个问题:
- 主要问题在于你调整大小写的方式:`arr[i] =-32;` 不会将 `arr[i]` 减去 `32`,而是将 `32` 存储到 `arr[i]` 中。正确的赋值运算符应该是 `-=`。同样,在另一种情况下,`+=` 也存在相同的问题。 - 通过减去 `32` 将小写字母转换为大写字母只适用于 ASCII 码,但对于其他字符集并不可移植。同样,将字符与 `'a'` 和 `'z'` 进行比较仅适用于 ASCII 码,而对于 EBCDIC 则不适用。应该使用 `` 中提供的函数实现这些操作。 - 你使用 `scanf("%c"...)` 读取了 100 个字符,但没有检查其返回值,也没有以 null 结尾该数组。此外,你应该最多读取数组大小减一的字符,以便留出空间放置 `\0` 字节。按照当前的方式编写程序,当执行 `printf("%s", arr);` 时会导致未定义的行为,因为 `arr` 没有以 null 结尾。
以下是已纠正的版本:
#include <ctype.h>
#include <stdio.h>

int main(void) {
    int c;

    while ((c = getchar()) != EOF) {
        if (isupper(c))
            c = tolower(c);
        else
        if (islower(c))
            c = toupper(c);

        putchar(c);
    }
    return 0;   
}

+1 好的,说实话我很喜欢这个答案。我可以取消选择之前的答案,选择你的作为更好的吗? 另外,我们为什么要将c声明为int当我们会输入字符? - Karan Singh
@KaranSingh:c 被定义为 int,以处理 getc() 返回的所有值:包括所有的 unsigned char 值和特殊值 EOF。类型 char 无法正确处理所有情况。EOF 将是 '\377' (iso-latin1 中的 'ÿ') 或永远不匹配。 - chqrlie

2
最明显的问题是你没有在字符串末尾添加空字符,因此当你调用printf("%s", arr)时,行为将是不可预测的。

2
你的代码问题在于它从未终止字符串。如果你读取了100个字符,然后想用printf中的%s打印它们,你必须在末尾添加一个空终止符,就像这样:
char arr[100+1]; // See +1
... // Reading code
arr[100] = '\0';

请注意,库函数islower/isupper提供了一种便携式且更易读的测试字符类型的方法。同样,tolower/toupper比简单地加减32提供了更多关于你代码意图的信息。此外,使用这些标准函数的C代码将在具有非ASCII字符编码的系统上工作。

如果我的字符串不是100个字符长,但我仍然想终止它。我该怎么做? 还有一些我在问题下面发表的评论。 - Karan Singh
@KaranSingh 如果你想在位置 n 终止字符串,使用 arr[n] = '\0'; 在最后一个字符后面的一个位置写入零就足够了。 - Sergey Kalinichenko

1
为了使用printf("%s", arr),您需要在arr末尾添加一个空字符。
一种方法是:
  • 声明char arr[101]
  • arr[100] = 0

0

你的代码存在几个问题:输入字符串没有以 null 结尾,大小写转换不正确,以及对 =- / -= 和 =+ / += 运算符的混淆。

下面的代码是基于你的代码:

为了避免问题,它使用 fgets() 而不是 scanf() 来获取以 null 结尾的字符串,仅供示例。

此外,它使用 C 库函数来避免不同字符集的问题,简化条件并进行大小写操作。

根据 @chqrlie 的建议编辑以提高代码质量。

#include <stdio.h>
#include <ctype.h>

int main()
{
    int i;  
    char arr[101];

    printf("Enter string: ");
    fgets(arr, sizeof(arr), stdin);;  
    for(i=0;i<strlen(arr); i++)  
    {
        int value = (unsigned char) arr[i]; // to properly use int parameters, as expected by ctype.h next functions
        if (isupper(value))
        {
            arr[i]=tolower(value);  
        }
        else {
            if (islower(value))
            {
                arr[i]=toupper(value);
            }
        }
    }  
    printf("%s", arr);  

    return 0;
}

在这里测试一下。


使用不安全、过时的函数gets()会返回-1。此外,您使用了tolowertoupper,您还应该使用islower()isupper(),并将char参数强制转换为(unsigned char)。免责声明是一个无聊的借口,请使用fgets() - chqrlie
@chqrlie,你是对的。如之前所述,我最初使用gets()来保持示例简单。但我同意你关于(不好)使用废弃函数的看法。现在已被编辑以使用当前有效的替代方法。 - MarcM
我取消了踩的操作。还要注意一下islower()isupper()等函数中有符号字符参数的问题。 - chqrlie

0
    #include <iostream>
#include<string>
using namespace std;
int main() {
    int i;
    string str;
    cin >> str;    //Reading input from STDIN
    // cout << "Input number is " << i << endl; // Writing output to STDOUT
    for(i=0;i<str.length();i++){
        if((str[i]>='A' && str[i]<='Z')||(str[i]>='a'&& str[i]<='z')){
            if(str[i]>='A' && str[i]<='Z'){
                str[i]=str[i]+32;
                // cout<<str[i];
            }
            
            else if(str[i]>='a' && str[i]<='z'){
                str[i]=str[i]-32;
            }
                
            cout<<str[i];   
        }
    }

}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接