简体   繁体   中英

What is the best way to read a file and then compare a string to what is in that file?

What is the best way to read a file and then compare a string to what is in that file? I have been trying to figure this out for days now and I am just stumped on how to do it. I would greatly appreciate some help.

Your question outlines in broad terms reading a string from a file, and making a string comparison with another string . To read from your file, you must first open the file for reading. For reading text from a file, your normal choice in C is fopen to open a stream and asign the return to a FILE pointer which can be used with the collection of stream reading functions found in the standard library. (eg fgetc , fgets , fscanf , getline , etc..)

Your job is to open a file, validate it is open, read the needed information from the file, and then close the file. To accomplish this, you will need to prepare a buffer (character array, or allocated block of memory) with sufficient space to hold the information read from the file ( +1 char for the nul-terminating character). Without the nul-terminating character, you have an array of characters and not a valid string ) A short example could be:

char buf[256] = {0};  /* char array to hold 255 chars + nul-terminating char */
FILE *fp = NULL;      /* FILE pointer to hold return of fopen */

fp = fopen (filename, "r"); /* open file for reading    */
if (fp == NULL) {           /* if not open throw error  */
    fprintf (stderr, "error: file open failed 'filename'.\n");
    exit (EXIT_FAILURE);
}

If you are reading a single string without included spaces from the file, you can simply read the first word with fscanf into buf . fscanf returns the number of successful conversion that match the given format specifier . Use the field width option with your format specifier to insure you read no more than your buffer will hold (eg "%255s" ) saving room for the nul-terminating char at the end. Use the return from fscanf to validate your read:

if (fscanf (fp, "%255s", buf) != 1) {
    fprintf (stderr, "error: fscanf read failure from 'filename'.\n");
    exit (EXIT_FAILURE);    
}

If the string you are reading from the file can include whitespace , then you either need to modify your fscanf format specifier , (eg "%255[...]" , where the character class [...] describes an expression to match your needed information) or use one of line-oriented stream functions ( fgets or getline ) to read an entire line from the file into buf and then parse buf as needed within the file. For example if the first line in the file included text separated by a comma :

The quick brown fox, jumps over the lazy dog.

and you need to compare the information appearing before the comma with a test string, you could do something like:

char str[256] = {0};    /* string to hold chars parsed from buf */
if (fgets (buf, 256, fp) == NULL) {
    fprintf (stderr, "error: fgets read failure from 'filename'.\n");
    exit (EXIT_FAILURE);    
}

if (sscanf (buf, "%[^,]", str) != 1) {
    fprintf (stderr, "error: sscanf no conversion made.\n");
    exit (EXIT_FAILURE);    
}

Finally, to compare if the strings are equal, the normal choice is to use strcmp . Two strings are equal if the return of the comparison by strcmp is 0 . You can implement the test like:

if (strcmp (str, teststr) == 0) /* test if strings are equal */
    printf ("\n string  : %s\n teststr : %s  EQUAL\n", str, teststr);
else
    printf ("\n string  : %s\n teststr : %s  DIFFER\n", str, teststr);

Which would perform the test with strcmp and print the string read from the file and the teststr and whether the strings are EQUAL or DIFFER.

You can put all the pieces together as follows. (note: the program takes the filename as the first argument, but by using a simple ternary operator, will use a default filename of data.txt if no filename is given -- stdin can be substituted for "data.txt" to read from stdin by default):

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main (int argc, char **argv) {

    char buf[256] = {0};  /* char array to hold 255 chars + null-terminating char */
    char str[256] = {0};  /* string to hold chars parsed from buf */
    char *teststr = "The quick brown fox";  /* string literal for comparison */
    FILE *fp = NULL;      /* FILE pointer to hold return of fopen */

    fp = fopen (argc > 1 ? argv[1] : "data.txt", "r");  /* open file for reading    */
    if (fp == NULL) {                                   /* if not open throw error  */
        fprintf (stderr, "error: file open failed 'filename'.\n");
        exit (EXIT_FAILURE);
    }

    if (fgets (buf, 256, fp) == NULL) { /* read 1 line from file */
        fprintf (stderr, "error: fgets read failure from 'filename'.\n");
        exit (EXIT_FAILURE);    
    }
    fclose (fp);            /* close file when reading complete */

    if (sscanf (buf, "%[^,]", str) != 1) {  /* parse up to ',' into str */
        fprintf (stderr, "error: sscanf no conversion made.\n");
        exit (EXIT_FAILURE);    
    }

    if (strcmp (str, teststr) == 0) /* test if strings are equal */
        printf ("\n string  : %s\n teststr : %s  EQUAL\n", str, teststr);
    else
        printf ("\n string  : %s\n teststr : %s  DIFFER\n", str, teststr);

    return 0;
}

Input File

$ cat dat/qbfcomma.txt
The quick brown fox, jumps over the lazy dog.

Use/Output

$ ./bin/fgets_strcmp dat/qbfcomma.txt

 string  : The quick brown fox
 teststr : The quick brown fox  EQUAL

Let me know if you have any additional questions.

Note: you could simply use fscanf with the format specifier "%255[^,]" to read the same information into buf and then simply test buf against teststr without the need to parse the line into str using sscanf . But it is important to note that the normal approach is to use a line-oriented (reading a line at a time) and then parsing the needed information from the line within your code. This will avoid a number of pitfalls that arise from using fscanf or when trying to shoehorn all pattern matching into a fscanf format specifier. It also allows additional methods of parsing the needed information from the buffer (such as using pointer arithmetic, etc..).

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