我在C中遇到问题:
我无法弄清楚如何将大写更改为小写,反之亦然,而不使用if语句,函数,也不更改字母以外的字符。
此问题的解决方案对有限的资源系统非常有用。
答案 0 :(得分:4)
您可以执行以下操作:
c ^= ((c>='A' && c <= 'Z') || (c>='a' && c <= 'z')) << 5
...但我不确定资源有限的系统比使用&#39;更好。等
答案 1 :(得分:2)
因为&#39; A&#39;是0x41和&#39; a&#39;是0x61,你可以将0x20位异或。
0x61 ^ 0x20 == 0x41 /* a -> A */
0x41 ^ 0x20 == 0x61 /* A -> a */
在完整字符串char *s
的循环中(假设它只包含字母):
for (; *s; s++) *s ^= 0x20;
<小时/> 的修改
我们应该只将它应用于信件。 &#39; A&#39;是0x41。 &#39; Z&#39;是0x5A,小写字符只是upper_case_char + 0x20。
所以c & 0xDF
始终是角色的大写版本。
混淆测试看起来像这样:
for (; *s; s++) *s ^= ((*s & 0xDF) >= 0x41 && (*s & 0xDF) <= 0x5A)
? 0x20 : 0x00;
或同等的,稍微更具可读性:
for (; *s; s++) *s ^= ((*s & 0xDF) >= 'A' && (*s & 0xDF) <='Z')
? 0x20 : 0x00;
答案 2 :(得分:1)
怎么样
void changecase (char * s)
{
for (; *s; s++)
*s ^= ((*s>='A') && (*s<='Z') || (*s>='a') && (*s<='z'))?32:0;
}
如果您不喜欢三元组或比较运算符:
void changecase (char * s)
{
for (; *s; s++)
*s ~= (
/* check top bits are 0100 or 0110 */
((*s & 0xE0 ^ 0x80) - 0x40) & 0x100) &&
/* not codes 64 or 96 */
(*s & 0x1f) &&
/* first 26 from 64 onwards only */
!(((*s && 0x1f) - 27) & 0x100)
) <<5;
}
答案 3 :(得分:0)
最高效的是定义static char conversionTable = {0x00, 0x01, ...}
。您只需将A
放在a
的ASCII列表中,然后将z
放在Z
的位置。然后转换成:
char original;
char converted;
converted = converionTable[original];
这只需要256字节的内存,转换速度非常快,因为它只不过是一个索引表访问。
理论注释:如果我是对的,C标准不保证使用ASCII作为字符表示。如果情况确实如此,问题仍然可以解决,但会变得更加混乱。表格不起作用。