我有一个程序应该使用移位密码解密加密的文本文件。在我循环浏览shift
选项的主循环中,我得到strtok
的分段错误。它第一次工作正常,但是当我第二次循环并使用NULL指针调用strtok
时,我得到了错误。我对strtok
不太熟悉,但我使用了一个临时变量,在每个循环后重置我的输入数组来处理字符串重新格式化。
此外,当单词不在词典文件中时,我在check_dict
中遇到另一个分段错误。当它能找到这个词时,它工作正常,所以我假设循环找不到NULL指针,所以它试图引用一个无效的地址。有什么想法吗?
编辑:我已更新了我的代码。 strtok
现在运作正常。我唯一的问题是我的check_dict
功能。这与我对字典数组的初始化有关。我拉的文件在每一行都有一个单词。我以NULL结束数组,但我的check_dict
函数似乎无法在循环中找到它并且我得到了分段错误。
typedef struct {
int shift, num_right;
} Shift_Op; // best shift option
int main(int argc, char *argv[]) {
FILE *fp; // input file pointer
FILE *dict_file; // dictionary file pointer
Shift_Op best_shift; // struct for ship options
char **dict, **word; // dictionary array
char *chars, *inp, *t;
int i, j, c, num, wc=0, cc=0, shift=1;
// check command-line arguments
if (argc==1) {
fprintf(stderr, "Please enter a file for decryption.\n");
return 1;
}
else if (argc==2) {
if (((fp=fopen(argv[1],"r"))==NULL) || ((dict_file=fopen("../../../../usr/share/dict/words","r"))==NULL)) {
fprintf(stderr, "Could not open file.\n");
return 1;
}
}
else if (argc==3) {
if ((fp=fopen(argv[1],"r"))==NULL) {
fprintf(stderr, "Could not open input file.\n");
return 1;
}
if ((dict_file=fopen(argv[2],"r"))==NULL) {
if ((dict_file=fopen("../../../../usr/share/dict/words","r"))==NULL) {
fprintf(stderr, "Could not open given dictoinary file or backup file.\n");
return 1;
}
else
printf("Could not open given dictionary file, using backup instead.\n");
}
}
//get file stats for dictionary
file_stats(dict_file, &cc, &wc);
rewind(dict_file);
// check memory allocation
if ((chars=(char *) malloc(cc+1))==NULL)
return 1;
if ((dict=(char **) malloc((wc+1)*sizeof(char *)))==NULL)
return 1;
if ((word=(char **) malloc((CHECK_WORD_LIMIT+1)*sizeof(char *)))==NULL)
return 1;
file_stats(fp, &cc, &wc);
rewind(fp);
if (((inp=(char *) malloc(cc+1))==NULL) || ((t=(char *) malloc(cc+1))==NULL))
return 1;
// input files into arrays
input_dict(dict_file, chars, dict);
input_file(fp, inp);
t = inp; // temp array for strtok
best_shift.num_right = 0;
// loop through string tokens
word[0] = strtok(t, " .,?!;:-/\"\n");
for (i=1; i<CHECK_WORD_LIMIT; i++) {
word[i] = strtok(NULL, " .,?!;:-/\"\n");
}
// loop through shift options
while (shift<25) {
printf("Checking shift = %d\n", shift);
num = 0;
for (j=0; j<CHECK_WORD_LIMIT; j++) { // loop through words at beginning of file
if (check_dict(shift_string(word[i], shift), dict)) // check if token is in dictionary array
num++;
printf("%s\n", shift_string(word[j], shift));
}
if (num>best_shift.num_right) { // if shift option gives more correct words
best_shift.shift = shift; // change best shift option
best_shift.num_right = num;
}
shift++;
}
shift = best_shift.num_right;
//while ((c=fgetc(fp))!=EOF) { // output shifted file
// putchar(shift_char(c, shift));
//}
free(dict);
free(chars);
free(word);
free(inp);
free(t);
return 0;
}
char shift_char(char c, int k) {
return (tolower(c)-k);
}
char *shift_string(char *s, int k) {
char *t;
int i = 0;
if ((t = (char *) malloc(strlen(s)))==NULL)
return NULL;
while (*s!='\0') {
t[i] = shift_char(*s, k);
s++;
i++;
}
t[i]=='\0';
return t;
}
int check_dict(char *w, char **d) {
int i = 0;
while (strcasecmp(w, d[i]) && (d[i]!=NULL))
i++;
return (!strcasecmp(w, d[i]));
}
void input_dict(FILE *d, char *chars, char **words) {
int c, i = 0, j = 1;
words[0] = &chars[0];
while ((c=fgetc(d))!=EOF) {
if (c=='\n') {
words[j] = &chars[i+1];
j++;
c = '\0';
}
chars[i] = c;
i++;
}
words[j] = NULL;
chars[i] = '\0';
}
void input_file(FILE *f, char *inp) {
int c;
while ((c=fgetc(f))!=EOF) {
*inp = c;
inp++;
}
}
void file_stats(FILE *d, int *cc, int *wc) {
int c;
while ((c=fgetc(d))!=EOF) {
(*cc)++;
if (c=='\n')
(*wc)++;
}
(*wc)++;
}