C-对字符串执行数学运算

C-对字符串执行数学运算,c,C,我对C中字符的数学运算感到困惑。这是为了实现一个基本的密码。我正在使用命令行参数argv中存储的字符串 for (int i = 0, n = strlen(p), m = strlen(argv[1]); i < n; i++) { if ((p[i] >= 'A' && p[i] <= 'Z') || (p[i] >= 'a' && p[i] <= 'z')) { if (argv[1][i % m

我对C中字符的数学运算感到困惑。这是为了实现一个基本的密码。我正在使用命令行参数argv中存储的字符串

for (int i = 0, n = strlen(p), m = strlen(argv[1]); i < n; i++)
{
    if ((p[i] >= 'A' && p[i] <= 'Z') || (p[i] >= 'a' && p[i] <= 'z'))
    {
        if (argv[1][i % m] >= 'A' && argv[1][i % m] <= 'Z')
        {
            printf("%c", ((p[i] - 'A') + ((argv[1][i % m]) - 'A')) % 26);
        }

        else if (argv[1][i % m] >= 'a' && argv[1][i % m] <= 'z')
        {
            printf("%c", ((p[i] - 'a') + ((argv[1][i % m]) - 'a')) % 26);
        }
    }

    else 
    {
        printf("%c", p[i]);
    }
然而,我不知道这是为什么。在我看来,我试图做的与教授给出的一个例子没有什么不同:

string s = get_string();
if (s != NULL)
{
    for (int i = 0, n = strlen(s); i < n; i++)
    {
        if (s[i] >= 'a' && s[i] <= 'z')
    {
        printf("%c", s[i] - ('a' - 'A'));
    }
    else
    {
        printf("%c", s[i]);
    }
}

非常感谢您的指导

您是对的,您可以简化代码

在C语言中,像
'a'
这样的东西是
int
类型。(与流行的观点相反,它们不是
字符
类型,只是C标准保证它们可以被分配到
字符
类型,而不会有溢出的危险。)单引号表示法用于避免C不要求特定字符编码的事实。也就是说,您不应该关心数字
'a'
等代表什么。如果你真的在意,那么严格来说你的代码是不可移植的C


因此,是的,你的表达形式是
(a-b)-(c-b)
简化为
a-c

你是正确的,你可以简化你的代码

printf("%c", ((p[i] - 'a') + ((argv[1][i % m]) - 'a')) % 26);
在C语言中,像
'a'
这样的东西是
int
类型。(与流行的观点相反,它们不是
字符
类型,只是C标准保证它们可以被分配到
字符
类型,而不会有溢出的危险。)单引号表示法用于避免C不要求特定字符编码的事实。也就是说,您不应该关心数字
'a'
等代表什么。如果你真的在意,那么严格来说你的代码是不可移植的C

因此,是的,您的形式
(a-b)-(c-b)
的表达式简化为
a-c

printf("%c", ((p[i] - 'a') + ((argv[1][i % m]) - 'a')) % 26);
从芭丝谢芭那里偷来的:

是的,你的(a-b)-(c-b)形式的表达式简化为a-c

那么,(a-b)+(c-b)也会得到a+c-2*b

因此,你首先:

printf("%c", (p[i] + argv[1][i % m] - 2*'a') % 26);
//                                           ^  yet left...
下一点是%26-它将计算0到26之间的值-这些都是您可能不想看到的控制字符

请注意,“a”的数值为97,“a”的数值为65(至少在ASCII中…)。因此,您将有兴趣在结果中重新添加此值:

printf("%c", (p[i] + argv[1][i % m] - 2*'a') % 26 + 'a');
//                                                ^ (or 'A' in the upper case case)
从芭丝谢芭那里偷来的:

是的,你的(a-b)-(c-b)形式的表达式简化为a-c

那么,(a-b)+(c-b)也会得到a+c-2*b

因此,你首先:

printf("%c", (p[i] + argv[1][i % m] - 2*'a') % 26);
//                                           ^  yet left...
下一点是%26-它将计算0到26之间的值-这些都是您可能不想看到的控制字符

请注意,“a”的数值为97,“a”的数值为65(至少在ASCII中…)。因此,您将有兴趣在结果中重新添加此值:

printf("%c", (p[i] + argv[1][i % m] - 2*'a') % 26 + 'a');
//                                                ^ (or 'A' in the upper case case)

那么,你的问题到底是什么?角色是-惊喜你可以用来做常规数学运算的数字。请参阅本页查看你的索引:@dan04对不起,我意识到我没有说清楚。我的代码不打印行
printf(“%c”,((p[i]-'a')+((argv[1][i%m])-'a'))%26)但如果该行仅为
printf(“%c”,p[i]+argv[1][i%m]),则为printf(“%c”,((p[i]-'a')+((argv[1][i%m])-'a'))%26)但如果该行仅为
printf(“%c”,p[i]+argv[1][i%m]),则为int
s?!天哪,这就是为什么
strchr
的第二个参数是整数!现在,如果我们可以在任何地方使用
int*
,为什么我们需要
char
,尤其是
char*
来表示字符串呢?@ForceBru请注意,字符文本的类型是int(即,当您编写'a','b','7',…)!(顺便说一下:C++中的不同…)如果你写的是代码> char c;
c是char类型,占一个字节(而在大多数现代系统中是int的4个字节)。@ForceBru:如果
int
是1的16位补码,则您可能无法这样做。我倾向于将数据填充到本质上可以归结为
无符号字符
数组中。@ForceBru一个可以(假设是4字节整数,然后使用无符号变量),但这会将绝大多数文本文档放大四倍,因为大多数文档只使用ASCII。在大多数其他语言中,只有少数字符需要用两个字节编码,例如。G德语、西班牙语(以及其他语言)。@ForceBru:虽然存储可能很便宜,但RAM和网络带宽并没有那么便宜。此外,还有一个问题,即与期望文本字符串由8位代码单元组成的API和协议的向后兼容性。因此,UTF-8仍然是比UTF-32更流行的编码。字符是
int
s?!天哪,这就是为什么
strchr
的第二个参数是整数!现在,如果我们可以在任何地方使用
int*
,为什么我们需要
char
,尤其是
char*
来表示字符串呢?@ForceBru请注意,字符文本的类型是int(即,当您编写'a','b','7',…)!(顺便说一下:C++中的不同…)如果你写的是代码> char c;
c是char类型,占一个字节(而在大多数现代系统中是int的4个字节)。@ForceBru:如果
int
是1的16位补码,则您可能无法这样做。我倾向于将数据填充到本质上可以归结为
无符号字符
数组中。@ForceBru一个可以(假设是4字节整数,然后使用无符号变量),但这会将绝大多数文本文档放大四倍,因为大多数文档只使用ASCII。在大多数其他语言中,只有少数字符需要用两个字节编码,例如。G德语、西班牙语?