0

コードで何らかのコンパイラ/リンカー エラーが発生しています。おそらくプリプロセッサに関連しています。エラー メッセージには、「x の複数の定義」と表示されます。ここで、x は、lib.c ファイル内の 4 つの関数のいずれかです。私が使用しているコンパイラ/リンカーは、code:blocks でパッケージ化された GNU GCC コンパイラです。

私は #include の順序を変更しようとしましたが、成功しませんでした。これがコンパイラ エラーではなくリンカー エラーであると私が信じるに至ったのは、意図的な構文エラーを犯した場合、コンパイラがそれを検出し、エラーメッセージを表示せずに中止します。

すべてのヘルプ/アドバイス/批判を歓迎します。事前に感謝します!

main.c ファイルは次のとおりです。

#include <stdlib.h>
#include "lib.c"

int main()
{
getGradeAverage();
return EXIT_SUCCESS;
}

そして lib.c:

#include "defs.h"

void getUserName ()
{
printf ("please enter the your name:");
studentRecord sr;
scanf("%40[^\n]%*c",&sr.studentName);
}

void getCourse (index)
{
printf("please enter the name of course 1:");
courseRecord cr1;
scanf("%40[^\n]%*c",&cr1.courseName);
do{
    printf("please enter a grade for course 1:");
        if ((scanf("%i",&cr1.grade))>-2)
        {
            printf("the grade you entered is not on the scale. please try again:");
            fflush(stdin);
            continue;
        }
    } while(true);
printf("please enter the name of course 2:");
courseRecord cr2;
scanf("%40[^\n]%*c",&cr2.courseName);
    do{
    printf("please enter a grade for course 1:");
        if ((scanf("%i",&cr2.grade))>-2)
        {
            printf("the grade you entered is not on the scale. please try again:");
            fflush(stdin);
            continue;
        }
    } while(true);

}

void GPAPrint ()
{
    int GPA;
    studentRecord sr;
    courseRecord cr1;
    courseRecord cr2;
    printf("Student name: %s\n",&sr.studentName);

}

void getGradeAverage ()
{
    int index=1;
    getUserName();
    getCourse(index);
    GPAPrint();
    return (0);

}

#includes と構造体のほとんどが含まれているため、defs.h ファイルもここに関連しています。

#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <math.h>
#include <string.h>
#define MAX_LENGTH 40

typedef struct courseRecord
{
char courseName [MAX_LENGTH+1];
int grade;
}courseRecord;

typedef struct studentRecord
{
char studentName [MAX_LENGTH+1];
char courseName[2];
}studentRecord;
4

1 に答える 1

1

おそらく、lib.cビルドにインクルードし#includemain.c. これにより、コンパイルされたオブジェクト (たとえば、lib.oおよびmain.o) がそれぞれ関数の定義を持つようになります。リンカーはこれを検出し (すべてのオブジェクト ファイルを調べますが、コンパイラは一度に 1 つずつ生成するため、2 つ以上のオブジェクト ファイルが何かを複数回定義しているインスタンスを検出できないため)、複数の定義について文句を言います。

ガイドラインとして、決してファイルでは#includeありません。.c

代わりに、関数の宣言 (別名プロトタイプ) をヘッダー ファイル (たとえばlib.h)に配置します。

 #ifndef LIB_H_INCLUDED
 #define LIB_H_INCLUDED

 #include "defs.h"

 void getUserName();
 void getCourse (index);

  // etc

 #endif

そして、関数を使用する必要が#includeあるすべての.cファイルにあります。これにより、関数が正しく呼び出されているかどうかをコンパイラが確認できるように、十分な情報が提供されます。次に、関数定義 (別名その実装) を に配置しlib.cます。 lib.cも必要になる#include "lib.h"ため、(とりわけ) コンパイラは、ヘッダーからの関数の宣言が定義と一致するかどうかを確認できます。

また、ヘッダーにインクルード ガードを配置しました。グーグルで理由を調べるための演習として残しておきます。

于 2016-11-12T20:34:12.827 に答える