在C中读取文本文件

时间:2015-03-11 19:13:40

标签: c file parsing pointers struct

我有一个文本文件如下:

sf5 sd6 sh7 

sh7 sd6 sf5(两种或其他可能的27种组合的任何顺序)。

我正在尝试从中提取值5,6, and 7 但是,我想以任何可能的顺序执行此操作,因此sf(somenumber)可以位于这3个位置中的任何位置,以及其他两个位置。因此,我正在尝试使用strstr作为我的一个宏。

#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);

    }    
}

但是输出仅对第一个值“sf5”是正确的,就好像后两个没有被解析一样。此外,如果我将“sf5”移动到最后,它的值提供为零,这也是没有意义的。

基本上,只有第一个if语句才能成功运行。任何帮助将不胜感激!

3 个答案:

答案 0 :(得分:2)

strstr函数给出搜索字符串的位置,如果找不到则为NULL。您必须在atol函数中使用此结果才能获得相关的值。

在下面的代码中,我使用变量token来存储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);    
}

答案 1 :(得分:0)

在每个if块之前打印t.values的值可能会有所帮助。 它表明t.values不会改变。只有第一个if块的表达式才为真。

如果您想使用strtok执行此操作... “对str1使用空指针的后续调用将导致保存的先前位置被恢复并从该点开始搜索...”

所以也许插入strtok(NULL,“\ n”)的调用,如下所示:

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);

现在输出

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

答案 2 :(得分:0)

您的代码有两个问题:

  • 在使用strstr()时你不使用返回指针,这样如果遇到字符串而不是在开头,它会在错误的地方查找数字;

  • 您不会在strtok()上循环以查找后续的子字符串。当strtok()将字符串分割成碎片时,您将无法在strstr()的第一个分隔符之外找到任何内容。

这是一种基于您原始方法的替代解决方案(但由于我在打字方面非常慢,在意外时间已经有2个其他有价值的解决方案;-))

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);
}

现在如果你输入aaasf5,他会找到5代表a,而之前发现0代表 此代码(也不属于您)解决了未找到其中一个值的情况。因此,您应该将a,b,c初始化为defautlt值,例如0.