在C中将字母转换为数字

use*_*466 6 c

我正在尝试编写一个将字母转换为数字的代码.例如,A ==> 0 B ==> 1 C ==> 2,依此类推.我想写下26条陈述.我想知道是否有更好的方法来做到这一点......

谢谢!

caf*_*caf 11

这种方式我认为比switch方法更好,但是符合标准(不假设ASCII):

#include <string.h>
#include <ctype.h>

/* returns -1 if c is not an alphabetic character */
int c_to_n(char c)
{
    int n = -1;
    static const char * const alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    char *p = strchr(alphabet, toupper((unsigned char)c));

    if (p)
    {
        n = p - alphabet;
    }

    return n;
}
Run Code Online (Sandbox Code Playgroud)

  • 我会给你一张@caf投票,因为它处理标准中的所有字符集.这也是我见过有人正常使用const const作为指针和指针的罕见时期之一:-)当然,作为一个老朋友,我会做的:'返回p?(int)(p - alphabet): - 1;' 而不是所有与n和if语句相关的东西. (3认同)

Jam*_*ack 9

如果你需要处理大写和小写,那么你可能想要做类似的事情:

if (letter >= 'A' && letter <= 'Z')
  num = letter - 'A';
else if (letter >= 'a' && letter <= 'z')
  num = letter - 'a';
Run Code Online (Sandbox Code Playgroud)

如果要显示这些,则需要通过向其添加"0"将数字转换为ascii值:

  asciinumber = num + '0';
Run Code Online (Sandbox Code Playgroud)

  • 或者,使用`num = toupper(letter) - 'A'`将字母转换为大写,从而避免使用条件.`toupper()`函数位于`ctype.h`头文件中. (4认同)

use*_*109 7

C标准不保证字母表中的字符将按顺序编号.因此,便携式代码不能假设,例如,'B'-'A'等于1.

C规范的相关部分是第5.2.1节,其中描述了字符集:

3基本源和基本执行字符集应具有以下成员:拉丁字母表的26个大写字母

    ABCDEFGHIJKLM   
    NOPQRSTUVWXYZ
Run Code Online (Sandbox Code Playgroud)

拉丁字母的26 个小写字母

    abcdefghijklm
    nopqrstuvwxyz
Run Code Online (Sandbox Code Playgroud)

10位十进制数字

    0123456789
Run Code Online (Sandbox Code Playgroud)

以下29个图形字符

    !"#%&'()*+,-./: 
    ;<=>?[\]^_{|}~ 
Run Code Online (Sandbox Code Playgroud)

空格字符和控制字符表示水平制表符,垂直制表符和换页符.源和执行基本字符集的每个成员的表示应该适合一个字节.在源和执行基本字符集中,上述十进制数字列表中0之后的每个字符的值应比前一个值大1.

因此规范只保证数字将具有顺序编码.字母字符的编码方式绝对没有限制.


幸运的是,有一种简单有效的方法将A转换为0,B转换为1,等等.这是代码

char letter = 'E';                  // could be any upper or lower case letter
char str[2] = { letter };           // make a string out of the letter
int num = strtol( str, NULL, 36 ) - 10;  // convert the letter to a number
Run Code Online (Sandbox Code Playgroud)

这个工作的原因可以在手册页中找到strtol:

(在10以上的基数中,大写或小写的字母'A'代表10,'B'代表11,依此类推,'Z'代表35.)

所以传递36 strtol作为基础告诉strtol转换'A''a'10 'B''b'11,依此类推.您需要做的就是减去10以获得最终答案.


Noo*_*ilk 5

有一个更好的方法.

在ASCII(www.asciitable.com)中,您可以知道这些字符的数值.

'A'是0x41.

所以你可以简单地从它们减去0x41,得到数字.我不太了解c,但是类似于:

int num = 'A' - 0x41;
Run Code Online (Sandbox Code Playgroud)

应该管用.

  • 克里斯:'A'到'Z'是连续的*不是由标准保证(只有'0'到'9'). (7认同)
  • 还有:`int num = letter - 'A';` (4认同)
  • @silky - 不,它没有.使用`0x41`而不是''A'是愚蠢的.为什么我们不直接用二进制编写我们的数字和字符串?为什么不计算我们自己的跳转和指针算术?@caf - 这已在各个地方指出,但我在精神上有一个相当艰难的一天所以它不会伤害提醒我.;)但是,是的,我从'0'推断 - '9'是连续的'A' - 'Z',虽然不是真的,但这是一个相当安全的假设,除非你打算为大型机编写代码.在几乎所有情况下,都不会改变` - 'A'`优于` - 0x41`这一事实. (3认同)
  • 更常见的是使用`int num ='A' - 'A'`(用问题中的字符或变量替换第一个)__在case_中我们不使用ASCII,尽管我认为这可能是标准所保证的.我知道标准保证'A'..'Z'在字符集中是连续的. (2认同)

Chr*_*utz 5

另一个更糟糕的(但仍然优于26个if语句)替代方案是使用switch/ case:

switch(letter)
{
case 'A':
case 'a': // don't use this line if you want only capital letters
    num = 0;
    break;
case 'B':
case 'b': // same as above about 'a'
    num = 1;
    break;
/* and so on and so on */
default:
    fprintf(stderr, "WTF?\n");
}
Run Code Online (Sandbox Code Playgroud)

只有在字母和代码之间完全没有关系时才考虑这一点.由于在你的情况下字母和代码之间有明确的顺序关系,使用它是相当愚蠢的并且维护很糟糕,但如果你必须将随机字符编码为随机值,这将是避免写入的方法a zillion if()/ else if()/ else if()/ else语句.

  • 这不是*太傻了.尽管你在别处评论@Chris,但C99只要求数字字符按顺序排列.Alpha可以遍布各处(例如EBCDIC及其两个不同的区域).事实上,这是迄今为止唯一正确的答案.+ 1. (2认同)