简体   繁体   中英

How would I compare a string (entered by the user) to the first word of a line in a file?

I am really struggling to understand how character arrays work in C. This seems like something that should be really simple, but I do not know what function to use, or how to use it.

I want the user to enter a string, and I want to iterate through a text file, comparing this string to the first word of each line in the file.

By "word" here, I mean substring that consists of characters that aren't blanks.

Help is greatly appreciated!

Edit: To be more clear, I want to take a single input and search for it in a database of the form of a text file. I know that if it is in the database, it will be the first word of a line, since that is how to database is formatted. I suppose I COULD iterate through every single word of the database, but this seems less efficient.

After finding the input in the database, I need to access the two words that follow it (on the same line) to achieve the program's ultimate goal (which is computational in nature)

Here is some code that will do what you are asking. I think it will help you understand how string functions work a little better. Note - I did not make many assumptions about how well conditioned the input and text file are, so there is a fair bit of code for removing whitespace from the input, and for checking that the match is truly "the first word", and not "the first part of the first word". So this code will not match the input "hello" to the line "helloworld 123 234" but it will match to "hello world 123 234". Note also that it is currently case sensitive.

#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.
}

I think what you need is fseek() .

1) Pre-process the database file as follows. Find out the positions of all the '\\n' (carriage returns), and store them in array, say a , so that you know that i th line starts at a[i] th character from the beginning of the file.

2) fseek() is a library function in stdio.h, and works as given here . So, when you need to process an input string, just start from the start of the file, and check the first word, only at the stored positions in the array a . To do that:

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

and then

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

for checking the i th line. Or, more efficiently, you could use:

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

Explanation: What fseek() does is, it sets the read/write position indicator associated with the file at the desired position. So, if you know at which point you need to read or write, you can just go there and read directly or write directly. This way, you won't need to read whole lines just to get first three words.

Your recent update states that the file is really a database, in which you are looking for a word. This is very important.

If you have enough memory to hold the whole database, you should do just that (read the whole database and arrange it for efficient searching), so you should probably not ask about searching in a file.

Good database designs involve data structures like trie and hash table . But for a start, you could use the most basic improvement of the database - holding the words in alphabetical order (use the somewhat tricky qsort function to achieve that).

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
}

If your database is too big to hold in memory, you should use a trie that holds just the beginnings of the words in the database; for each beginning of a word, have a file offset at which to start scanning the file.

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
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM