1

行列連鎖乗算を実行しようとしていますが、C のファイルから入力を取得する必要があります

1 つのテスト ケースでは問題なく動作しますが、他の実行では失敗します

テストケース #1 (これは正常に動作します)

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

テストケース #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++;
    }
}
4

1 に答える 1

2

非常に多くの問題と誤解。有益なアドバイスを提供することは困難です。

私が理解しているように、入力行ごとに2つの数値を持つ一連の行列の次元を読み取ることを意図しており、N行の2番目の数値はN + 1行の最初の数値と同じである必要があります。EOF に到達するまで、何行の入力があるかはわかりません。一般に、数字はすべて 1 桁または 2 桁にする必要があります (それ以上ではありません)。配列の実際のデータは別の場所に保存されるか、生成されます。このコードでは処理されません。

あなたのコードは次のとおりです。

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つのアイテムを読んだことを確認しません。文字列でOKです。整数を直接読み取っていた場合、それは問題になります。EOF でも 1 でもない 0 の整数が変換される可能性があります。使用する必要がありますwhile (fscanf(file, "%2s", str) == 1)
  • fscanf()変換を行わない明確な理由はありません。
  • fscanf()OTOH、 1行に2つの数字(のみ)を強制することもできません。すべての数字を 1 行に入れるか、数字を含む各行の間に 2 つの空白行を入れてそれぞれの数字を 1 行に並べると便利です。
  • 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()全体として、一度に 1 行ずつ読み取り ( )、次に で行を解析するという観点で考える必要があると思いますsscanf()。おそらく、一度に 2 つの整数を配列に割り当てるという観点から考える必要があります。

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);

このコードは、ある行の 2 番目の次元が次の行の最初の次元と同じかどうかをチェックしません。1 桁または 2 桁の正の整数 (基本的には 1..99) はチェックしません。より大きな値、ゼロ、および負の値を許可します。(このテストc == '\n'では、2 番目の数字の後に改行があることを確認します。末尾の空白などは許可されません。)

pそれが (現在) 0 (ヌル ポインター) に初期化されていることを考えると、 を使用せずに無条件malloc()に使用することができます。realloc()ほとんどの人はそれをしたくないのですが、繰り返しを避けることができます。

于 2012-08-11T21:10:35.230 に答える