细分故障 - 代码最近有效



我一直在编写一件分配的代码,并且已经准备好了。今天,我再次尝试了一下,但是这次我在尝试执行程序后得到了一个细分错误(核心倾倒)消息。

我似乎找不到错误。它毫无问题地编译,但在执行后停止。我真的很感谢任何帮助!该代码如下所示:

#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] = '';
}

您分配要读取输入文件的缓冲区是一个字节太短:您必须分配一个额外的字节并存储一个null终端以使其成为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_filen", argv[0]);
        return 1;
    }
    pointer_in = fopen(argv[1], "r");
    if (pointer_in == NULL) {
        fprintf(stderr, "cannot open input file %s: %sn"
                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 bytesn", 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 %sn", argv[1]);
        return 1;
    }
    input_buffer[len] = '';
    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: %sn"
                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]) != ''; 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;
}

最新更新