2017-01-29 6 views
1

Когда я запускаю свой код и выбираю вариант 2 или 3, после ввода моей строки, я получаю ошибку ошибки сегментации, и я не вижу, что вызывает ошибку. Я предполагаю, что что-то связано с моими функциями шифрования и дешифрования, но я не уверен, что.Что вызывает ошибку ошибки сегментации?

#include <stdio.h> 
#include <string.h> 
#define SIZE 500 
int getUserChoice() 
{ 
    int decision = 0; 

    printf("-------------------------------\n"); 
    printf("| 1) Change Shift (default 3) |\n"); 
    printf("| 2) Encrypt a message  |\n"); 
    printf("| 3) Decrypt a message  |\n"); 
    printf("| 4) Quit      |\n"); 
    printf("-------------------------------\n"); 
    printf("Option: "); 
    scanf("%d", &decision); 
    if(decision <= 0 || decision >= 4) 
    { 
     return 0; 
    } 

    return decision; 
} 
int getShift() 
{ 
    int key = 3; 
    printf("Enter new shift value: "); 
    scanf("%d", &key); 
    return key; 
} 
void getString(char buf[]) 
{ 
    char c = 0; 
    int i = 0; 
    while((c = getchar()) != '\n' && c != EOF){ 
    } 
    printf("Input: "); 
    fgets(buf, SIZE, stdin); 
    printf("Output: %s\n", buf[i]); 

} 
void encrypt(char buf[], int shift) 
{ 
    int i; 

    for(i = 0; i < (strlen(buf-1));++i) 
    { 

     buf[i] = buf[i] + shift; 

    } 

} 
void decrypt(char buf[], int shift) 
{ 
    int i; 

    for(i = 0; i < (strlen(buf-1)); ++i) 
    { 

     buf[i] = buf[i] - shift; 

    } 

} 
int main() 
{ 
    char userStr[SIZE]; 
    int shift = 3; 
    int number; 
    while(1) 
    { 
     number = getUserChoice(); 
     if(number == 1) 
     { 
      shift = getShift(); 
     } 
     if (number == 2) 
     { 
      getString(userStr); 
      encrypt(userStr, shift); 
     } 
     if (number == 3) 
     { 
      getString(userStr); 
      decrypt(userStr, shift); 
     } 
     if (number == 0) 
     { 
      break; 
     } 
    } 
    return 0; 

} 
+2

Почему вы вычитанием '1' из' buf'? Это обращается за пределами буфера, что является неопределенным поведением. – Barmar

+0

Надеюсь, что это была просто опечатка, и вы намеревались делать 'for (i = 0; i <(strlen (buf) -1); ++ i)', но это должно быть просто 'for (i = 0; i < strlen (buf); ++ i) ' – Anty

+0

Когда я шифрую и расшифровываю свою строку, я не хочу также шифровать и расшифровывать символы новой строки или нулевые. – Boo92

ответ

1

Ваша программа рушится из-за этой линии в функции getString():

printf("Output: %s\n", buf[i]); 

Значение, сохраненное в buf[i] является char, но вы пытаетесь напечатать его с помощью спецификации %s преобразования, ведущие к неопределенному поведению. Существуют также проблемы в функциях encrypt() и decrypt(), где вы пытаетесь найти strlen(buf - 1). Помните, buf преобразуется в указатель на char в выражении, поэтому это арифметика указателя. И если результат арифметической операции указателя указывает на любое местоположение, которое не находится в самом массиве, или один за концом массива, поведение не определено. Итак, у вас есть UB. Я подозреваю, что вы имели в виду strlen(buf) - 1, что в любом случае не обязательно.

Вы должны переписать функцию getString(), чтобы удалить конечную новую строку с входа, чтобы вам больше не нужно было беспокоиться об этом. Кроме того, если пользователь вводит слишком много символов, будут лишние символы, оставленные во входном потоке, и это было бы хорошей идеей, чтобы отказаться от них, а также:

void getString(char buf[]) 
{ 
    int c; 
    int i = 0; 

    while ((c = getchar()) != '\n' && c != EOF) 
     continue;     // discard leading characters 


    fgets(buf, SIZE, stdin); 
    while (buf[i] != '\n' && buf[i] != '\0') 
    { 
     ++i; 
    } 

    if (buf[i] == '\n')    // replace newline with '\0' 
    { 
     buf[i] = '\0'; 
    } else { 
     while ((c = getchar()) != '\n' && c != EOF) 
      continue;    // discard extra characters 
    } 
} 

Здесь c объявлен как int , чтобы сохранить возможное значение EOF. Перед вызовом fgets() есть цикл, чтобы удалить все оставшиеся во входном потоке из предыдущих вызовов до scanf(). После ввода ввода существует цикл, который ищет вход для символа \n. Если найден, новая строка заменяется терминатором NUL. В противном случае во входном потоке есть дополнительные символы, и они отбрасываются.

Код, который печатает Input:, и Output: был перемещен в main(), где он должен быть, чтобы преобразованный вход можно было отобразить.

encrypt() и decrypt() функции могут быть легко улучшены таким образом, что \0 не трансформированной:

void encrypt(char buf[], int shift) 
{ 
    int i = 0; 

    while (buf[i] != '\0') 
    { 
     buf[i] = buf[i] + shift; 
     ++i; 
    } 
} 

Вместо того чтобы использовать счетчик, чтобы контролировать цикл, цикл продолжается до тех пор, NUL символ не встречается ,

Вот измененный код в полном объеме:

#include <stdio.h> 
#include <string.h> 
#define SIZE 500 

int getUserChoice(void) 
{ 
    int decision = 0; 

    printf("-------------------------------\n"); 
    printf("| 1) Change Shift (default 3) |\n"); 
    printf("| 2) Encrypt a message  |\n"); 
    printf("| 3) Decrypt a message  |\n"); 
    printf("| 4) Quit      |\n"); 
    printf("-------------------------------\n"); 
    printf("Option: "); 
    scanf("%d", &decision); 
    if(decision <= 0 || decision >= 4) 
    { 
     return 0; 
    } 

    return decision; 
} 

int getShift(void) 
{ 
    int key = 3; 
    printf("Enter new shift value: "); 
    scanf("%d", &key); 
    return key; 
} 

void getString(char buf[]) 
{ 
    int c; 
    int i = 0; 

    while ((c = getchar()) != '\n' && c != EOF) 
     continue;     // discard leading characters 


    fgets(buf, SIZE, stdin); 
    while (buf[i] != '\n' && buf[i] != '\0') 
    { 
     ++i; 
    } 

    if (buf[i] == '\n')    // replace newline with '\0' 
    { 
     buf[i] = '\0'; 
    } else { 
     while ((c = getchar()) != '\n' && c != EOF) 
      continue;    // discard extra characters 
    } 
} 

void encrypt(char buf[], int shift) 
{ 
    int i = 0; 

    while (buf[i] != '\0') 
    { 
     buf[i] = buf[i] + shift; 
     ++i; 
    } 
} 

void decrypt(char buf[], int shift) 
{ 
    int i = 0; 

    while (buf[i] != '\0') 
    { 
     buf[i] = buf[i] - shift; 
     ++i; 
    } 
} 

int main(void) 
{ 
    char userStr[SIZE]; 
    int shift = 3; 
    int number; 
    while(1) 
    { 
     number = getUserChoice(); 
     if(number == 1) 
     { 
      shift = getShift(); 
     } 
     if (number == 2) 
     { 
      printf("Input: "); 
      getString(userStr); 
      encrypt(userStr, shift); 
      printf("Output: %s\n", userStr); 
     } 
     if (number == 3) 
     { 
      printf("Input: "); 
      getString(userStr); 
      decrypt(userStr, shift); 
      printf("Output: %s\n", userStr); 
     } 
     if (number == 0) 
     { 
      break; 
     } 
    } 
    return 0; 

} 

А вот пример взаимодействия:

------------------------------- 
| 1) Change Shift (default 3) | 
| 2) Encrypt a message  | 
| 3) Decrypt a message  | 
| 4) Quit      | 
------------------------------- 
Option: 2 
Input: hello world 
Output: khoor#zruog 
------------------------------- 
| 1) Change Shift (default 3) | 
| 2) Encrypt a message  | 
| 3) Decrypt a message  | 
| 4) Quit      | 
------------------------------- 
Option: 3 
Input: khoor#zruog 
Output: hello world 
------------------------------- 
| 1) Change Shift (default 3) | 
| 2) Encrypt a message  | 
| 3) Decrypt a message  | 
| 4) Quit      | 
------------------------------- 
Option: 4