0

これは私が苦労している宿題の小さな部分です。関数にはこの部分よりも多くのものがありますが、これが私が苦労しているすべてです(後でもっとあります)。これを実行すると、整数ファイルの読み取りに失敗したことがわかります。どこが間違っていたのか、どこから調べ始めるべきか誰か教えてもらえますか?

int * readIntegers(const char * filename, int * numberOfIntegers)
{

  FILE* fp = fopen(filename, "r");  
 int count = 0;
// int array;
 if(fp== NULL)
   {
     return NULL;
   }
 while(fscanf(fp, "%d", &count)>0)
   {
     (*numberOfIntegers)++;
   }
 printf("%d\n",*numberOfIntegers); 

コンパイラの警告、私が投稿したこととは関係がないので、私はこれらについて心配していません

warning: return from incompatible pointer type [enabled by default]
 warning: function returns address of local variable [enabled by default]
 warning: unused variable ‘array’ [-Wunused-variable]

そして、実行すると、これが得られます...

./pa03 inputs/input0 > outputs/output0    ./pa03 inputs/input0 > outputs/output0
Failed to read integer-file 'inputs/input0', aborting
cat outputs/output0
Failed to read integer-file 'inputs/input0', aborting
cat outputs/output0

また、最後にある print ステートメントは診断用でした。関数の後半で、答えを表示する配列を返します。numberOfInputs が正しい数に更新されたかどうかを確認しようとしていましたが、これは今のところ発生していません。印刷ステートメントを更新して、機能するかどうかを確認します...更新します。

これが現在のログ全体です。

gcc -g -Wall -Wshadow -c -o obj/answer03.o answer03.c answer03.c: 関数 'readIntegers' 内: answer03.c:85:2: 警告: 互換性のないポインター型からの戻り [デフォルトで有効] answer03 .c:85:2: 警告: 関数はローカル変数のアドレスを返します [デフォルトで有効] answer03.c:68:6: 警告: 未使用の変数 'array' [-Wunused-variable] gcc -g -Wall -Wshadow -c -o obj/pa03.o pa03.c gcc -g -Wall -Wshadow obj/answer03.o obj/pa03.o -o pa03

./pa03 入力/入力 0 > 出力/出力 0 * glibc が検出されました * ./pa03: munmap_chunk(): 無効なポインター: 0x00007fff9ffebad0 * ======= バックトレース: ========= /lib/x86_64- linux-gnu/libc.so.6(+0x7eb96)[0x2acd35b25b96] ./pa03[0x400c67] /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xed)[0x2acd35ac876d] ./pa03[0x400699] ======= メモリーマップ: ======== 00400000-00402000 r-xp 00000000 08:06 1443970
/home/matt/ECE264/solutions/PA03/pa03 00601000-00602000 r--p 00001000 08 :06 1443970
/ホーム/マット/ECE264/ソリューション/PA03/pa03 00602000-00603000 rw-p 00002000 08:06 1443970
/ホーム/マット/ECE264/ソリューション/PA03/pa03 0219f000-021c0000 rw-0 0ヒープ] 2acd35882000-2acd358a4000 r-xp 00000000 08:06 8130309
/lib/x86_64-linux-gnu/ld-2.15.so 2acd358a4000-2acd358a9000 rw-p 00000000 00:00 0 2acd35aa4000-2acd35aa5000 r--p 00022000 08:06 8130309 /lib/x86-gnu.15. So 2ACD35AA5000-ACD35AA7000 RW-P 00023000 08:06 8130309
/LIB/X86_64-LINUX-GNU/LD-2.15.SO 2ACD35AA7000-ACD35C5C5C5C000 R-XP 0000000008:068127294-LIB-LIB-
CMU。そう 2acd35c5c000-2acd35e5b000 ---p 001b5000 08:06 8127294
/lib/x86_64-linux-gnu/libc-2.15.so 2acd35e5b000-2acd35e5f000 r--p 001b4000 08:06 81272864 /4
/lib-clib-nug_6 2.15.so 2acd35e5f000-2acd35e61000 rw-p 001b8000 08:06 8127294
/lib/x86_64-linux-gnu/libc-2.15.so 2acd35e61000-2acd35e68000 rw-p 00000000 00:00 0 2acd35e68000-2acd35e7d000 r-xp 00000000 08:06 8130119 /lib/x86_lib/x1c-nugs.6socc-nugs.6 2acd35e7d000-2acd3607c000 ---p 00015000 08:06 8130119
/lib/x86_64-linux-gnu/libgcc_s.so.1 2acd3607c000-2acd3607d000 r--p 00014000 08:06 8130119/
lib. .1 2ACD3607D000-2ACD3607E000 RW-P 00015000 08:06 8130119
/LIB/x86_64-linux-gnu/libgcc_s.so.1 7fffcd000-7fff9ffeee000 rw-p 000000:00 00 0
[vdso] ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0
[vsyscall] ./bin/test.sh: 20 行目: 8797 中止 (コア ダンプ) ./$EXEC $INF > $OUTF cat outputs/output0

5 ソートされていない配列: 35254288 0 194 5 -1610695872 ソートされた配列: 35254289 5 -1610695984 1 -1610695872 -- 失敗 (ソートされていません)。整数 '35254288' が見つかりません -- 失敗。整数 '35254289' が見つかりません -- 失敗。

期待される出力を確認しています: expected/expected0 - FAIL。期待される:

並べ替えられていない配列: 4 1 3 2 5 並べ替えられた配列: 1 2 3 4 5 -- 正しい。ソートされた配列の 3 番目の位置にある整数「4」 -- 合格。ソートされた配列の 4 番目の位置にある整数 '5' -- 合格。

make: * [test0] エラー 1

テストケース: 4 1 3 2 5

4

1 に答える 1

2

このprintf("%n", numberOfIntegers)呼び出しは、 が指す整数にゼロを書き込みますnumberOfIntegers。これは、%nフォーマットが解釈される前にゼロ文字が書き込まれるためです ( の仕様を参照してくださいprintf())。

おそらく、あなたは次のものを使いたいと思っていました:

printf("%d\n", *numberOfIntegers);

SSCCE

これは、質問に示されているコードに密接に基づいた SSCCE ( Short, Self-Contained, Correct Example ) であり、そのコードには何もひどく問題がないことを示しています。したがって、質問で発生した問題は、示す。

#include <stdio.h>

static
int *readIntegers(const char *filename, int *numberOfIntegers)
{
    FILE *fp = fopen(filename, "r");
    int count;
    if (fp == NULL)
    {
        return NULL;
    }
    while (fscanf(fp, "%d", &count) > 0)
    {
        (*numberOfIntegers)++;
    }
    printf("%d\n", *numberOfIntegers);
    fclose(fp);
    return numberOfIntegers;
}

int main(int argc, char **argv)
{
    const char *file = "data";
    int num = 0;
    int *p;
    if (argc > 1)
        file = argv[1];
    p = readIntegers(file, &num);
    if (p != &num)
    {
        fprintf(stderr, "Failed to read numbers from file %s\n", file);
        return 1;
    }
    else
        printf("Number of numbers in file %s is %d\n", file, num);
    return 0;
}

data以下を含むという名前のファイルがあるとします。

0 1 2 3 4 5 6 7 8 9 10

または、各空白を改行に置き換えた同等のファイルの場合、プログラムの出力は次のようになります。

11
Number of numbers in file data is 11

プログラムが呼び出された場合ri( Read Integers )、次のように呼び出されます。

$ ./ri missing
Failed to read numbers from file missing
$

どちらの場合もクラッシュしません。ファイルを閉じて入力ポインタを返すコードを追加しました。このコードは、GCC 4.8.1 を使用して Mac OS X 10.8.4 でクリーンにコンパイルされます。コマンド ラインは非常に厳密に設定されています。

$ gcc -O3 -g -std=c11 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes \
>     -Wold-style-definition ri.c -o ri
$

したがって、前述のように、問題は精査のために提示されたコード フラグメントに直接あるわけではありません。

あなたが無視しているコンパイラの警告は、表示されたコードが正常に実行された後に明らかになる問題を正確に示しているため、私は本当に心配しています. ローカル変数へのポインターを返すことは、プログラムをクラッシュさせる方法です。関数から間違った型のポインターを返すことは、プログラムをクラッシュさせる方法です。(使用されていない変数の警告は、彼らが得るのと同じくらい無害であることを認めます — 宣言をコメントアウトすることで、それが表示されないようにしましたが、私はそれについて心配していません.)

したがって、誰でも問題をうまく診断できるように、より多くのプログラムを提示する必要があります。あなたが示すのはOKコードです。

于 2013-09-10T23:03:03.780 に答える