如何将字符串(由用户输入)与文件中某行的第一个单词进行比较?

时间:2013-09-22 19:33:15

标签: c

我真的很难理解字符数组在C中是如何工作的。这看起来应该非常简单,但我不知道使用什么函数,或者如何使用它。

我希望用户输入一个字符串,我想迭代一个文本文件,将该字符串与文件中每一行的第一个单词进行比较。

这里的“字”是指由不是空格的字符组成的子字符串。

非常感谢帮助!

编辑: 为了更清楚,我想采取单个输入并在文本文件形式的数据库中搜索它。我知道如果它在数据库中,它将是一行的第一个单词,因为这是数据库格式化的方式。我想我可能会遍历数据库中的每个单词,但这似乎效率较低。

在数据库中找到输入后,我需要访问它后面的两个单词(在同一行)以实现程序的最终目标(这是计算性的)

3 个答案:

答案 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)

您最近的更新声明该文件实际上是一个数据库,您正在寻找一个单词。这非常重要。

如果你有足够的内存来容纳整个数据库,你应该这样做(读取整个数据库并安排它进行有效的搜索),所以你应该询问在文件中搜索

良好的数据库设计涉及triehash 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
}