Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/file/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在C语言中读取文本文件_C_File_Parsing_Pointers_Struct - Fatal编程技术网

在C语言中读取文本文件

在C语言中读取文本文件,c,file,parsing,pointers,struct,C,File,Parsing,Pointers,Struct,我有一个文本文件,如下所示: sf5 sd6 sh7 或sh7 sd6 sf5(两种或其他可能的27种组合的任意顺序) 我试图从中提取值5、6和7 然而,我想以任何可能的顺序来做这件事,所以sf(somenumber)可以处于这3个位置中的任何一个,以及其他两个位置。因此,我尝试使用strstr作为我的宏之一 #include <stdio.h> #include <string.h> #include <stdlib.h> #include <ct

我有一个文本文件,如下所示:

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

我试图从中提取值
5、6和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);

    }    
}
#包括
#包括
#包括
#包括
类型定义结构测试
{
字符*值;
}试验;
int main(int argc,char*argv[])
{
试验t;
文件*文件;
char-str[100];
INTA、b、c;
如果(argc>1)
{
file=fopen(argv[1],“r”);
if(file==NULL)
{
出口(1);
}
}
其他的
{
出口(1);
}
while(fgets(str,100,file)!=NULL)
{
t、 值=strtok(str,“\n”);
如果(t.values==NULL)
出口(1);
if(strstr(t.值,“sf”))
{
a=atol(t.values+2);//字母后面的两个位置
}
if(strstr(t.值,“sd”))
{
b=atol(t.values+2);//字母后面的两个位置
}
if(strstr(t.值,“sh”))
{
c=atol(t.values+2);//字母后面的两个位置
}
printf(“a的值:%d\n b的值:%d\n c的值:%d\n”,a、b、c);
}    
}
但是,输出仅对第一个值“sf5”正确,就好像第二个值没有被解析一样。另外,如果我把“sf5”移到末尾,它的值将为零,这同样没有意义


基本上,只有第一个
if
语句能够成功工作。任何帮助都将不胜感激

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);    
}
#包括
#包括
#包括
#包括
int main(int argc,char*argv[])
{
文件*文件;
char-str[100];
INTA、b、c;
如果(argc>1)
{
file=fopen(argv[1],“r”);
if(file==NULL)
{
出口(1);
}
}
其他的
{
出口(1);
}
while(fgets(str,100,file)!=NULL)
{
字符*令牌;
令牌=strstr(str,“sf”);
if(令牌!=NULL)
{
a=atol(token+2);//字母后面的第二个位置
}
令牌=strstr(str,“sd”);
if(令牌!=NULL)
{
b=atol(token+2);//字母后的第二个位置
}
令牌=strstr(str,“sh”);
if(令牌!=NULL)
{
c=atol(token+2);//字母后的第二个位置
}
printf(“a的值:%d\n b的值:%d\n c的值:%d\n”,a、b、c);
}
fclose(文件);
}

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

如果你想使用。。。 “使用空指针对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

您的代码有两个问题:

  • 在使用时,不要使用返回指针,因此如果遇到字符串而不是在开头,它将在错误的位置查找数字

  • 您不会循环查找后续的子字符串。由于
    strtok()
    将字符串切碎,因此除了第一个分隔符之外,您将无法使用
    strstr()
    找到任何内容

这里有一个基于您最初方法的替代解决方案(但由于我打字速度非常慢,同时还有另外两个有价值的解决方案;-))

现在,如果您输入aaasf5,他将为a找到5,而之前它找到了0。

此代码(或您的代码)解决了找不到其中一个值的情况。因此,您应该将a、b、c初始化为defautlt值,例如0

使用
atol()
可以防止您知道程序失败的原因,请尝试
char*endptr;a=strtol(t.值+2,&endptr,10);如果(*endptr!='\0')printf(“值'%s'未转换,因为无法转换下列字符'%s'\n',t.values+2,endptr))。您没有检查
t.values!=NULL
,如果
strtok()
找不到
'\n'
它将返回
NULL
。如果您不介意使用外部库,您可以使用正则表达式非常轻松地解析它,使用类似于PCRE:。如果您想手动执行一些更易于维护的操作,而不考虑复杂性的增加,那么一个简单的起点就是阅读递归体面解析。不幸的是,当我最终学习如何使用PCRE这样的外部库时,实现它就太晚了。在第一次通过3
If()
s之后,do
t.values=strtok(NULL,“\n”)并对3
if()
s进行测试,直到
t.values==NULL
。我已检查,t.values从不为NULL。
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);
}