C программа не обрабатывает нечисловые клавиши c - PullRequest
0 голосов
/ 21 апреля 2020

Добрый вечер, люди надеются, что у вас все хорошо, я прихожу ко всем вам, потому что мне нужна некоторая помощь по поводу некоторого кода C, который я написал, помните, что я только начал кодировать в C, так что извините, если этот вопрос звучит глупо .

По сути, я делаю CS50, и мы пишем программу, которая кодирует сообщения, поэтому сначала мы запрашиваем у пользователя аргумент командной строки, который будет ключом, который мы будем использовать для преобразования простого текста в зашифрованный текст. так что, в основном, если пользователь запускает команду, скажем, 2, т.е.: ./caesar 2, все слова, которые он введет позже, будут «выполняться» с двух сторон.

моя программа работает так, как предполагается, и если пользователь набирает букву вместо цифры, которую программа не будет запрашивать для сообщения пользователя. тем не менее, если пользователь запускает командную строку, например, так: ./caesar 8x, программа будет запускаться даже после того, как пользователь наберет букву, поэтому любые идеи о том, как перебрать аргумент пользовательской команды и если есть буква, должны выполняться ? спасибо!

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


int main(int argc, string argv[])
{

    if (argc == 2 && isdigit(*argv[1]))
    {

        int key = atoi(argv[1]);

        string plaintext = get_string("plaintext: ");
        printf("ciphertext: ");

        for (int i = 0, n = strlen(plaintext); i < n; i++)
        {
            if (isupper(plaintext[i]))
            {
                printf("%c", (((plaintext[i] + key) - 65) % 26) + 65);
            }

            else if (islower(plaintext[i]))
            {
                printf("%c", (((plaintext[i] + key) - 97) % 26) + 97);
            }

            else
            {
                printf("%c", plaintext[i]);
            }
        }

        printf("\n");
        return 0;
    }

    else if (argc == 1)
    {
        printf("NO KEY\n");
        return 1;
    }

    else if (argc >= 3 || argv[1] == (string) argv[1])
    {
        printf ("Usage: ./caesar key\n");
        return 1;
    }
}

РЕДАКТИРОВАТЬ. Решено

вот как в итоге выглядел код, спасибо @bruno за помощь btw

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


int main(int argc, string argv[])
{

    if (argc == 2)
    {
        char *endp;
        long lkey;
        int errno = 0;

        lkey = strtol(argv[1], &endp, 10);
        if ((errno != 0) || (*argv[1] == 0) || (*endp != 0) || (lkey < 0) || (((int) lkey) != lkey) || argc >= 3)

            // this statement check to see the characters on argv[1] are all digits
        {
            printf("Usage: ./caesar key\n");
        }
        else // if the argv[1] is all digits then prompts the user for a plaintext
        {
            int key = atoi(argv[1]); // converts the key into an integer

            string plaintext = get_string("plaintext: ");
            printf("ciphertext: ");

            for (int i = 0, n = strlen(plaintext); i < n; i++)

                // goes thru each of the chars in plaintext and determines if is uppercase, lowercase or none.
            {
                if (isupper(plaintext[i]))
                {
                    printf("%c", (((plaintext[i] + key) - 65) % 26) + 65);

                    // it takes 65 and then sums it back to convert the character from the ASCII uppercase index and back
                }

                else if (islower(plaintext[i]))
                {
                    printf("%c", (((plaintext[i] + key) - 97) % 26) + 97);

                    // if the case is lower it takes 97 and then adds 97 back just to maintain the ASCII index.
                }

                else // if it not a lower case nor an uppercase, which means is a symbol then leave it like that.
                {
                    printf("%c", plaintext[i]);
                }
            }
            printf("\n");
            return 0;
        }
    }

    else if (argc == 1) // if the user doesnt prompt a key print no key to user
    {
        printf("NO KEY\n");
        return 1;
    }

    else if (argc >= 3) // if user prompts 3 or more keys into argv then prints error message regargind the usage
    {
        printf("Usage: ./caesar key\n");
        return 1;
    }

}

Ответы [ 2 ]

1 голос
/ 21 апреля 2020

если пользователь запускает командную строку, например, вот так ./caesar 8x программа будет запускаться, даже если пользователь набрал букву

, вы получите число из аргумента программы, используя atoi, он останавливается при достижении не-ди git, поэтому результат одинаков для 8 и 8x.

Если аргумент несовместим с числом с начала, atoi вернет 0, поэтому atoi опасно. В любом случае, в этом случае вы не можете быть в этом случае благодаря вашему тесту isdigit(*argv[1]) ранее.

любые идеи о том, как перебрать аргумент пользовательской команды, и если есть буква, программа должна запускаться

Возможно, вы хотели сказать программа должна не запустить .

Чтобы проверить, совместим ли весь аргумент с числом, которое вы можете использовать strtol для преобразования:

if (argc == 2) {
  char * endp;
  long lkey;

  errno = 0;

  lkey = strtol(argv[1], &endp, 10);
  if ((errno != 0) || (*argv[1] == 0) || (*endp != 0) ||
      (lkey < 0) || (((int) lkey) != lkey)) {
    printf("invalid argument %s\n", argv[1]);
  }
  else {
    int key = (int) lkey;

    ...

Поскольку вы в настоящее время используете int для key, я проверяю, совместимо ли значение с int, я также проверяю, что оно положительное, потому что это совместимо с вашим использованием, и в вашей версии вы подтверждаете, что первый символ - это ди git

0 голосов
/ 21 апреля 2020

Добрый вечер, я не знаю, правильно ли я понял ваш вопрос, но я попробую. Проблема в том, что вы проверяете, равен ли счетчик args 2, а 2-й аргумент - это di git. если так, сделайте следующий код, который вы написали. а если нет? Вы не обрабатываете случай argc == 2 и argv [1] не является di git.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...