Я понятия не имею, почему я получаю ошибки ошибки сегментации
#include <stdio.h>
#include <cs50.h> //stdlib.h is included in cs50.h so I don't need it
#include <string.h>
#include <ctype.h>
#include <math.h>
int main(int argc, string argv[]) // command line input
{
if(argc != 2) // check if there is only one input
{
printf("error\n");
return 1;
}
int commandlength = strlen(argv[1]); // find string length of command string
string key[commandlength + 1]; // taking the key from the input and putting it in something that will take less typing later
for(int i = 0; i < commandlength; i++) // check if every char in the string is a letter
{
if(isalpha(argv[1][i]))
continue;
else
{
printf("error\n");
return 1;
}
}
strcpy(key[commandlength], argv[1]); // copy key from command line into a string called key
string input = GetString();
int inputlength = strlen(input); // length of string typed in when prompted
int k = 0; // this will be used to iterate the key separately from i, since the key only iterates when applied to an alpha
for(int i = 0; i < inputlength; i++)
{
if(ispunct(input[i]))
printf("%c", input[i]);
if(isspace(input[i]))
printf("%c", input[i]);
if(isupper(input[i]))
{
printf("%c", (input[i] + atoi(key[k]) % commandlength - 65) % 26 + 65);
k++;
}
if(islower(input[i]))
{
printf("%c", (input[i] + atoi(key[k]) % commandlength - 97) % 26 + 97);
k++;
}
}
printf("\n");
return 0;
}
Перед чтением, пожалуйста, имейте в виду, что я студент. Гораздо выгоднее получить подробное объяснение, чем просто строку кода с надписью "вот, пожалуйста, я исправил это". Я буду ссылаться на этот пост в своем представлении, и у нас есть очень строгие правила относительно академической честности и того, что копирование против помощи, и я был бы очень признателен, если бы об этом помнили.
Целью этого проекта является создание надежного шифра. Ниже приведены инструкции моего учителя:
Ваша последняя задача на этой неделе - написать в vigenere.c программу, которая шифрует сообщения с использованием шифра Vigenère. Эта программа должна принимать один аргумент командной строки: ключевое слово k, состоящее полностью из буквенных символов. Если ваша программа выполняется без каких-либо аргументов командной строки, с более чем одним аргументом командной строки или с одним аргументом командной строки, который содержит любой не алфавитный символ, ваша программа должна немедленно выдать жалобу и завершиться, причем main возвращает 1 (тем самым означает ошибку, которую могут обнаружить наши собственные тесты). В противном случае ваша программа должна продолжить запрашивать у пользователя строку открытого текста p, которую она затем должна зашифровать в соответствии с шифром Вигенера с помощью k, в конечном итоге вывести результат и выйти, а main вернет 0.
Что касается символов в k, вы должны рассматривать A и a как 0, B и b как 1, …, а Z и z как 25. Кроме того, ваша программа должна применять шифр Вигенера только к символу в p, если этот символ письмо. Все остальные символы (цифры, символы, пробелы, знаки пунктуации и т. Д.) Должны выводиться без изменений. Более того, если ваш код собирается применить j-й символ k к i-му символу p, но последний окажется не алфавитным символом, вы должны подождать, чтобы применить этот j-й символ k к следующему алфавитному символу в p; Вы еще не должны перейти к следующему символу в k. Наконец, ваша программа должна сохранять регистр каждой буквы в p.
Я почти уверен, что выполнил требования для итерации кода, удостоверился, что ключ зацикливается, если он короче шифруемой фразы, и убедился, что я не применяю ключ к не-буквенным символам. Тем не менее, я получаю значение по умолчанию для сегментирования, прежде чем мне будет предложено ввести строку для шифрования, поэтому я почти уверен, что проблема заключается в верхней части кода. Я немного просмотрел код и до сих пор не могу понять, почему он продолжает сегрегироваться.
4 ответа
Изменить это утверждение
strcpy(key[commandlength], argv[1]);
в
strcpy( key, argv[1] );
key[commandlength] является объектом типа char, значение которого используется в качестве адреса строки, если вы используете эту недопустимую конструкцию
strcpy(key[commandlength], argv[1]);
Также не очень хорошая идея использовать continue
в вашей петле. Вместо
for(int i = 0; i < commandlength; i++) // check if every char in the string is a letter
{
if(isalpha(argv[1][i]))
continue;
else
{
printf("error\n");
return 1;
}
}
Я бы просто написал
for(int i = 0; i < commandlength; i++) // check if every char in the string is a letter
{
if( !isalpha(argv[1][i] ) )
{
printf("error\n");
return 1;
}
}
И как отметил BLUEPIXY вместо
string key[commandlength + 1];
там должно быть
char key[commandlength + 1];
при условии, что у вас нет некоторого typedef, похожего на
typedef char string;
Однако, если у вас действительно есть такой typedef, то следующее утверждение
string input = GetString();
будет недействительным, потому что вы пытаетесь вызвать функцию strlen для ввода:
int inputlength = strlen(input);
И не используйте магические числа в вашем коде, как, например, в этом утверждении
printf("%c", (input[i] + atoi(key[k]) % commandlength - 65) % 26 + 65);
Я полагаю, что 65 - это "А". Так что было бы лучше использовать явно символьный литерал "А" вместо 65.
Я не уверен, что string
тип должен быть (в соответствии с main(int argc string argv[]
) линия выглядит как char*
, Если это так, то вы получите массив указателей на символы со строкой string key[commandlength + 1];
С линией strcpy(key[commandlength], argv[1]);
Вы копируете строку из argv[i]
до последнего указателя в массиве, который вы создали. Но так как этому указателю (пока) не назначена какая-либо память. Кроме того, он имеет случайный контент и указывает на случайную ячейку памяти. Таким образом, вы получаете Segfault.
Вероятно, вы хотите один указатель, который имеет stringlength
из argv[1]
строка как память связана.
Ответ пользователя johanneshau несколько прав. Чтобы добавить к его / ее ответу, вы должны объявить ключ переменной, как показано ниже
string key;
вместо
string key[commandlength + 1];
Затем вы должны назначить память для указанной выше переменной-указателя, потому что string является typedef для char * и, следовательно, она не может хранить какую-либо строку, пока ей не будет выделено некоторое количество памяти.
key = (string)malloc(sizeof(char) * (commandlength + 1));
Приведенная выше строка выделит память для хранения входной строки.
Затем вы должны скопировать входную строку в нее, используя следующий код
strcpy(key,argv[1]);
Итак, теперь у вас есть фактическая строка, скопированная в переменную key.
Прежде чем вернуться из функции (семантически запрограммированной), вы должны освободить память, используя функцию free, поскольку мы динамически распределяли ее, используя функцию malloc в куче.
free(key);
Если у вас нет идеи, скомпилируйте ваш исходный код следующим образом: "gcc -Wall -g source.c"; запустите вашу программу, после сбоя программы запустите "dgb ./prog core"
в GDB типа "Bt", и вы увидите номер строки, где происходит ошибка сегмента
если дамп ядра не может быть создан в рабочем каталоге, выполните следующее: "ulimit -c unlimited" (в среде bash)