我一直在为作业编写一段代码,而且它已经准备好了。今天我再一次尝试了,但这次我尝试执行程序后得到了一个分段错误(核心转储)消息。
我似乎无法找到错误。它编译没有问题,但在执行时它停止。我真的很感激任何帮助!代码如下所示:
#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';
}
答案 0 :(得分: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;
}