为什么这对某人起作用,而不是我?

时间:2014-07-30 14:09:10

标签: c sorting pointers

我收到了这段代码:

#include <stdio.h>
#include <string.h>
#include <math.h>
#include <dirent.h>
#include <stdlib.h>
#define W 1031
#define B 256

struct position {
    int x;
    int y;
    struct position *next;
};

struct wordFiles {
    char *fileName;
    struct position *cor;
    struct wordFiles *next;
};

struct wordTree {
    char *word;
    struct wordFiles *files;
    struct wordTree *left;
    struct wordTree *right;
};

struct wordTree *hashTable[W];

typedef struct wordFiles *files_Ptr;

typedef struct position *pos_ptr;

typedef struct wordTree *wordTreePtr;

long int power(int a, long b){
    long int value,i;
    value = 1;
    for (i = 0; i < b; i++)
        value *= a;
    return value;
}

int hashValue (char *word){
    long int i=0,s=0,n;
    n = strlen(word);
    for (i=0; i<n; i++){
        s += power(B,n-i-1) * word[i];
    }
    return (s%W);
}

void readword(char *word , FILE *curr_file, int *x_axis, int *y_axis, int *newline, int *endfile){
    char c;
    c = (char) malloc(sizeof(char));
    if ((fscanf(curr_file, "%s", word))!=1 || fscanf(curr_file, "%c", &c)!=1){
        *endfile=1;
    }
    *x_axis += strlen(word);
    if (strlen(word)==1 && c=='\n'){
        *newline = 1;
        return;
    }
    if (c==' ') {
        *x_axis +=1;
    }
    else if (c=='\n') {
        *newline = 1;
    }
    return;
}

void coordinateslistInsert (pos_ptr *lp,int x, int y){
    pos_ptr prev,curr;
    prev = NULL;
    curr = *lp;
    while (curr != NULL){
        prev = curr;
        curr = curr->next;
    }
    pos_ptr n = (pos_ptr) malloc(sizeof(struct position));
    if (n == NULL) {
        printf("Out of memory\n");
        return;
    }
    n->next = NULL;
    n->x = x;
    n->y = y;
    if (prev==NULL) {
        *lp = n;
    }
    else {
        prev->next = n;
    }
    return;
}

void filelistInsert (files_Ptr *lp, char *filename, int x, int y, int k) {
    files_Ptr prev, curr;
    prev = NULL;
    curr = *lp;
    if ( curr!=NULL && k == 1 && strcmp(curr->fileName, filename) == 0 ){
        coordinateslistInsert(&(*lp)->cor, x, y);
        return;
    }
    while (curr != NULL){
        prev = curr;
        curr = curr->next;
    }
    files_Ptr n = (files_Ptr)malloc(sizeof(struct wordFiles));
    if (n == NULL) {
        printf("Out of memory\n");
        return;
    }
    n->fileName = filename;
    n->next = NULL;
    coordinateslistInsert (&(*n).cor , x ,y);
    if (prev==NULL) {
        *lp = n;
    }
    else {
        prev->next = n;
    }
    return;
}

void treeBalancedInsert (wordTreePtr *curr_tree, char *word, char *filename, int x, int y) {
    int k=0;
    if (*curr_tree == NULL) {
        *curr_tree =(wordTreePtr) malloc(sizeof(struct wordTree));
        if (*curr_tree == NULL) {
            printf("Out of memory\n");
            exit(1);
        }
        (*curr_tree)->word=malloc(30*sizeof(char));
        (*curr_tree)->left = (*curr_tree)->right = NULL;
        strcpy((*curr_tree)->word,word);
        filelistInsert (&(*curr_tree)->files , filename,x,y,k);
    }
    else {
        if (strcmp((*curr_tree)->word,word) == 0){
            k=1;
            filelistInsert (&(*curr_tree)->files , filename,x,y,k);
            return;
        }
        else if (strcmp((*curr_tree)->word,word) < 0)
            treeBalancedInsert(&(((*curr_tree)->left)), word, filename, x, y);
        else
            treeBalancedInsert(&(((*curr_tree)->right)), word, filename,x ,y);
    }

}

void search (char *word, int h_value, struct wordTree *hashtable[]){
    wordTreePtr n = hashTable[h_value];
    while(n!=NULL && strcmp ( n->word , word ) !=0){
        if (strcmp ( n->word , word ) > 0 ){
            n = n->right;
        }
        else if(strcmp ( n->word , word ) < 0){
            n = n->left;
        }
    }
    if (n==NULL){
        printf("NOT FOUND");
        return;
    }
    printf("%s\n",n->word);
    files_Ptr k = n->files;
    while (k!=NULL) {
        pos_ptr q = k->cor ;
        while (q!=NULL) {
            printf("%s(%d,%d)\n",k->fileName,q->y,q->x);
            q = q->next;
        }
        k = k->next;
    }
    return;
}


int main(int argc, char *argv[])
{
    int j,i;
    for (i=0; i<W; i++){
        hashTable[i] = NULL;
    }
    for (j=1; j<argc; j++){
        FILE *curr_file=fopen(argv[j], "r+");
        int h_value = 0, x_axis = 1, y_axis=1, newline=0,endfile=0;
        if (curr_file == NULL) {
            perror("Error: ");
            return (-1);
        }
        char *word=NULL , *filename;
        filename = (char *) malloc(30*sizeof(char));
        filename = argv[j];
        while (endfile!=1){
            word = (char *) malloc(20*sizeof(char));
            readword(word, curr_file, &x_axis, &y_axis, &newline, &endfile);
            h_value = hashValue(word);
            treeBalancedInsert(&hashTable[h_value], word, filename, x_axis-(unsigned)strlen(word)-1, y_axis);
            if (newline==1){
                y_axis +=1;
                x_axis=1;
                newline=0;
            }
        }
        fclose(curr_file);
        free(word);
    }
    char *wordToSearch;
    wordToSearch = (char *) malloc(20*sizeof(char));
    scanf("%s",wordToSearch);
    search(wordToSearch,hashValue(wordToSearch),hashTable);
    return 0;
}

它写在Mac上,据说可行。但是当我在我的机器上编译并运行时,它就不会。 它的作用是将文本文件作为参数并对二进制树中的单词进行排序,这些单词根据单词的哈希值放置在哈希表中。然后你可以输入一个单词,它会告诉你它出现的坐标和哪些文件。

无论如何,eclipse上的调试一步一步地停留在filelistInsert的(curr = curr-&gt; next),代码块显示了另外两个问题,一个在treebalancedinsert函数中,它调用filelistinsert函数,在main当它需要treebalanceinsert函数时。 我无法找到filelistinsert中的错误,并且时间紧迫。 (我知道这是一个非常糟糕的问题,但我很绝望)

2 个答案:

答案 0 :(得分:3)

变化:

char c;
c = (char) malloc(sizeof(char));

char c;

注意:这是程序中的错误,但它并不能解释程序崩溃的原因。

其他地方:

    filename = (char *) malloc(30*sizeof(char));
    filename = argv[j];

这是内存泄漏,如果您假设filename30个字符数组,那么您可能会遇到麻烦。

答案 1 :(得分:1)

我看到了几个问题。

在我头脑中发出警报的第一件事就是像

这样的线条
(*curr_tree)->word=malloc(30*sizeof(char));

word = (char *) malloc(20*sizeof(char));

如果您从输入文件中读取超过19个字符的任何单词,您将会出现缓冲区溢出,这会在某些时候引起胃灼热。我有理由相信这是你问题的根源(当我在自己的源文本上运行这个程序时,我在阅读“(*curr_tree)->word=malloc(30*sizeof(char));”后开始得到段错误,很可能是因为我们溢出了20个字符的缓冲区并且别人的东西。

readword函数应根据输入文件的内容决定为单词分配多少内存。这意味着你将不得不使readword函数更聪明一些,并让它在读取输入时分配/重新分配缓冲区,如下所示:

void readword(char **word , FILE *curr_file, int *x_axis, int *y_axis, int *newline, int *endfile){
    int c;
    size_t bufLen = 0;
    const size_t bufExtent=10;
    size_t idx = 0;

    *word = NULL;

    /**
     * Read input one character at a time until we see a space or EOF
     */
    while ( ( c = fgetc( curr_file ) ) != EOF && !isspace( c ))
    {
      /**
       * Are we at the end of our buffer?
       */
      if ( idx == bufLen )
      {
        /**
         * Extend the buffer
         */
        char *tmp = realloc( *word, bufLen + bufExtent );
        if ( tmp )
        {
          bufLen += bufExtent;
          *word = tmp;
        }
        else
        {
          fprintf( stderr, "readword: Could not allocate memory to extend word\n" );
          return;
        }
      }
      (*word)[idx++] = c;
    }
   /**
     * If we read a string, 0-terminate it
     */
    if ( *word )
    {
      (*word)[idx] = 0;
      *x_axis += strlen(*word);
    }

然而,即便如此,我仍然会遇到运行时错误,因此此代码中还有其他时间炸弹。

然后是这个:

filename = (char *) malloc(30*sizeof(char));
filename = argv[j];

这不会将argv[j]的内容复制到刚刚分配的内存中;相反,它将指针值argv[j]分配给filename,覆盖指向您刚刚分配的内存的指针,从而导致内存泄漏。再次,你正在为文件名选择一个任意长度。尝试以下内容:

filename = malloc( strlen( argv[j] ) + 1 );
strcpy( filename, argv[j] );

Style nit:

隐藏typedef后面的指针类型是 not ,除非该类型是不透明的,并且永远不会直接进行引导。如果我在对象声明中看到*,我立即知道它应该如何在表达式中使用。使用foo_ptr typedef可能会使代码扫描更好一些,但它会阻碍IMO的低调。多年来我一直被这种方式所困扰,以至于我一般都避免使用typedef。