2016-12-06 68 views
2

我一直在为一项任务编写一段代码,它已经准备就绪。今天我再次尝试了一次,但是这次我尝试执行该程序后出现了分段错误(核心转储)消息。分割错误 - 代码最近工作

我似乎无法找到该错误。它编译没有问题,但一旦执行就停止。我非常感谢任何帮助!代码如下所示:

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

#define MAX 256 

int find_key(char aString[]); 
void decrypt(char cipher[], char plain[], int key); 

int main(int argc, char *argv[]) { 
    FILE *pointer_in = fopen(argv[1], "r"); 
    FILE *pointer_out = fopen(argv[2], "w"); 
    char *input_buffer; 
    char output_string[MAX]; 
    long len; 
    int key = 0; 

    if (pointer_in == NULL) { 
     return 1; 
    } 

    /* Reading entire file into a buffer. 
    Finding byte length */ 
    fseek(pointer_in, 0L, SEEK_END); 
    len = ftell(pointer_in); 

    /* load the file index to 
    the start of the pointer_in */ 
    fseek(pointer_in, 0L, SEEK_SET);  

    /* allocate memory to enable 
    buffer to contain the file */ 
    input_buffer = (char*)calloc(len, sizeof(char));  

    /* if a memorey failure */ 
    if (input_buffer == NULL) { 
     return 1; 
    } 
    /* read the file into the buffer */ 
    fread(input_buffer, sizeof(char), len, pointer_in); 
    fclose(pointer_in); 

    /* key is calculated and passed */  
    key = find_key(input_buffer); 

    /* decrypts the input_buffer, using the key and 
    passes decrypted text to output_string */ 
    decrypt(input_buffer, output_string, key); 

    /* free up memory */ 
    free(input_buffer); 

    /* prints the output_string to the pointer_out */ 
    fprintf(pointer_out, "%s", output_string); 
    fclose(pointer_out); 
} 

/* A function to find find the caesar key used 
initially to encrypt a file. Done by frequency 
analysis of letters and comparing to a a corpus 
of most used english letters */ 

int find_key(char aString[]) { 
    char key_holder; 
    char alphaLetter[MAX]; 
    int alphaFreq[MAX]; 
    int key; 

    for (int i = 0; i <= 25; i++) { 
     alphaLetter[i] = 'a' + i; /* Array elements A-Z */ 
     alphaFreq[i] = 0;   /* Frequency of occurrence */ 
    } 

    for (int i = 0; i < strlen(aString); i++) { 
     if (isupper(aString[i])) /* If indexed character is upper, */ 
     {       /* convert to lower by upping ASCII */ 
      aString[i] += 32;  /* value by the difference between */ 
     }       /* lowercase and equivalent uppercase */ 
     switch(aString[i])   /* letters (32) */ 
     { 
      case 'a': 
      alphaFreq[0] += 1; 
      break; 
      case 'b': 
      alphaFreq[1] += 1; 
      break; 
      case 'c': 
      alphaFreq[2] += 1; 
      break; 
      case 'd': 
      alphaFreq[3] += 1; 
      break; 
      case 'e': 
      alphaFreq[4] += 1; 
      break; 
      case 'f': 
      alphaFreq[5] += 1; 
      break; 
      case 'g': 
      alphaFreq[6] += 1; 
      break; 
      case 'h': 
      alphaFreq[7] += 1; 
      break; 
      case 'i': 
      alphaFreq[8] += 1; 
      break; 
      case 'j': 
      alphaFreq[9] += 1; 
      break; 
      case 'k': 
      alphaFreq[10] += 1; 
      break; 
      case 'l': 
      alphaFreq[11] += 1; 
      break; 
      case 'm': 
      alphaFreq[12] += 1; 
      break; 
      case 'n': 
      alphaFreq[13] += 1; 
      break; 
      case 'o': 
      alphaFreq[14] += 1; 
      break; 
      case 'p': 
      alphaFreq[15] += 1; 
      break; 
      case 'q': 
      alphaFreq[16] += 1; 
      break; 
      case 'r': 
      alphaFreq[17] += 1; 
      break; 
      case 's': 
      alphaFreq[18] += 1; 
      break; 
      case 't': 
      alphaFreq[19] += 1; 
      break; 
      case 'u': 
      alphaFreq[20] += 1; 
      break; 
      case 'v': 
      alphaFreq[21] += 1; 
      break; 
      case 'w': 
      alphaFreq[22] += 1; 
      break; 
      case 'x': 
      alphaFreq[23] += 1; 
      break; 
      case 'y': 
      alphaFreq[24] += 1; 
      break; 
      case 'z': 
      alphaFreq[25] += 1; 
      break; 
      default: break; 
     } 
    } 

    /* bubble sort, so in the end alphaLetter[0] 
    will contain most frequent character */ 
    for (int i = 1; i < 26; i++) { 
     if (alphaFreq[0] < alphaFreq[i]) { 
      alphaFreq[0] = alphaFreq[i]; 
      alphaLetter[0] = alphaLetter[i]; 
     } 
    } 
    key_holder = alphaLetter[0]; 
    key = (key_holder - 97) - 4; 
    return key; 
} 

/* A function to decrypt using the key found by 
our find_key() function */ 
void decrypt(char cipher[], char plain[], int key) { 
    int string_length = strlen(cipher); 
    int ascii_a = 0; 

    for (int i = 0; i < string_length; i++) { 
     if (isalpha(cipher[i])) { 
      if (islower(cipher[i])) { 
       ascii_a = 122; 
      } else { 
       ascii_a = 90; 
      } 

      plain[i] = ((cipher[i] - ascii_a - key) % 26) + ascii_a; 
     } else { 
      plain[i] = cipher[i]; 
     } 
    } 
    plain[string_length] = '\0'; 
} 
+3

欢迎堆栈溢出!请参阅[如何创建最小,完整和可验证示例](/ help/mcve)。 –

+1

第一个潜在的问题:你确定'pointer_out'事实上是否成功打开? – yano

+1

'key = find_key(input_buffer);':'input_buffer'不是null-teminate。 tyr'input_buffer =(char *)calloc(len + 1,sizeof(char)); ' – BLUEPIXY

回答

5

你分配给读取输入文件的缓冲区是一个字节太短:你必须分配一个额外的字节和存储空终止,使之成为C字符串。

您还假定输出消息适合尺寸为MAX的缓冲区,如果源文件大于MAX-1字节,则该缓冲区不正确。要么将输入限制为MAX-1字节,要么将输出缓冲区分配到适当的大小。

这里是main功能的修正版本:

#include <ctype.h> 
#include <errno.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

int main(int argc, char *argv[]) { 
    FILE *pointer_in, *pointer_out; 
    char *input_buffer, *output_string; 
    long len; 
    int key; 

    if (argc < 3) { 
     fprintf(stderr, "usage: %s input_file output_file\n", argv[0]); 
     return 1; 
    } 
    pointer_in = fopen(argv[1], "r"); 
    if (pointer_in == NULL) { 
     fprintf(stderr, "cannot open input file %s: %s\n" 
       argv[1], strerror(errno)); 
     return 1; 
    } 

    /* Get the file size */ 
    fseek(pointer_in, 0L, SEEK_END); 
    len = ftell(pointer_in); 
    fseek(pointer_in, 0L, SEEK_SET);  

    /* allocate memory to read the whole file */ 
    input_buffer = calloc(len + 1, sizeof(char)); 
    output_string = calloc(len + 1, sizeof(char)); 

    if (input_buffer == NULL || output_string == NULL) { 
     fprintf(stderr, "cannot allocate memory for %ld bytes\n", len + 1); 
     return 1; 
    } 

    /* read the file into the buffer */ 
    if (fread(input_buffer, sizeof(char), len, pointer_in) != len) { 
     fprintf(stderr, "cannot read input file %s\n", argv[1]); 
     return 1; 
    } 
    input_buffer[len] = '\0'; 
    fclose(pointer_in); 

    /* key is calculated and passed */  
    key = find_key(input_buffer); 

    /* decrypts the input_buffer, using the key and 
    passes decrypted text to output_string */ 
    decrypt(input_buffer, output_string, key); 

    /* prints the output_string to the pointer_out */ 
    pointer_out = fopen(argv[2], "w"); 
    if (pointer_out == NULL) { 
     fprintf(stderr, "cannot open output file %s: %s\n" 
       argv[2], strerror(errno)); 
     return 1; 
    } 
    fputs(output_string, pointer_out); 
    fclose(pointer_out); 
    free(input_buffer); 
    free(output_string); 

    return 0; 
} 

find_key()功能非常低效:

  • 您重新计算字符串的每个字符的长度。
  • 您应该计算的,而不是使用一个巨大的switch

数组索引下面是一个简化版本:

int find_key(char aString[]) { 
    /* This code assumes ASCII: the letters are assumed to be contiguous */ 
    int alphaFreq[26] = { 0 }; 
    int c, key; 

    for (int i = 0; (c = (unsigned char)aString[i]) != '\0'; i++) { 
     if (c >= 'a' && c <= 'z') { 
      alphaFreq[c - 'a']++; 
     } else 
     if (c >= 'A' && c <= 'Z') { 
      alphaFreq[c - 'A']++; 
     } 
    } 

    /* find the most frequent character */ 
    c = 0; 
    for (int i = 1; i < 26; i++) { 
     if (alphaFreq[c] < alphaFreq[i]) { 
      c = i; 
     } 
    } 
    key = c - 4; 
    return key; 
} 
+1

对于很多需要修正的转换问题,在我们说'这是一个更正后的版本'之前:' – Michi

+0

OP甚至不关心'int argc,'。 – Michi

+0

@Michi:我用更好的分析更新了答案。 – chqrlie