Конкатенация строк с переменными и указателями в 'C' - PullRequest
0 голосов
/ 17 февраля 2019

Я работаю над шифром Цезаря для онлайн-курса, и у меня есть проблема с исходным значением в конечном выводе, и я не могу избавиться от него.Я подозреваю, что это происходит из-за неправильного вызова

strcpy(str1, &final_val);
strcat(str2, str1);

, поэтому, когда я запускаю

make test && ./test 1

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

plaintext: asd
ciphertext: bcd 

Вместо этого я получу

plaintext: asd
ciphertext: bacbdc

Если вы хотите опробовать код, вам нужно будет сделать это внутри этого sanbox потому что у него есть необходимая библиотека CS50.

Код

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

bool input_valid(int count, string arg);
bool in_alphabet(int count, string arg);

int main(int argc, string argv[]) {
    int key;
    int ascii_val;
    char final_val;
    string string;

    char str1[80];
    char str2[80];

    // check input again if validation fails
    if (!input_valid(argc, argv[1])) {
        printf("Invalid input!\nUSAGE: ./caesar key\n");
        return 1;
    }

    string = get_string("plaintext: ");

    // get integer from string input
    key = strtol(argv[1], NULL, 10);

    for (int i = 0; i < strlen(string); i++) {
        ascii_val = (int)string[i];

        bool valid_lower_case = (ascii_val + key) >= 97 && (ascii_val + key) <= 122;
        bool valid_upper_case = (ascii_val + key) >= 65 && (ascii_val + key) <= 90;

        // check if value is a letter
        if (isalpha(string[i])) {
            // check if value is in the valid alphabet range
            if (valid_lower_case || valid_upper_case) {
                final_val = ascii_val + key;
            } else {
                // for lowercase: wrap around if the letter passes 'z'
                final_val = 97 + (key - (122 - (ascii_val - 1)));
            }
        } else {
            final_val = ascii_val;
        }

        strcpy(str1, &final_val);
        strcat(str2, str1);
    }
    for (int i = 0; i < 5; i++) {
        printf("%i\n", str2[i]);
    }

    printf("ciphertext: %s\n", str2);
}

bool input_valid(int count, string arg) {
    // input has more args than just the file name
    // input is an integer
    return count > 1 && isdigit(arg[0]);
}

Ответы [ 2 ]

0 голосов
/ 17 февраля 2019

Заменено strcopy() и strcat().Получил это, добавив к str2 как это:

str2[i] = final_val;
0 голосов
/ 17 февраля 2019

strcpy(str1, &final_val); - неопределенное поведение.strcpy ожидает, что оба параметра будут указателями на строки с нулевым символом в конце.Однако, поскольку массивы распадаются на указатели при передаче в функции, strcpy не знает разницы между указателем на массив символов и адресом одной переменной char.

Он будет пытаться скопировать память, начинающуюся с &final_val, в str1, останавливаясь, только когда он встречает нулевой терминатор в другом месте в памяти вашего процесса, если таковой имеется.Чтобы скопировать один символ в строку, просто используйте str[x] = ch и str[x + 1] = '\0'.

...