我想从白色空格分隔的文本文件中扫描形成矢量的变量,而绊脚石(通常对我而言)缺乏优雅。
目前我的扫描代码要求将矢量大小描述为文件中的第一个元素:
7 : 1 3 6 8 -9 .123 1.1
这让我感到困扰,因为'7'可以通过检查空白来确定。
我尝试了各种形式的fscanf(),strtok()等,但似乎都是野蛮的。如果不诉诸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 */
}
}
解决方案: 感谢经过检查的答案,我实施了:
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() */
答案 0 :(得分:1)
有什么问题:
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;
}
尝试使用scanf读取向量,如果出现问题则返回-1错误代码。
如果你想做一些比这更复杂的事情,你最好至少使用flex(如果不是野牛)。
答案 1 :(得分:0)
如果您使用realloc()
,如果您使用初始malloc()
分配不足,则可以随时要求更多内存。一个常见的策略是分配任意n
个项目。每当你耗尽空间时,你加倍n
并调整缓冲区大小。
或者,您可以使用链接列表而不是数组。链接列表处理插入和追加比数组更好,但您放弃了按索引访问项目的功能。
答案 2 :(得分:0)
你的载体有多大? 一种方法是,
就像你观察到的那样,维度'7'
不一定是输入的一部分
您只需要一个足够大的本地缓冲区,以获得最长的线路
并且,对它进行了一些错误处理:-)
答案 3 :(得分:0)
这是一个不需要矢量大小作为文件中第一个条目的版本:
#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;
}
最大行数和条目数是出于性能原因和懒惰而修复的。