C : text file, 字符串比较等

标签 c arrays string file string-comparison

首先是我的代码的链接:http://codepad.org/u68QnKPp

简要描述一下我的代码的作用:它在执行时需要正好 5 个字母的序列(例如:./anagramme p a n n e)并经历了很多,包括创建单词列表、与静态字典 (fr5.txt) 进行比较以查看如果法语中存在任何创建的单词(字谜),则应显示这些单词(如果存在)。

问题出现在第 191 行,即使两个字符串相等,比较(使用 streq)也会失败(提示缩进的 tryna 调试部分),因此即使遇到正确的单词也永远不会匹配任何单词(除非您将其直接编码到如果条件明显...... cf评论部分)。
streq()功能似乎功能 clap clap 因为注释部分在未注释时效果很好。

我的问题是:我在字符串比较/指针操作中做错了什么,我应该如何解决?

[编辑:显示问题代码(最新版本将始终是上面的链接)]

    time_t start,end;
    float elapsed;
        /**looping through dictionnary and comparing to words found**/
    start=clock();
    for(int i=0 ; i<res_len ; i++){
        fichier f = fopen("fr5.txt","r");
        if(f==NULL)exit(-1);
        if(verbose){echo("file opened for loop\n");}
        char* curr_loop_word = (char*)malloc(6 * sizeof(char));
        strcpy(curr_loop_word,iter[i]);
        for(int j=0 ; j<dico_nb_ligne ; j++){
            if(verbose)echo("browsing dictionnary");
            char* curr =(char*)malloc(6 * sizeof(char)) ;
            //strcpy(curr, fgetl(f));
            size_t len=5;
            ssize_t x = getline(&curr,&len,f);

                char* tst = (char*)malloc(6 * sizeof(char));
                char* test = (char*)malloc(6 * sizeof(char));
                for(int i=0 ; i<5 ; i++){
                    tst[i]=curr[i];
                    test[i]=curr_loop_word[i];
                }
                tst[5]='_';
                test[5]='_';
                strcpy(curr,tst);
                free(tst);
                strcpy(curr_loop_word,test);
                free(test);

            if(x==-1)exit((int)x);
            if(verbose)printf("size : %zu",x);
            if(verbose)printf("current dictionnary word : %s\n",curr);

            if(streq(curr,curr_loop_word)/* || streq(curr,"panne_")*/){//problem occurs here
                if(verbose)echo("found one :\n");
                strcpy(mots[mots_len],curr);
                mots_len+=1;
                if(verbose){
                    printf("correct word found : %s\n",curr);
                }
                break;
            }

        }
        fclose(f);
        if(verbose){echo("file closed after loop\n");}
    }
    end=clock();
    elapsed = (float)(end-start)/(float)CLOCKS_PER_SEC;

[/编辑]

PS:
我用 getline()因为每个单词都在文件中的单独一行上(单词已经排序为仅包含 5 个字母单词)。

PS2:
我希望你不介意 main() 之前的函数的花哨缩进。纯粹是为了清楚当我浏览代码而不在 main 上放置标记时是什么。

PS3:
我希望我的问题/问题很清楚,如果不告诉我什么不是,我会编辑它。

PS4:
也许一个好的解决方案是切换到 C++ 以避免至少一级指针?

最佳答案

这里(样式和缩进改进):

char * curr = malloc(6);
size_t len = 5;
ssize_t x = getline(&curr, &len, f);

char * tst = malloc(6);
char * test = malloc(6);
for ( int i = 0; i < 5; ++i ) {
    tst[i] = curr[i];
    test[i] = curr_loop_word[i];
}

tst[5] = '_';
test[5] = '_';

strcpy(curr, tst);
free(tst);

strcpy(curr_loop_word, test);
free(test);

你从 curr 开始,您提供给 getline() 的 6 字符动态分配数组存储一个 5 个字符的字符串。到目前为止还可以,除非你从不检查 getline()实际上有5个字符,你应该。

您似乎想要做的是将这 5 个字符加上下划线写入 tst .但你也做tst 6 个字符长,六个字符加上终止空字符需要 7 个字符。然后,最重要的是,您实际上并没有编写终端空字符,因此您的字符串不会终止,并且您的 strcpy()调用将在您的数组末尾运行,以及任何后续 strcmp()通话同样会失败。

所以,你需要在这里分配 7 个字节,并且你需要将终止的 null 写入两个字符串。

从您的代码中跳出的少量其他点:
  • 不要从 malloc() 转换返回值- 在 C 语言中是不必要的,通常被认为是不好的风格
  • sizeof(char)根据定义是 1,所以不要使用它
  • typedef 只会带来麻烦学习 FILE *以这种方式 - 只需使用 FILE *
  • 而不是定义你的 echo()函数,你可以使用标准 puts()
  • 在您的 notEOF()函数,在 char 的系统上未签名,x == EOF不会工作。 getchar()返回 int ,而不是 char ,所以你的 notEOF()函数应采用 int论据,而不是 char争论。
  • 没用malloc()一次又一次地分配一个在编译时已知的小尺寸数组。只需使用 char tst[6]; , 或 char tst[7];当你修复它时。当然没必要malloc()free()在循环的每次迭代中一遍又一遍地重复它们。
  • 无论如何,malloc()可能会失败,你永远不会检查这个。你应该。
  • 你的大main()功能急需分解成更小的功能,可以单独测试和调试。
  • 在同一主题上,很难理解为什么这么短的程序有这么多全局变量,而所有这些变量都只在一个函数中使用
  • 试着记住你的键盘有一个空格键

  • 编辑:这是一种明智的方法,使用适合问题的实际数据结构,并将逻辑适本地分解为单独的函数。它最终得到的代码比您的示例多一点,但是您在编写更多代码时所花费的时间节省了您不花时间盯着屏幕想知道为什么它不工作的时间。特别是看主文件,dictlist.c并注意我们有多少次:
  • 调用malloc() - 从不
  • 比较一个字符串与另一个字符串 - 一次,在检查命令行参数时
  • 复制字符串 - 从不
  • 直接设置字符串中的字符,或手动将终止空字符添加到字符串 - 一次,从文件输入中删除换行符
  • 增加一个计数器 - 从不,除了 for循环索引
  • 排序数据 - 从不

  • 每次我们在编写程序的主逻辑时不做这些事情中的任何一件,都是一次我们保证在做的时候不会出错。

    dictfind.c:
    #include <stdio.h>
    #include <stdlib.h>
    #include <stdbool.h>
    #include <string.h>
    #include "wordlist.h"
    #include "logging.h"
    
    #define MAX_LINE_LENGTH 64
    
    
    /*
     * Returns a word list made from entries in a dictionary file
     */
    
    WordList get_dictionary(void)
    {
        WordList dict = wordlist_create();
    
        FILE * fp = fopen("dictionary.txt", "r");
        if ( !fp ) {
            perror("couldn't open dictionary for reading");
            exit(EXIT_FAILURE);
        }
    
        char buffer[MAX_LINE_LENGTH];
        while ( fgets(buffer, MAX_LINE_LENGTH, fp) ) {
            size_t len = strlen(buffer);
            if ( len > 0 && buffer[len - 1] == '\n' ) {
                buffer[len - 1] = 0;
            }
            wordlist_add(dict, buffer);
        }
    
        if ( fclose(fp) != 0 ) {
            perror("couldn't close dictionary file");
            exit(EXIT_FAILURE);
        }
    
        log_msg("Read %zu words into dictionary.\n", wordlist_length(dict));
    
        return dict;
    }
    
    
    /*
     * Returns true if none of the arguments equal each other
     */
    
    bool no_dups(size_t i, size_t j, size_t k, size_t l, size_t m)
    {
        return i != j && i != k && i != l && i != m &&
               j != k && j != l && j != m && k != l &&
               k != m && l != m;
    }
    
    
    /*
     * Returns a list of words of all combinations of the five
     * letter string provided.
     */
    
    WordList make_words(char * letters)
    {
        WordList words = wordlist_create();
    
        for ( size_t i = 0; i < 5; ++i ) {
            for ( size_t j = 0; j < 5; ++j ) {
                for ( size_t k = 0; k < 5; ++k ) {
                    for ( size_t l = 0; l < 5; ++l ) {
                        for ( size_t m = 0; m < 5; ++m ) {
                            if ( no_dups(i, j, k, l, m) ) {
                                char new_word[] = {letters[i], letters[j],
                                    letters[k], letters[l], letters[m], 0};
                                wordlist_add_unique(words, new_word);
                            }
                        }
                    }
                }
            }
        }
    
        log_msg("Made %zu words from input.\n", wordlist_length(words));
    
        return words;
    }
    
    
    /*
     * Returns a list of dictionary matches from a list of candidate words
     */
    
    WordList get_matches(WordList dict, WordList words)
    {
        WordList matches = wordlist_create();
    
        for ( size_t i = 0; i < wordlist_length(words); ++i ) {
            char * word = wordlist_word(words, i);
            if ( wordlist_contains(dict, word) ) {
                wordlist_add(matches, word);
                log_msg("Adding found match: %s\n", word);
            }
        }
    
        return matches;
    }
    
    
    /*
     * Main function
     */
    
    int main(int argc, char ** argv)
    {
        if ( argc == 7 && strcmp(argv[6], "-v") == 0 ) {
            logging_enable(true);
        }
        else if ( argc != 6 ) {
            fprintf(stderr, "Usage: dictfind a b c d e [-v]\n");
            return EXIT_SUCCESS;
        }
    
        char letters[5] = {argv[1][0], argv[2][0], argv[3][0],
                           argv[4][0], argv[5][0]};
    
        WordList dict = get_dictionary();
        WordList words = make_words(letters);
        WordList matches = get_matches(dict, words);
    
        for ( size_t i = 0; i < wordlist_length(matches); ++i ) {
            printf("Match found: %s\n", wordlist_word(matches, i));
        }
    
        wordlist_destroy(dict);
        wordlist_destroy(words);
        wordlist_destroy(matches);
    
        return EXIT_SUCCESS;
    }
    

    单词表.h:
    #ifndef WORD_LIST_H
    #define WORD_LIST_H
    
    #include <stddef.h>
    #include <stdbool.h>
    
    typedef struct wordlist * WordList;
    
    WordList wordlist_create(void);
    void wordlist_destroy(WordList list);
    void wordlist_add(WordList list, char * word);
    void wordlist_add_unique(WordList list, char * word);
    char * wordlist_word(WordList list, size_t index);
    int wordlist_find(WordList list, char * word);
    bool wordlist_contains(WordList list, char * word);
    size_t wordlist_length(WordList list);
    
    #endif
    

    词表.c:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include "wordlist.h"
    
    #define INITIAL_LIST_CAPACITY 16
    
    struct wordlist {
        size_t length;
        size_t capacity;
        char ** words;
    };
    
    WordList wordlist_create(void)
    {
        struct wordlist * new_list = malloc(sizeof *new_list);
        if ( !new_list ) {
            perror("couldn't allocate memory for word list");
            exit(EXIT_FAILURE);
        }
    
        char ** new_words = malloc(INITIAL_LIST_CAPACITY * sizeof(*new_words));
        if ( !new_words ) {
            perror("couldn't allocate memory for words");
            exit(EXIT_FAILURE);
        }
    
        new_list->length = 0;
        new_list->capacity = INITIAL_LIST_CAPACITY;
        new_list->words = new_words;
    
        return new_list;
    }
    
    void wordlist_destroy(WordList list)
    {
        for ( size_t i = 0; i < list->length; ++i ) {
            free(list->words[i]);
        }
        free(list->words);
        free(list);
    }
    
    void wordlist_add(WordList list, char * word)
    {
        if ( list->length == list->capacity ) {
            list->capacity *= 2;
            char ** new_words = realloc(list->words,
                                        list->capacity * sizeof *new_words);
            if ( !new_words ) {
                perror("couldn't reallocate memory for word list");
                exit(EXIT_FAILURE);
            }
            list->words = new_words;
        }
    
        char * new_word = malloc(strlen(word) + 1);
        if ( !new_word ) {
            perror("couldn't allocate memory for new word");
            exit(EXIT_FAILURE);
        }
    
        strcpy(new_word, word);
        list->words[list->length++] = new_word;
    }
    
    void wordlist_add_unique(WordList list, char * word)
    {
        if ( wordlist_find(list, word) == -1 ) {
            wordlist_add(list, word);
        }
    }
    
    char * wordlist_word(WordList list, size_t index)
    {
        if ( index >= list->length ) {
            fprintf(stderr, "word list accessed out of bounds\n");
            exit(EXIT_FAILURE);
        }
        return list->words[index];
    }
    
    int wordlist_find(WordList list, char * word)
    {
        for ( int i = 0; i < list->length; ++i ) {
            if ( strcmp(list->words[i], word) == 0 ) {
                return i;
            }
        }
        return -1;
    }
    
    bool wordlist_contains(WordList list, char * word)
    {
        return wordlist_find(list, word) != -1;
    }
    
    size_t wordlist_length(WordList list)
    {
        return list->length;
    }
    

    记录.h:
    #ifndef LOGGING_H
    #define LOGGING_H
    
    #include <stdbool.h>
    
    void logging_enable(bool enabled);
    void log_msg(char * fmt, ...);
    
    #endif
    

    记录.c:
    #include <stdio.h>
    #include <stdbool.h>
    #include <stdarg.h>
    #include "logging.h"
    
    static bool logging_enabled = false;
    
    void logging_enable(bool enabled)
    {
        logging_enabled = enabled;
    }
    
    void log_msg(char * fmt, ...)
    {
        if ( logging_enabled ) {
            va_list ap;
            va_start(ap, fmt);
            vfprintf(stderr, fmt, ap);
            va_end(ap);
        }
    }
    

    字典.txt:
    apple
    plate
    words
    finds
    trunk
    poked
    tiger
    horse
    spill
    horns
    stuff
    boxed
    fried
    biter
    sword
    tribe
    shore
    hoser
    pills
    fired
    

    生成文件:
    dictfind: dictfind.o wordlist.o logging.o
        cc -o dictfind dictfind.o wordlist.o logging.o
    
    dictfind.o: dictfind.c wordlist.h logging.h
        cc -o dictfind.o dictfind.c -c -std=c99 -pedantic -Wall
    
    wordlist.o: wordlist.c wordlist.h
        cc -o wordlist.o wordlist.c -c -std=c99 -pedantic -Wall
    
    logging.o: logging.c logging.h
        cc -o logging.o logging.c -c -std=c99 -pedantic -Wall
    
    clean:
        rm -f dictfind dictfind.o wordlist.o logging.o
    

    带有样本输出:
    paul@thoth:~/src/sandbox/dictfind$ make
    cc -o dictfind.o dictfind.c -c -std=c99 -pedantic -Wall
    cc -o wordlist.o wordlist.c -c -std=c99 -pedantic -Wall
    cc -o logging.o logging.c -c -std=c99 -pedantic -Wall
    cc -o dictfind dictfind.o wordlist.o logging.o
    paul@thoth:~/src/sandbox/dictfind$ ./dictfind b r i t e
    Match found: biter
    Match found: tribe
    paul@thoth:~/src/sandbox/dictfind$ ./dictfind d w s r o -v
    Read 20 words into dictionary.
    Made 120 words from input.
    Adding found match: words
    Adding found match: sword
    Match found: words
    Match found: sword
    paul@thoth:~/src/sandbox/dictfind$ ./dictfind b i t e s
    paul@thoth:~/src/sandbox/dictfind$ ./dictfind f t u s f -v
    Read 20 words into dictionary.
    Made 60 words from input.
    Adding found match: stuff
    Match found: stuff
    paul@thoth:~/src/sandbox/dictfind$ ./dictfind a a a a h -v
    Read 20 words into dictionary.
    Made 5 words from input.
    paul@thoth:~/src/sandbox/dictfind$ 
    

    关于C : text file, 字符串比较等,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42308096/

    相关文章:

    javascript - 如何在提交时将复杂的表单对象存储到 redux 状态?

    javascript - 在下面提到的场景中如何为爱好提供 typescript 类型?

    C - 将 2 for 循环重写为 1 for 循环以复制数组。

    c - 为什么 realloc 会出错?错误中止(核心转储)

    c - 查找在c中发送信号的进程

    java - Java 中大字符串的唯一 String 对象

    javascript - 我如何在java脚本中找到一个句子中单词的出现次数

    iphone - 如何将 C 数组声明为 Objective-C 对象的属性?

    Javascript - 无限滚动 JSON 数组?

    java - 如何在 File Java 中保留 2 个制表符空间格式