Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/66.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_Parsing_Std - Fatal编程技术网

C 扫描可变数量的';字段';从文本文件

C 扫描可变数量的';字段';从文本文件,c,parsing,std,C,Parsing,Std,我想从空白分隔的文本文件中扫描一个形成向量的变量,但这个绊脚石(对我来说通常都是这样)缺乏优雅 目前,我的扫描代码要求将向量的大小描述为文件中的第一个元素: 7 : 1 3 6 8 -9 .123 1.1 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #define LINE_MAX 256 #define VECTOR_SIZE_MA

我想从空白分隔的文本文件中扫描一个形成向量的变量,但这个绊脚石(对我来说通常都是这样)缺乏优雅

目前,我的扫描代码要求将向量的大小描述为文件中的第一个元素:

7 : 1 3 6 8 -9 .123 1.1
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#define LINE_MAX 256
#define VECTOR_SIZE_MAX 32

struct vector
{
    size_t size;
    double *values;
};

// returns 1 on error
_Bool scan_vector(FILE *file, struct vector *v)
{
    char buffer[LINE_MAX];
    if(!fgets(buffer, sizeof(buffer), file))
        return 1;

    double values[VECTOR_SIZE_MAX];

    size_t size = 0;
    errno = 0;

    for(char *head = buffer, *tail = NULL;; ++size, head = tail)
    {
        while(isspace(*head)) ++head;
        if(!*head) break;

        if(size >= VECTOR_SIZE_MAX)
            return 1;

        values[size] = strtod(head, &tail);
        if(errno || head == tail)
            return 1;
    }

    v->size = size;
    v->values = malloc(sizeof(double) * size);
    if(!v->values) return 1;

    memcpy(v->values, values, sizeof(double) * size);

    return 0;
}

int main(void)
{
    struct vector v;
    while(!scan_vector(stdin, &v))
    {
        printf("value count: %u\n", (unsigned)v.size);
        free(v.values);
    }

    return 0;
}
这让我很困扰,因为“7”可以通过检查空白来确定

我尝试过各种形式的fscanf()、strtok()等,但它们似乎都是野蛮的forcish。如果不使用lex/yacc(不可用),有人能提出比下面更优雅的建议吗

typedef struct vector_tag
{
    int Length;
    double * value;
} vector;

vector v;

char buf[BIG_ENOUGH], key[BIG_ENOUGH], val[BIG_ENOUGH];

void scan_vector(FILE * fh)
{
    int i, length;
    double * data;
    char * tok;

    do {
        if (feof(fh)) return;
        fgets(buf, sizeof buf, fh);    
    } while (2 != sscanf(buf,"%[^:]:%[^\n\r]",key,val));

    length      =
    v.Length    = strtol(key,NULL,10);
    data        =
    v.value     = malloc(length * sizeof(double));

    tok = strtok(val, " "); /* I'd prefer tokenizing on whitespace */
    for (i = 0; i++ < v.Length; ) {
        * data++ = strtod(tok,NULL);;
        tok = strtok(NULL, " "); /* Again, tokenize on whitespace */
    }
}
typedef结构向量\u标记
{
整数长度;
双*值;
}载体;
向量v;
char buf[足够大]、key[足够大]、val[足够大];
无效扫描向量(文件*fh)
{
int i,长度;
双*数据;
char*tok;
做{
if(feof(fh))返回;
fgets(buf、大小buf、fh);
}而(2!=sscanf(buf,“%[^:::%[^\n\r]”,key,val));
长度=
v、 长度=strtol(键,空,10);
资料=
v、 值=malloc(长度*sizeof(双精度));
tok=strtok(val,“”;/*我更喜欢在空格上标记*/
对于(i=0;i++
解决方案: 多亏了检查过的答案,我实现了:

static int scan_vector(FILE * fh, vector * v)
{
    if (1 == fscanf(fh,"%d:",& v->length))
    {
        int         i;

        v->value    = malloc(v->Length * sizeof(double));

        assert (NULL != v->value);

        for (i = 0; i < v->Length; i++)
        {
            if (fscanf(fh,"%lf",v->value + i) != 1) return(0);
        } 
        return(1);
    } 
    return(0);
} /* scan_vector() */
静态整数扫描向量(文件*fh,向量*v)
{
如果(1==fscanf(fh、%d:,&v->长度))
{
int i;
v->value=malloc(v->Length*sizeof(double));
断言(NULL!=v->value);
对于(i=0;iLength;i++)
{
如果(fscanf(fh,“%lf”,v->value+i)!=1)返回(0);
} 
申报表(1);
} 
返回(0);
}/*扫描向量()*/
如果您使用,那么如果您没有分配足够的初始
malloc()
内存,则始终可以请求更多内存。常见的策略是分配任意
n
项开始。当空间用完时,您可以加倍
n
并调整缓冲区大小

或者,您可以使用链表而不是数组。链表比数组更好地处理插入和追加操作,但是您放弃了按索引访问项目的功能。

如果使用链表,如果初始
malloc()分配的内存不足,您可以随时请求更多的内存。常见的策略是分配任意
n
项开始。当空间用完时,您可以加倍
n
并调整缓冲区大小


或者,您可以使用链表而不是数组。链表比数组更好地处理插入和追加操作,但您放弃了按索引访问项目的功能。

向量可以有多大?
一个办法是

  • 将一行扫描到本地缓冲区(我认为这是一个向量数据)
  • 扫描本地缓冲区以计算空白分隔符(非常容易编码)
  • 然后进行正确的分配
  • 然后,初始化向量
正如您所观察到的,维度
'7'
不必是输入的一部分。
您只需要一个足够大的本地缓冲区,以容纳可能最长的行。

还有,它的一些错误处理
:-)
向量有多大?
一个办法是

  • 将一行扫描到本地缓冲区(我认为这是一个向量数据)
  • 扫描本地缓冲区以计算空白分隔符(非常容易编码)
  • 然后进行正确的分配
  • 然后,初始化向量
正如您所观察到的,维度
'7'
不必是输入的一部分。
您只需要一个足够大的本地缓冲区,以容纳可能最长的行。

还有,它的一些错误处理
:-)

像这样的东西有什么问题:

int scan_vector(FILE *fh)
{
    char pad[2];
    int i;
    if (fscanf(fh,"%d %1[:]", &v.Length, &pad) != 2)
        return -1;
    v.value = malloc(v.Length * sizeof(double));
    for (i = 0; i < v.Length; i++) {
        if (fscanf(fh, "%lf", &v.value[i]) != 1)
            return -1;
    }
    return 0;
}
int扫描向量(文件*fh)
{
炭垫[2];
int i;
如果(fscanf(fh,“%d%1[:]”,&v.Length,&pad)!=2)
返回-1;
v、 值=malloc(v.Length*sizeof(double));
对于(i=0;i
这将尝试使用scanf读取向量,如果出现问题,将返回-1错误代码


如果您想做比这复杂得多的事情,至少最好使用flex(如果不是bison的话)。

这样的东西有什么问题:

int scan_vector(FILE *fh)
{
    char pad[2];
    int i;
    if (fscanf(fh,"%d %1[:]", &v.Length, &pad) != 2)
        return -1;
    v.value = malloc(v.Length * sizeof(double));
    for (i = 0; i < v.Length; i++) {
        if (fscanf(fh, "%lf", &v.value[i]) != 1)
            return -1;
    }
    return 0;
}
int扫描向量(文件*fh)
{
炭垫[2];
int i;
如果(fscanf(fh,“%d%1[:]”,&v.Length,&pad)!=2)
返回-1;
v、 值=malloc(v.Length*sizeof(double));
对于(i=0;i
这将尝试使用scanf读取向量,如果出现问题,将返回-1错误代码


如果你想做比这更复杂的事情,至少最好使用flex(如果不是bison的话)。

这里有一个版本,它不需要向量的大小作为文件的第一个条目:

7 : 1 3 6 8 -9 .123 1.1
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#define LINE_MAX 256
#define VECTOR_SIZE_MAX 32

struct vector
{
    size_t size;
    double *values;
};

// returns 1 on error
_Bool scan_vector(FILE *file, struct vector *v)
{
    char buffer[LINE_MAX];
    if(!fgets(buffer, sizeof(buffer), file))
        return 1;

    double values[VECTOR_SIZE_MAX];

    size_t size = 0;
    errno = 0;

    for(char *head = buffer, *tail = NULL;; ++size, head = tail)
    {
        while(isspace(*head)) ++head;
        if(!*head) break;

        if(size >= VECTOR_SIZE_MAX)
            return 1;

        values[size] = strtod(head, &tail);
        if(errno || head == tail)
            return 1;
    }

    v->size = size;
    v->values = malloc(sizeof(double) * size);
    if(!v->values) return 1;

    memcpy(v->values, values, sizeof(double) * size);

    return 0;
}

int main(void)
{
    struct vector v;
    while(!scan_vector(stdin, &v))
    {
        printf("value count: %u\n", (unsigned)v.size);
        free(v.values);
    }

    return 0;
}
#包括
#包括
#包括
#包括
#定义行_MAX 256
#定义向量大小最大32
结构向量
{
大小;
双*值;
};
//错误时返回1
_布尔扫描向量(文件*FILE,结构向量*v)
{
字符缓冲区[LINE_MAX];
如果(!fgets(缓冲区、sizeof(缓冲区)、文件))
返回1;
双值[VECTOR_SIZE_MAX];
大小\u t大小=0;
errno=0;
对于(char*head=buffer,*tail=NULL;;++size,head=tail)
{
while(isspace(*head))++head;
如果(!*头)断裂;
如果(大小>=向量大小最大值)
返回1;
值[大小]=strtod(头部和尾部);
if(errno | | head==tail)
返回1;
}
v->size=size;
v->values=malloc(sizeof(double)*大小);
如果(!v->values)返回1;
memcpy(v->values,values,sizeof(double)*size);
返回0;
}
内部主(空)
{
str