首先是我的代码的链接: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/