【问题标题】:Handling ASCII alphabets in C在 C 中处理 ASCII 字母
【发布时间】:2017-06-11 16:27:53
【问题描述】:
#include <stdio.h>
#include <string.h>

int main()
{
    int key;
    char line[500];
    char ch = '\0';
    int i = 0;

    printf("Enter key: ");
    scanf("%d", &key);
    getchar();

    printf("Enter line: ");

    while(ch != '\n')
    {
        ch = getchar();
        line[i] = ch;
        i++;    
    }

    int length = i; 
    int k = 0;
    char temp[length];

    for(i = 0; i < length; i++)
    {

        if((int)line[i] >= 65 && (int)line[i] <= 90)
        {           
                temp[k++] = (int)line[i] + key;
        } else if((int)line[i] >= 97 && (int)line[i] <= 122){
                temp[k++] = (int)line[i] + key;
        } else {
            temp[k++] = line[i];
        }
    }

    printf("\n");

    for(i = 0; i < length; i++)
    {
        printf("%c", temp[i]);
    }
}

到目前为止,我所做的是将字符转换为另一个字符。例如,如果我输入“abc ABC”,并且添加值(int key)是3,那么它应该打印出“def DEF”。

这很好用,但我想进一步实现的是在角色越界时倒带。例如,如果我输入“XYZ”并且添加值为3,它应该打印出“ABC”,而不是“[]”。我可以就如何解决这个问题获得任何帮助或建议吗?谢谢..

【问题讨论】:

  • 使用模运算。
  • 对不起,我该怎么做模运算?
  • 这里不需要cast,因为整数提升是隐式发生的。
  • 哦,谢谢!!但是,这里发生了另一个问题.. 如果我输入 5 作为加数,输入“Veni,vidi,vici”作为字符串输入,我得到“jsn,nin,nhn”,而不是“Asn,nin,nhn”我可以请知道原因吗?
  • 一般使用int来存储getchar()的返回值。

标签: c ascii computer-science


【解决方案1】:

首先,当我看到

if((int)line[i] >= 65 && (int)line[i] <= 90)

我的第一反应是,“65 和 90 是什么意思?”好吧,我知道,但是,这些数字对您来说是不必要的麻烦,对读者来说也是不必要的麻烦。所以就说

if(line[i] >= 'A' && line[i] <= 'Z')

相反。在 C 中,像'A' 这样的字符常量的值是机器字符集中字符的值,或者 ASCII 中的 65。 (我也去掉了一些不必要的演员表。)

接下来,解决问题的一种蛮力方法是只检查溢出:

if(line[i] >= 'A' && line[i] <= 'Z')
{
    temp[k] = line[i] + key;
    if(temp[k] > 'Z')
        temp[k] -= 26;
    k++;
}

由于在完成之前我必须对temp[k] 做几件事,所以我将k++ 移到了末尾。

对于 a-z 情况,您可以使用类似的代码。

如果你想让程序更通用,还有key可能是负数的可能性。在这种情况下,您还必须担心字母“小于”A。你可以像这样扩展代码:

if(line[i] >= 'A' && line[i] <= 'Z')
{
    temp[k] = line[i] + key;
    if(temp[k] > 'Z')
        temp[k] -= 26;
    else if(temp[k] < 'A')
        temp[k] += 26;
    k++;
}

再一次,你会在 a-z 的情况下重复这个。

现在,这样做的非暴力方法是认识到我们在这里执行的“环绕”算术也称为“模数”算术,因为它与“模数”或“余数”有关操作员,%。因此,如果您了解% 的工作原理,您可以编写如下代码:

if(line[i] >= 'A' && line[i] <= 'Z')
{
    int c = line[i] - 'A';
    c = (c + key) % 26;
    temp[k++] = c + 'A';
}

这仍然不是很简单,因为我们必须从像“Y”这样的字母到它在字母表中从 0 开始的位置 (25),再到它的移位值 (28,假设 key 为 3) , 到它的“模”值 {2},然后最后回到像 'B' 这样的字母。

或者,更详细地说,大写字母在 ASCII 中是 65 到 90。所以我们减去 65 得到 0-25 范围内的数字。一旦我们在 0-25 范围内,我们就可以使用模数运算,因为% 26 基本上意味着“仅在 0 - 25 范围内的整数”。最后,当我们完成模数运算时,我们再次添加 65,以恢复到实际字母的 65-90 范围。 (而不是减和加 65,我们减和加'A',因为它是相同的值,但更清晰。)

而且,我仍然只显示大写字母的代码;对于 a-z 情况,您也必须重复此代码。

【讨论】:

  • 如果偏移量为 300 会发生什么?提示 - 它不会起作用。
  • @RoiHatam 当然。但是 (a) 他不会那样做(或不期望它会起作用),并且 (b) 我们正在通过简单的阶段建立 %
  • 如果我使用这种情况,我会丢失我的 '(space)' 我应该如何避免丢失它?
  • @seung 我发布的代码片段根本不应该改变空格字符——它们应该只改变大写字母,类似的情况应该只改变小写字母。所以我不确定你为什么说你正在失去你的空间。您了解我发布的代码应该如何工作吗?
猜你喜欢
  • 2013-07-13
  • 2011-06-03
  • 2021-06-04
  • 1970-01-01
  • 2012-12-07
  • 2021-03-04
  • 2013-03-22
  • 2014-02-27
  • 1970-01-01
相关资源
最近更新 更多