2017-01-29 24 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

なぜあなたはbuf' 'から '1'減算されていますか?これはバッファの外側にアクセスします。これは未定義の動作です。 – Barmar

+0

私はそれがちょうどタイプミスで、あなたが 'for(i = 0; i <(strlen(buf)-1); ++ 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 
    } 
} 

cintとして宣言されています可能な値は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 
関連する問題