在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