动态数组C不适用于所有输入

时间:2012-08-11 19:45:32

标签: c dynamic-arrays

我正在尝试进行矩阵链乘法,我需要从C

中的文件中获取输入

对于一个测试用例,它适用于其他运行失败

testcase#1(这很好)

3 5
5 7
7 9
9 6
6 7
7 9

testcase#2(这使matrix.exe停止工作)

30 35
35 15
15 5
5 10
10 20
20 25

注意:在测试用例中,连续数字是矩阵的行和列

这是我正在使用的代码

int *p,i=0;
char str[3],*extra;
FILE * file;
file = fopen("D:/Dump/testcases/matrix.txt", "r");
if (file) {
    while (fscanf(file, "%s", str)!=EOF){
        switch(i){
            case 0:     p=(int *)malloc(sizeof(int));
                        *(p)=atoi(str);
                        break;
            default:    *(p+i)=(int)malloc(sizeof(int));
                        *(p+i)=atoi(str);
                        break;
        }
        i++;
    }
}

1 个答案:

答案 0 :(得分:2)

这么多问题和误解;很难提供有用的建议。

据我所知,你的意思是要读取每行输入两个数字的一​​系列矩阵的维数,第N行的第二个数字应该与第N + 1行的第一个数字相同。在您到达EOF之前,您不知道会有多少行输入。通常,数字应该都是一位或两位数(不再是)。数组的实际数据存储在别处或生成 - 在此代码中不处理。

您的代码是:

int *p,i=0;
char str[3],*extra;
FILE * file;
file = fopen("D:/Dump/testcases/matrix.txt", "r");
if (file) {
    while (fscanf(file, "%s", str)!=EOF){
        switch(i){
            case 0:     p=(int *)malloc(sizeof(int));
                        *(p)=atoi(str);
                        break;
            default:    *(p+i)=(int)malloc(sizeof(int));
                        *(p+i)=atoi(str);
                        break;
        }
        i++;
    }
}
  • 文件打开正常;你没有表明结束,但这是一个小问题。
  • 您不限制读取的字符串的大小;您可以使用%2s来确保不会溢出您使用的(相当短的)字符串。
  • 您不检查fscanf()实际上是否读过1项。使用字符串,没关系。如果你直接读整数,那就不行了。你可以得到0整数转换,既不是EOF也不是1.你应该使用while (fscanf(file, "%2s", str) == 1)
  • 没有非常明显的理由不让fscanf()为您进行转换。
  • OTOH,你不能强迫fscanf()在一行上要求两个数字(仅限);它会很乐意将所有数字放在一行,或者每行都有一个数字,每行包含数字之间有2个空行。
  • switch有点奇怪。 default子句可能应该使用realloc()而不是malloc(),而default中的强制转换则存在严重问题。作为一个整体的内存分配方案是非常有缺陷的,你知道,因为你问了这个问题。你可以通过写下来拯救它:

    default:
        p = (int *)realloc(p, (i+1) * sizeof(int));
        p[i] = atoi(str);  /* Or *(p+i) if you prefer */
        break;
    

总的来说,我认为你需要考虑一次读取一行(fgets()),然后用sscanf()解析这些行。您应该考虑一次分配数组两个整数。

int  *p = 0;
int   i = 0;
FILE *file = fopen("D:/Dump/testcases/matrix.txt", "r");

if (file != 0)
{
    char buffer[4096];
    while (fgets(buffer, sizeof(buffer), file) != 0)
    {
        int d1, d2;
        char c;
        if (sscanf(buffer, "%d%d%c", &d1, &d2, &c) != 3 || c != '\n')
        {
            fprintf(stderr, "Badly formatted line: %s", buffer);
            break;
        }
        void *space;
        if (i == 0)
            space = malloc(2 * (i + 1) * sizeof(int));
        else
            space = realloc(p, 2 * (i + 1) * sizeof(int));
        if (space == 0)
        {
            fprintf(stderr, "Memory allocation failed (%d bytes)\n", 2 * (i + 1) * sizeof(int));
            break;
        }
        p = (int *)space;
        p[2*i + 0] = d1;
        p[2*i + 1] = d2;
        i++;
    }
    fclose(file);
}

/* i is the number of lines read (sets of matrix dimensions) */
/* p is the pointer to 2*i array dimensions */
/* ...Use i and p... */
free(p);

代码不会检查一行上的第二个维度是否与下一行的第一个维度相同。它不检查1或2位数的正整数(基本上是1..99);它允许更大的值,零和负值。 (测试c == '\n'确保在第二个数字后面有换行符;不允许尾随空格等。)

鉴于p(现在)已初始化为0(空指针),您可以不使用malloc()而只是无条件地使用realloc()。大多数人不喜欢这样做,但它避免重复。