在C中将字母转换为数字

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

谢谢!

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

if (letter >= 'A' && letter <= 'Z') num = letter - 'A'; else if (letter >= 'a' && letter <= 'z') num = letter - 'a'; 

如果要显示这些,那么您需要通过向其添加“0”将数字转换为ascii值:

  asciinumber = num + '0'; 

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

 #include  #include  /* 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; } 

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

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

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

  ABCDEFGHIJKLM NOPQRSTUVWXYZ 

拉丁字母的26 个小写字母

  abcdefghijklm nopqrstuvwxyz 

10位十进制数字

  0123456789 

以下29个图形字符

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

空格字符和控制字符表示水平制表符,垂直制表符和换页符。 源和执行基本字符集的每个成员的表示应该适合一个字节。 在源和执行基本字符集中,上述十进制数字列表中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 

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

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

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

有一个更好的方法。

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

‘A’是0x41。

所以你可以简单地从它们减去0x41,得到数字。 我不太了解c,但有点像:

 int num = 'A' - 0x41; 

应该管用。

另一个,更糟糕的是(但仍然优于26语句)替代方案是使用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"); } 

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

在大多数编程和脚本语言中,有一种方法可以获得任何字符的“序数”值。 (将其视为从字符集开头的偏移量)。

因此,您通常可以执行以下操作:

 for ch in somestring: if lowercase(ch): n = ord(ch) - ord ('a') elif uppercase(ch): n = ord(ch) - ord('A') else: n = -1 # Sentinel error value # (or raise an exception as appropriate to your programming # environment and to the assignment specification) 

当然,这对基于EBCDIC的系统不起作用(并且可能不适用于其他一些奇特的字符集)。 我想一个合理的健全性检查是测试这个函数返回单调增加值在0..26范围内的字符串“abc … xzy”和“ABC … XYZ”)。

一种完全不同的方法是创建字母及其值(一个或两个简单循环)的关联数组(字典,表,哈希)。 然后使用它。 (大多数现代编程语言都支持关联数组。

当然,我不是“做功课”。 你必须为自己做这件事。 我只是在解释这些是任何专业程序员都会使用的明显方法。 (好吧,汇编语言hack也可能只为每个字节掩盖一位)。

由于char数据类型被视为类似于C和C ++中的int数据类型,因此您可以使用以下内容:

 char c = 'A'; // just some character int urValue = c - 65; 

如果您担心案例敏感性:

 #include  // if using C++ #include  int urValue = toupper(c) - 65; 

噢,如果你有C ++

用于unicode定义如何将字符映射到值

 typedef std::map WCharValueMap; WCharValueMap myConversion = fillMap(); WCharValueMap fillMap() { WCharValueMap result; result[L'A']=0; result[L'Â']=0; result[L'B']=1; result[L'C']=2; return result; } 

用法

 int value = myConversion[L'Â']; 

我为一个项目编写了这段代码,我想知道这种方法是多么天真。

这里的好处是似乎与标准相符,我的猜测是运行时间大约是。 O(k)其中k是字母表的大小。

 int ctoi(char c) { int index; char* alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; c = toupper(c); // avoid doing strlen here to juice some efficiency. for(index = 0; index != 26; index++) { if(c == alphabet[index]) { return index; } } return -1; } 
 #include #include int val(char a); int main() { char r; scanf("%c",&r); printf("\n%d\n",val(r)); } int val(char a) { int i=0; char k; for(k='A';k<=toupper(a);k++) i++; return i; }//enter code here