这里(样式和缩进改进):
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 个字符作为你的 6 个字符加上终止的空字符。然后,最重要的是,您实际上并没有编写终端空字符,因此您的字符串不会终止,并且您的 strcpy() 调用将在您的数组末尾运行,并且任何后续 strcmp() 调用都是会同样惨败。
所以,这里需要分配 7 个字节,并且需要将终止的 null 写入两个字符串。
从您的代码中跳出的少量其他点:
不要从 malloc() 转换返回值 - 这在 C 中是不必要的,通常被认为是不好的样式
sizeof(char) 定义为 1,所以不要使用它
typedefing 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 并注意我们有多少次:
每次我们在编写程序的主要逻辑时不做这些事情中的任何一件,都可以保证我们在做的时候不会出错。
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;
}
wordlist.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
wordlist.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;
}
logging.h:
#ifndef LOGGING_H
#define LOGGING_H
#include <stdbool.h>
void logging_enable(bool enabled);
void log_msg(char * fmt, ...);
#endif
logging.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$