分段故障问题

时间:2014-10-31 13:56:00

标签: c segmentation-fault malloc strtok

我有一个程序应该使用移位密码解密加密的文本文件。在我循环浏览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)++;
}

0 个答案:

没有答案