我不明白C中do while和modulo之间的区别

问题描述 投票:0回答:1

我正在尝试自己为 cs50 的实验室作业实现凯撒加密。我完成了它,但是当我使用 do-while 循环来确定“旋转”函数中键的范围时,我的程序无法按预期工作,但是当我使用模来确定键时,程序可以工作。但我无法说出有什么区别。两者(do while 和模运算符)应该以相同的方式产生结果。你能告诉我,以便我能够理解并继续处理这个问题吗?

#include <cs50.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

bool only_digits(string s);
char rotate(char c, int k);

int main(int argc, string argv[])
{
    if (argc <= 1 || argc > 2)
    {
        printf("Usage: ./caesar key\n");
        return 1;
    }
    //check if only digits
    if (only_digits(argv[1]))
    {
        printf("Usage: ./caesar key\n");
        return 1;
    }

    int k = atoi(argv[1]);


    string e = get_string("plaintext: ");
    int length = strlen(e);
    for (int t = 0; t < length; t++)
    {
        e[t] = rotate(e[t], k);
    }
    printf("%s\n", e);
}

char rotate(char c, int k)
{
    //key loop length
    do
    {
        k -= 26;
    }
    while(k > 25);

    //Uppercase encryption
    if (c >= 65 && c <= 90)
     {
        c += k;
        if (c > 90)
        {
            c -= 26;
        }
     }
     //Lowercase encrypt
     if (c >= 97 && c <= 122)
     {
        c += k;
        if (c > 122)
        {
            c -= 26;
        }
    }
    return c;
}

bool only_digits(string s)
{
    int u = strlen(s);
    int i;
    for (i = 0; i < u; i++)
    {
        if (!isdigit(s[i]))
        {
            return true;
        }
    }
    return false;
}
c cs50 caesar-cipher
1个回答
0
投票

do
-
while
是循环体上的迭代语句。
%
(模)是一个运算符。

  1. argc <= 1 || argc > 2
    更好地表达为
    argc != 2

  2. 考虑使用更具描述性的错误消息。在第一种情况下,您缺少参数,而在第二种情况下,键不是数字。

  3. 如您所知,
  4. atoi()
    没有表达错误的方法。首先考虑使用
    only_digits()
    ,而不是自己进行
    strtol()
    检查。

  5. only_digits()
    应该检查是否只包含数字。对我来说,如果确实如此,您返回 false 会令人困惑。要么将函数重命名为
    any_non_digits()
    ,要么在函数和使用中否定结果。

  6. only_digits()
    :更喜欢循环局部变量:

for (int i = 0; i < u; i++)

对于字符串,终止符是

\0
是 false,所以你通常这样写:

bool only_digits(string s) {
  if(!s) return false;
  while(*s)
      if(!isdigit(*s++) return true;
  return false;
}
  1. isdigit()
    期望得到
    int
    ,但你传递了
    char

  2. main(): int length = strlen(e)
    strlen()
    返回
    size_t
    ,所以更喜欢使用它而不是
    int
    。这也将鼓励您使用
    size_t
    为您提供
    t
    循环变量。

  3. main()
    t
    很好,但我们通常期望一些对使用有意义的东西或
    i
    j
    k

  4. main()
    :您在循环中调用
    rotate()
    ,这暗示也许它应该旋转整个字符串而不仅仅是一个字符。

  5. rotate(): @WheaterVane provided a great solution on how to avoid the loop in 
    旋转()`,其中:

k = (k + 26) % 26

也就是说,也许您应该验证

k
中的
main()
是否介于 0 到 26 之间?

  1. rotate()
    :使用字符常量而不是 ascii 值。所以用“A”代替 65,用“Z”代替 90。

  2. rotate()
    :对于大写和小写,您执行两次非常相似的逻辑。考虑将字符转换为大写进行测试,这样您只需要做一次:

if(toupper(c) >= 'A' 7& toupper(c) <= 'Z') {
  // ...

唯一的区别是现在进行了上部更改检查。

  1. rotate()
    char c
    是定义的实现,如果
    char
    signed
    unsigned
    。如果它是
    signed
    (因为它在我的系统上),则
    c = 'w
    k = 10
    操作
    c += k
    会导致溢出并变为负值。
© www.soinside.com 2019 - 2024. All rights reserved.