2014-09-26 2 views
-3
#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. Ниже приведены инструкции, которые преподал мой преподаватель:

Ваша последняя задача на этой неделе - написать в vigenere.c программу, которая шифрует сообщения с помощью шифрования Vigenère. Эта программа должна принимать один аргумент командной строки: ключевое слово k, составленное полностью из алфавитных символов. Если ваша программа выполняется без аргументов командной строки, с несколькими аргументами из командной строки или с одним аргументом командной строки, который содержит любой алфавитный символ, ваша программа должна жаловаться и немедленно уходить с возвратом 1 (тем самым означающее ошибку, которую могут обнаружить наши собственные тесты). В противном случае ваша программа должна перейти к приглашению пользователя для строки открытого текста p, которую она затем должна зашифровать в соответствии с шифрованием Vigenère с k, в конечном итоге распечатать результат и выйти с основным возвратом 0.

Что касается символов в k вы должны обрабатывать A и a как 0, B и b как 1, ... и Z и z как 25. Кроме того, ваша программа должна применять только шифр Vigenère к символу в p, если этот символ является буквой. Все остальные символы (цифры, символы, пробелы, знаки препинания и т. Д.) Должны выводиться без изменений. Более того, если ваш код собирается применить j-й символ k к i-му символу p, но последний окажется не алфавитным символом, вы должны подождать, чтобы применить этот j-й символ k к следующему алфавитному символу в p ; вы еще не должны перейти к следующему символу в k. Наконец, ваша программа должна сохранять случай каждой буквы в p.

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

+5

Вы пробовали отлаживать? – user1336087

+0

Я не знаю, как это сделать; однако я знаю, что он успешно блокирует пароли с неалфавитными символами и блокирует входы, которые либо не имеют ключа (т. е. argc == 1 в этом сценарии), либо имеют более одного (argc> 2). Я также знаю это segfaults, прежде чем запрашивать строку для шифрования, поэтому это заставляет меня думать, что проблема лежит между ними. – iced

+2

Скомпилируйте все предупреждения и отладочную информацию 'gcc -Wall -g', затем ** используйте отладчик ** (' gdb'). –

ответ

1

Изменить это утверждение

strcpy(key[commandlength], argv[1]); 

в

strcpy(key, argv[1]); 

ключ [commandlength] является объектом значения полукокса тип, который используется в качестве адреса строки, если вы используете эту недопустимую конструкцию

strcpy(key[commandlength], argv[1]); 

Также не рекомендуется использовать continue r петля.Вместо

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]; 

Provi Ded, что у вас нет какой-то ЬурейеЕ похож на

typedef char string; 

Однако, если вы на самом деле есть такой ЬурейеЕ то следующее заявление

string input = GetString(); 

будет недействителен, потому что вы пытаетесь вызвать функцию STRLEN для ввода:

int inputlength = strlen(input); 

не использовать магические числа в коде, как, например, в этом заявлении

printf("%c", (input[i] + atoi(key[k]) % commandlength - 65) % 26 + 65); 

Я полагаю, что 65 - это «А». Поэтому было бы лучше использовать явно литеру «А» вместо 65

+0

В дополнение к этому - исходный код должен генерировать сообщение компилятора - не игнорировать предупреждения/ошибки компилятора –

+0

Я сделал эти изменения, а затем удалил atoi, так как я больше не нуждался в нем. Я проверю его и отправлю обратно с результатами. – iced

+0

Протестировано - дефолты сегментации исчезли! Тем не менее, ничто не зашифровывается правильно, поэтому я должен работать над ними. – iced

1

Я не уверен, что string тип должен быть (в зависимости от main(int argc string argv[]) линии это выглядит как char*. Если это так, то вы получите массив символьных указателей с линией string key[commandlength + 1];

С линией strcpy(key[commandlength], argv[1]);

скопировать строку из argv[i] до последнего указателя в массиве вы создали. Но поскольку этот указатель не имеет (все же) памяти, назначенную. Кроме того, он имеет случайный контент и указывает на случайную ячейку памяти. Поэтому вы получаете segfault.

Возможно, вы хотите, чтобы один указатель имел stringlength строки argv[1] как связанную память.

0

Ответ, заданный пользователем johanneshau, несколько прав. Чтобы добавить к его/ее ответу, вам следует объявить переменный ключ, как показано ниже

string key; 

вместо

string key[commandlength + 1]; 

Затем следует присвоить память вышеприведенном переменнуюуказателя, потому что строка является ЬурейеЙ для полукокса * и, следовательно, он не может хранить какую-либо строку, пока не будет выделена какая-либо память.

key = (string)malloc(sizeof(char) * (commandlength + 1)); 

В приведенной выше строке выделяется память для ввода входной строки.

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

strcpy(key,argv[1]); 

Так что теперь у вас есть фактическая строка скопированной в ключевой переменный.

Перед тем как вернуться из функции (семантически программа), вы должны освободить память, используя свободную функцию, так как мы выделили ее динамически, используя функцию malloc в куче.

free(key); 
0

Если у вас нет идеи, тогда скомпилируйте источник следующим образом: "gcc -Wall -g source.c"; запустить программу, после того, как аварийное завершение работы программы, запустите «DGB ядро ​​./prog»

в тип GdB «Ы» и вы увидите номер строки, где ошибка сегментный приходит

если дамп не может создать в рабочем , выполните следующие действия: «ulimit -c unlimited» (в среде bash)

Смежные вопросы