凯撒C中数字的密码

时间:2019-12-08 11:44:17

标签: c

我想为数字输入Caesar cipher。 (在所有数字前加3)

输入:52输出:85

输入:954输出:287

输入:-10457输出:-43780

如果有人帮助我,我会很高兴。

我尝试过这种方法,但是当我输入的数字少于5个数字时,它会以3开头。

当我输入52时,它输出33385。我还想问用户该程序应该接受一个新数字还是直接退出。

#include <stdio.h>
#include <stdlib.h>

int main()
{

    int number, operation;

    printf("Enter the number: ");
    scanf("%d", &number);

    printf("%d", ((number / 10000) + 3) % 10);
    printf("%d", (((number % 10000) / 1000) + 3) % 10);
    printf("%d", (((number % 1000) / 100) + 3) % 10);
    printf("%d", (((number % 100) / 10) + 3) % 10);
    printf("%d\n", ((number % 10) + 3) % 10);

    printf("press 1 to continue or 2 for exit.");
    scanf("%d", &operation);

    switch (operation) {
    case 1:
        printf("Enter the number: ");
        scanf("%d", &number);

        printf("%d", ((number / 10000) + 3) % 10);
        printf("%d", (((number % 10000) / 1000) + 3) % 10);
        printf("%d", (((number % 1000) / 100) + 3) % 10);
        printf("%d", (((number % 100) / 10) + 3) % 10);
        printf("%d\n", ((number % 10) + 3) % 10);

        break;

    case 2:

        break;
    }

    return 0;
}

3 个答案:

答案 0 :(得分:5)

当您输入52时,您的数字变量取值为00052,它将随您的代码转换为33385。如果您不希望前导3,则可以不打印它们,也可以先检索数字并计算仅当该数字不为0时,其相关的凯撒数字。

考虑任何int数字(无论数字为)的另一种可能性是:

#include "stdio.h"
#include <stdlib.h>

int main()
{
    int number, abs_number;
    int caesar_number = 0;
    int digit_pos = 1;

    printf("Enter the number: ");
    scanf("%d", &number);

    abs_number = abs(number);

    while (abs_number != 0)
    {
        caesar_number += (((abs_number % 10) + 3) % 10) * digit_pos;
        abs_number /= 10;
        digit_pos *= 10;
    }

    if (number < 0)
    {
        caesar_number = -caesar_number;
    }
    printf("Result is: %d\n", caesar_number);

    return 0;
}

答案 1 :(得分:2)

此解决方案适用于所有测试用例(正数和负数),大于100000的数字以及零的数字:

#include "stdio.h"
#include "stdlib.h"

const int SHIFT = 3;

int main() {
    int number, abs_number, is_negative, operation, result, decimal_place;

    do {
        result = 0;
        decimal_place = 1;

        printf("Enter the number: ");
        scanf("%d", &number);

        // remove the sign before entering the cipher logic...
        abs_number = abs(number);
        // ...but do remember it so we can add it back later
        is_negative = number < 0;

        // from least to most significant decimal place
        do {
            // cipher the digit and accumulate it in the result
            result += (((abs_number % 10) + SHIFT) % 10) * decimal_place;
            // remove the consumed digit from the input variable
            abs_number /= 10;
            // move to the next decimal place
            decimal_place *= 10;
        } while (abs_number > 0);

        printf("Result is: %s%d\n", is_negative ? "-" : "", result);

        printf("Press 1 to continue or 2 for exit.");
        scanf("%d", &operation);

    } while (operation == 1);  // repeat if user requested another cipher

    return 0;
}

原始代码中有一些需要注意的地方:

  • 您的代码不会循环。 switch大小写不会帮助您重复操作。为此,您需要一个while循环;
  • 它不适用于较大的数字:您必须添加一行额外的代码来处理大于100000的数字...这导致了我的下一个观点:
  • 您有重复的代码:您的逻辑以两种不同的方式重复。第一个是迭代主体。即使您用switch循环替换了while语句,您的第一次迭代也不必要地在循环外展开。第二种是您处理输入数字的每个小数位的方式。如果您使用相同的代码段来处理任何小数位数,那会更好吗?复制代码被认为是不好的做法。它使代码更大,更难维护,并且容易使重复的代码仅在一个位置而不是另一个位置被更改。您始终希望避免重复代码。

答案 2 :(得分:1)

除非不记录用户输入的长度,否则“凯撒数字密码”不可逆。使用"777""7""000""0"之类的输入,输出必须是4个不同的答案才能转换回去。

要维护内部数字表示形式,请考虑使用"%n"来跟踪用户输入的长度。

static void print_digits(int a, int length, int offset) {
  if (length > 1) {
    print_digits(a/10, length-1);
  }
  putchar((a+offset)%10 + '0');
}

...

#define OFFSET 3

int number;
int n1, n2;
int offset = OFFSET % 10;
if (offset < 10) offset += 10; // Handle negative OFFSET

printf("Enter the number: ");
if (scanf(" %n%d%n", &n1, &number, &n2) == 1) {
  int length = n2 - n1;
  if (number < 0) {
    putchar('-');
    number = -number;
    length--;
  }
  print_digits(number, length, offset);
}

以上代码在选择输入幅度大于INT_MAX/10左右时遇到问题。要处理大整数,请考虑移至字符串处理。