我真的很难理解字符数组在C中是如何工作的。这看起来应该非常简单,但我不知道使用什么函数,或者如何使用它。
我希望用户输入一个字符串,我想迭代一个文本文件,将该字符串与文件中每一行的第一个单词进行比较。
这里的“字”是指由不是空格的字符组成的子字符串。
非常感谢帮助!
编辑: 为了更清楚,我想采取单个输入并在文本文件形式的数据库中搜索它。我知道如果它在数据库中,它将是一行的第一个单词,因为这是数据库格式化的方式。我想我可能会遍历数据库中的每个单词,但这似乎效率较低。
在数据库中找到输入后,我需要访问它后面的两个单词(在同一行)以实现程序的最终目标(这是计算性的)
答案 0 :(得分:1)
以下是一些可以满足您要求的代码。我认为这将有助于您了解字符串函数如何更好地工作。注意 - 我没有对输入和文本文件的条件有多好做出很多假设,所以有很多代码可以从输入中删除空格,并检查匹配是否真的是“第一个单词”,而不是“第一个单词的第一部分”。因此,此代码将不会将输入“hello”与“helloworld 123 234”行匹配,但它将匹配“hello world 123 234”。另请注意,它目前区分大小写。
#include <stdio.h>
#include <string.h>
int main(void) {
char buf[100]; // declare space for the input string
FILE *fp; // pointer to the text file
char fileBuf[256]; // space to keep a line from the file
int ii, ll;
printf("give a word to check:\n");
fgets(buf, 100, stdin); // fgets prevents you reading in a string longer than buffer
printf("you entered: %s\n", buf); // check we read correctly
// see (for debug) if there are any odd characters:
printf("In hex, that is ");
ll = strlen(buf);
for(ii = 0; ii < ll; ii++) printf("%2X ", buf[ii]);
printf("\n");
// probably see a carriage return - depends on OS. Get rid of it!
// note I could have used the result that ii is strlen(but) but
// that makes the code harder to understand
for(ii = strlen(buf) - 1; ii >=0; ii--) {
if (isspace(buf[ii])) buf[ii]='\0';
}
// open the file:
if((fp=fopen("myFile.txt", "r"))==NULL) {
printf("cannot open file!\n");
return 0;
}
while( fgets(fileBuf, 256, fp) ) { // read in one line at a time until eof
printf("line read: %s", fileBuf); // show we read it correctly
// find whitespace: we need to keep only the first word.
ii = 0;
while(!isspace(fileBuf[ii]) && ii < 255) ii++;
// now compare input string with first word from input file:
if (strlen(buf)==ii && strstr(fileBuf, buf) == fileBuf) {
printf("found a matching line: %s\n", fileBuf);
break;
}
}
// when you get here, fileBuf will contain the line you are interested in
// the second and third word of the line are what you are really after.
}
答案 1 :(得分:1)
我认为你需要的是fseek()
。
1)按如下方式预处理数据库文件。找出所有'\ n'(回车)的位置,并将它们存储在数组中,比如说a
,这样就知道i
行从a[i]
字符开始从文件的开头。
2)fseek()
是stdio.h中的库函数,并按给定的here工作。因此,当您需要处理输入字符串时,只需从文件的开头开始,并检查第一个单词,仅在数组a
中的存储位置。要做到这一点:
fseek(inFile , a[i] , SEEK_SET);
然后
fscanf(inFile, "%s %s %s", yourFirstWordHere, secondWord, thirdWord);
用于检查i
行。
或者,更有效率,您可以使用:
fseek ( inFile , a[i]-a[i-1] , SEEK_CURR )
说明:fseek()的作用是,它将与文件关联的读/写位置指示器设置在所需位置。所以,如果你知道你需要读或写,你可以去那里直接阅读或直接写。通过这种方式,您不需要阅读整行来获得前三个单词。
答案 2 :(得分:1)
您最近的更新声明该文件实际上是一个数据库,您正在寻找一个单词。这非常重要。
如果你有足够的内存来容纳整个数据库,你应该这样做(读取整个数据库并安排它进行有效的搜索),所以你应该不询问在文件中搜索
良好的数据库设计涉及trie和hash table等数据结构。但首先,您可以使用数据库的最基本的改进 - 按字母顺序保留单词(使用有点棘手的qsort函数来实现)。
struct Database
{
size_t count;
struct Entry // not sure about C syntax here; I usually code in C++; sorry
{
char *word;
char *explanation;
} *entries;
};
char *find_explanation_of_word(struct Database* db, char *word)
{
for (size_t i = 0; i < db->count; i++)
{
int result = strcmp(db->entries[i].word, word);
if (result == 0)
return db->entries[i].explanation;
else if (result > 0)
break; // if the database is sorted, this means word is not found
}
return NULL; // not found
}
如果你的数据库太大而无法容纳在内存中,你应该使用只包含数据库中单词开头的trie;对于单词的每个开头,都有一个文件偏移量,用于开始扫描文件。
char* find_explanation_in_file(FILE *f, long offset, char *word)
{
fseek(f, offset, SEEK_SET);
char line[100]; // 100 should be greater than max line in file
while (line, sizeof(line), f)
{
char *word_in_file = strtok(line, " ");
char *explanation = strtok(NULL, "");
int result = strcmp(word_in_file, word);
if (result == 0)
return explanation;
else if (result > 0)
break;
}
return NULL; // not found
}