【问题标题】:validating content of input file验证输入文件的内容
【发布时间】:2012-02-20 21:11:29
【问题描述】:

我有这个防御性编程问题,我真的不知道如何解决。

我有这个函数,它将文件路径和表的大小(行/列计数)作为参数,我正在寻找更好的方法来验证输入文件。我假设这个函数的参数总是正确的。 size 表示存储在文件中的表的“较小的一侧”:

例如:

1 2 3 4 
5 6 7 8 

大小 = 2 是正确的,而

1 2 3 4 5
5 6 7 8 9

大小 = 2 不正确

我也希望能够拒绝这样的文件

1 2 3 4 5 6 7 8

size = 2(通过 fscanf 接受)

我希望能够拒绝的另一种文件类型是

1 2 3
4 5 6

大小 = 2

目前我唯一的安全措施是检查文件的元素是否真的是数字。

这是我到目前为止所做的代码:

void import(float** table, int size, char* path)
{
    FILE* data = fopen(path, "r");
    assert(data);
    int i,j;
    int st;

    for (i=0; i<size; i++)
    {
        for(j=0; j<(size*2)-1; j++)
        {
            st = fscanf(data, "%f", &table[i][j]);
            if (!st)
            {
                printf("Error while importing the file.\n");
                fclose(data);
                return -1;
            }
        }
    }
    fclose(data);
}

我真的不知道从哪里开始以及如何开始,我不是很精通 C,似乎存在很多功能和机制来做我想做的事,但它们看起来都非常复杂,有些实际上比我提供的代码。

如果有人能指出我正确的方向,那就太好了。

【问题讨论】:

  • "number = 2"是什么意思?
  • 我想我不明白正确的文件是什么样的。我只能看到2 永远是对的。
  • @LihO 输入的数字,就是代码里的大小
  • 这绝对是assert的错误使用方式。 assert 不是用于错误检查,而是用于逻辑一致性。换句话说,你可以这样写: data = open( ... ); if( data == NULL ) { ... } assert( data != NULL );,但是打开后调用 assert 是无效的错误检查。
  • @Sword22 你被告知错了。你应该经常检查你的 malloc 和你的文件打开,但你不应该用 assert 这样做。断言用于说明逻辑必要性或参数假设。 (例如, int foo( int *x ) { assert( x ) ... } 说明 foo 不能用 NULL 指针调用。)

标签: c file input defensive-programming


【解决方案1】:

您的 for 循环可能如下所示:

char line[1000], *token;
for (i = 0; i < size; i++) // for each line
{
    if (fgets(line, 1000, data) != NULL) // read line
    {
        token = strtok (line," ");
        for (j = 0; j < (size * 2) - 1; j++) // for each number from line
        {
            if (sscanf(token, "%f", &table[i][j]) <= 0)
            {
                // there are columns missing:
                printf("Error while importing the file.\n");
                fclose(data);
                return -1;
            }
            token = strtok (NULL," ");
        }
    }
    else
    {
        // there are rows missing:
        printf("Error while importing the file.\n");
        fclose(data);
        return -1;
    }
}

另请注意,assert(data); 应替换为以下内容:

if (!data)
{
    printf("Error while openning the file [filePath=\"%s\"].\n", filePath);
    cleanExit();
}

【讨论】:

  • @Sword22:对不起,我有一个错误。您不能直接从line 读取此输入,您必须将其拆分为令牌。现在检查我的答案。
【解决方案2】:

您无法轻易检测到 scanf() 中的行尾,因此直接使用它不符合您的标准。

您可能需要阅读整行(fgets()getline()),然后依次处理每一行。行处理可以使用sscanf(),也可以使用%n指令。概括地说,这归结为:

for (line_num = 0; line_num < size; line_num++)
{
    ...read line from file into buffer line, checking for EOF...
    start = line;
    for (i = 0; i < 2 * size; i++)
    {
        if (sscanf(start, "%f%n", &value, &offset) != 1)
            ...ooops - short line or non-numeric data...
        else
        {
            start += offset;
            table[line_num][i] = value;
        }
    }
}
...check that there's no clutter after the last expected line...

【讨论】:

    【解决方案3】:

    您还可以计算整个文件的校验和。问题是你对此有多认真。创建一个异或校验和很容易,但它对碰撞并不安全。如果重要的话,最好的可能是使用类似 sha-1 的东西。

    【讨论】:

      猜你喜欢
      • 2014-10-08
      • 2020-09-25
      • 2011-02-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-05-16
      • 1970-01-01
      相关资源
      最近更新 更多