简体   繁体   中英

Reading in text file in C

I've got a text file as follows:

sf5 sd6 sh7 

or sh7 sd6 sf5 (any order of the two or the other possible 27 combinations).

I'm trying to extract the values 5,6, and 7 from it However, I want to do this in any order possible, so sf(somenumber) can be in any of those 3 positions, as well as the other two. Thus, I'm trying to use strstr as one of my macros.

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

typedef struct test
{
    char * values;
}test;

int main(int argc, char * argv[])
{
    test t;
    FILE * file; 
    char str[100];
    int a,b,c;

    if(argc > 1) 
    {
        file = fopen(argv[1],"r");

        if(file == NULL)
        {
            exit(1);
        }
    }

    else 
    {

        exit(1);
    }

    while(fgets(str,100,file) != NULL)
    {
        t.values = strtok(str," \n");

        if(t.values == NULL)
            exit(1);
        if(strstr(t.values,"sf"))
        {
            a = atol(t.values+2); // the number two positions after the letter
        }


        if(strstr(t.values,"sd"))
        {
            b = atol(t.values+2); // the number two positions after the letter 

        }


        if(strstr(t.values,"sh"))
        {
            c = atol(t.values+2); // the number two positions after the letter

        }

        printf("Value of a: %d\n Value of b: %d\n Value of c: %d\n",a,b,c);

    }    
}

However the output is only correct for the first value "sf5", as if the second two aren't being parsed. Also, if I move "sf5" to the end, it's value provides to be zero which again makes no sense.

Basically, only the first if statement ever works successfully. Any help would be much appreciated!

The strstr function gives the position of the searched string or NULL if it's not found. You have to use this result in the atol function in order to get the value associated.

In the code below I use the variable token to store the result of strstr:

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

int main(int argc, char * argv[])
{
    FILE * file; 
    char str[100];
    int a,b,c;

    if(argc > 1) 
    {
        file = fopen(argv[1],"r");
        if(file == NULL)
        {
            exit(1);
        }
    }
    else 
    {
        exit(1);
    }

    while(fgets(str,100,file) != NULL)
    {
        char *token;

        token = strstr(str,"sf"));
        if (token != NULL)
        {
            a = atol(token+2); // the number two positions after the letter
        }

        token = strstr(str,"sd"));
        if (token != NULL)
        {
            b = atol(token+2); // the number two positions after the letter 

        }

        token = strstr(str,"sh"));
        if (token != NULL)
        {
            c = atol(token+2); // the number two positions after the letter
        }

        printf("Value of a: %d\n Value of b: %d\n Value of c: %d\n",a,b,c);
    }
    fclose(file);    
}

It may be helpful to print the value of t.values before each if block. It shows that t.values does not change. Only the first if block's expression will be true.

If you want to do this using strtok ... "Subsequent calls with a null pointer for str1 will cause the previous position saved to be restored and begins searching from that point..."

So maybe insert calls of strtok(NULL, " \\n"), like this:

t.values = strtok(str," \n");

if(strstr(t.values,"sf"))
{
    a = atol(t.values+2); // the number two positions after the letter
}

t.values = strtok(NULL," \n");  // get pointer to next token
if(strstr(t.values,"sd"))
{
    b = atol(t.values+2); // the number two positions after the letter
}

t.values = strtok(NULL," \n");  // get pointer to next token
if(strstr(t.values,"sh"))
{
    c = atol(t.values+2); // the number two positions after the letter
}

printf("Value of a: %d\n Value of b: %d\n Value of c: %d\n",a,b,c);

Now the output is

Value of a: 5
 Value of b: 6
 Value of c: 7

Your code has two issues :

  • in the use of strstr() you don't use the return pointer, so that if encountering the string but not at the beginning, it vwill look for the digit at the wrong place;

  • you don't loop on strtok() to find the subsequent substrings. As strtok() cuts the string in pieces, you won't find anythning beyond the first separator with strstr() ;

Here an alternative solution based on your original approach (but as I'm very slow in typing, in the meanttime there are already 2 other valuable solutions ;-) )

while (fgets(str, 100, file) != NULL)
{
    t.values = strtok(str, " \t\n"); 
    while (t.values) {    // loop to analyse each substring
        if (p = strstr(t.values, "sf"))
            a = atol(p + 2); // the number two positions after the FOUND string
        else if (p = strstr(t.values, "sd"))
            b = atol(p + 2); // the number two positions after the letter 
        else if (p = strstr(t.values, "sh"))
            c = atol(p + 2); // the number two positions after the letter
        t.values = strtok(NULL, " \t\n");
    }
    printf("Value of a: %d\n Value of b: %d\n Value of c: %d\n", a, b, c);
}

Now if you enter aaasf5 he will find 5 for a, while it found 0 before.
This code (nor yours) address the case where one of the value isn't found. You should therefore initialize your a,b,c to a defautlt value, for example 0.

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