1

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

我希望用户输入一个字符串,并且我想遍历一个文本文件,将此字符串与文件中每一行的第一个单词进行比较。

这里的“单词”是指由非空白字符组成的子字符串。

非常感谢您的帮助!

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

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

4

3 回答 3

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.
}
于 2013-09-22T20:16:46.947 回答
1

我想你需要的是fseek().

1) 对数据库文件进行如下预处理。找出所有 '\n' (回车)的位置,并将它们存储在数组中,例如a,以便您知道i第 行从a[i]文件开头的第 th 个字符开始。

2)fseek()是 stdio.h 中的一个库函数,按此处给出的方式工作。因此,当您需要处理输入字符串时,只需从文件的开头开始,并检查第一个单词,仅在数组中存储的位置a。要做到这一点:

fseek(inFile , a[i] , SEEK_SET);

接着

fscanf(inFile, "%s %s %s", yourFirstWordHere, secondWord, thirdWord);

用于检查第ith 行。或者,更有效的是,您可以使用:

fseek ( inFile , a[i]-a[i-1] , SEEK_CURR )

说明: fseek() 所做的是,它将与文件关联的读/写位置指示器设置在所需位置。所以,如果你知道什么时候需要读或写,你可以直接去那里直接读或写。这样,您无需阅读整行即可获得前三个单词。

于 2013-09-22T20:32:55.473 回答
1

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

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

良好的数据库设计涉及诸如trie哈希表之类的数据结构。但首先,您可以使用数据库最基本的改进——按字母顺序保存单词(使用有点棘手的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
}
于 2013-09-22T21:10:23.667 回答