プロが教えるわが家の防犯対策術!

分割ファイルで構造体を使うにはヘッダファイルに書くと思うのですがどうやって書けばいいのでしょうか?
charやintはexternでできるのですが・・・
例で教えてくださいm(__)m

A 回答 (4件)

ちなみに、構造体へのポインタの宣言であれば、単に



extern struct A *a;

とするだけで済みます。
ただし、構造体の中身にアクセスするのであれば、完全な構造体の定義が必要になります。
    • good
    • 0
この回答へのお礼

回答ありがとうございます。
ポインタの宣言ではないのです><

今、main.c、sansho.c、touroku.c、sansho.h、touroku.hというのがあるんです。
で、main.cにはsansho.h、touroku.hをインクルードしていて、sansho.cにはsansho.h、touroku.cにはtouroku.hをインクルードしています。
で、main.cにはsansho.cなども分割ファイルでリンク?みたいになっているので構造体の宣言が重複してるみたいなエラーが出ちゃうんです><

お礼日時:2006/06/18 23:00

まず、char や int は extern できているということで。



char や int はC言語が持っている型なので、

extern char hoge;

とすると、コンパイラには理解できます。
しかし、構造体の場合は、どういう構造なのか、コンパイラに教えてあげないと、コンパイラが理解できないというのが、答えになります。

ですから、ヘッダファイルで、

struct hogeType{
int a;
int b:
char c[100];
};

などと書くことで、(この場合は)hogeType という構造体を定義したことと、その具体的な構造をコンパイラに伝えます。(もちろん、hogeType でなくても、わかりやすい名前で)

これで、コンパイラが、struct hogeType という型を理解したと考えておおむねOKです。

あとは、この構造体を使うところで、このヘッダファイルを include すれば、他の char や int と同じように、 struct hogeType を使うことができます。

struct hogeType hoge; // 実体の定義
extern struct hogeType hoge; // 外部定義の参照

struct hogeType func(struct hogeType a);
// 構造体を引数にして、構造体を返す関数

などなど。

あと、struct hogeType というのを、簡略化して、struct なしですませようとする場合には、typedef を使います。
C++では、(typedef しなくても)struct 無しでもOKです。
    • good
    • 0

申し訳ない。

C言語でしたね。
先の例は、下記の *何れか* に変更してもらわないと、コンパイルできないと思います。
--
変更パターン(1):
a.c, b.c の
 X_t x;

 struct X_t x;
に変更
--
変更パターン(2):
x.h の
struct X_t {...};

typedef struct {...} X_t;
に変更
    • good
    • 0

構造体も extern 出来ますよ(正確には、構造体の実体も char や int (の実体)と同様に extern 出来ます)。


## 構造体を定義することと、extern を記述することは事は次元の異なることです。

例ですが、
== x.h
struct X_t
{
 int a;
 char b;
};
== a.c
#include "x.h"
void foo()
{
 X_t x;
  : (処理)
}
== b.c
#include "x.h"
void bar()
{
 X_t x;
  : (処理)
}
--
って感じでしょうか??
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています

このQ&Aと関連する良く見られている質問

Q構造体のextern方法

C++のビギナーなのですが、
普通の変数、配列のexternはできているのですが、
構造体をexternができずに困っています。

2時間ほど調べまわったのですが、
typedefを使わなければならない(?) とか
構造体は変数なんかと違い、特別なやり方をしないとダメらしい事までは解ったのですが、
実際動くやり方を見つけきれませんでした;

方法(手順)や、解説サイトなどをご存知でしたら、教えて頂けると幸いです。

Aベストアンサー

まさか, 「実体を定義していない」というオチはないよなぁ....

Q ポインタを使って関数の値のやり取り

c言語の問題なのですが、2つの異なる1次元配列の積をseki関数を使って計算してもうひとつの配列に入れてmain関数で表示するのですが、うまく走りません原因がわかる人がいた教えてください。
作った実行文は、
#include<stdio.h>
int seki(int *pa,int *pb,int *pc);
main(){
int a[]={5,2,3,5,3,2,4,8,9,9,7},b[]={4,3,8,4,6,2,8,9,1,6,4},c[11]={0};
int i,*pa,*pb,*pc;

pa=&a;
pb=&b;
pc=&c;

seki(pa,pb,pc);
for(i=0;i<11;i++)
printf("%d,",*(pc+i));

}
int seki(int *pa,int *pb,int *pc){
int j;
for(j=0;j<11;j++)
*(pc+j)=*(pa+j) * *(pb+j);
}
こんな表示が出てきます。
toi2.c: In function `main':
toi2.c:7: warning: assignment from incompatible pointer type
toi2.c:8: warning: assignment from incompatible pointer type
toi2.c:9: warning: assignment from incompatible pointer type
たぶんmain関数内で書いたseki関数の引数の型に問題があると思うのですが。

c言語の問題なのですが、2つの異なる1次元配列の積をseki関数を使って計算してもうひとつの配列に入れてmain関数で表示するのですが、うまく走りません原因がわかる人がいた教えてください。
作った実行文は、
#include<stdio.h>
int seki(int *pa,int *pb,int *pc);
main(){
int a[]={5,2,3,5,3,2,4,8,9,9,7},b[]={4,3,8,4,6,2,8,9,1,6,4},c[11]={0};
int i,*pa,*pb,*pc;

pa=&a;
pb=&b;
pc=&c;

seki(pa,pb,pc);
for(i=0;i<11;i++)
printf("%d,",*(pc+i));

}
int seki(int *pa,int *pb,i...続きを読む

Aベストアンサー

質問の下に書かれているコンパイルエラーと思われる表示から
そのエラーの原因が読み取ることが出来ます。
ここでの原因は、プログラム中次の3行がエラーであると指摘されています。
7行目:pa=&a;
8行目:pb=&b;
9行目:pc=&c;
それぞれ、どういう状況かというと、
エラーをそのまま訳せば
『ポインタとしての割り当て方がおかしいですよ』
という風に捉えられます。
まず、整数型配列として宣言してあるaという変数があります。
これは、これ自身がポインタであるので
&aという表記では、『ポインタ変数aのポインタ』ということになり、
純粋なポインタ変数paには代入する事ができません。
よって、上のエラーを解消するには、
pa = a;
とすればよいでしょう。
(8,9行目も同様)

Qfscanf関数について

--------------------------------------------------
#include<stdio.h>
#include<stdlib.h>
int main()
{
FILE*fp;
int ch,dt;
char ss[80];

if((fp=fopen("bbb.txt","w"))==NULL){
printf("出力ファイルをオープンできません.\n");
exit(1);
}

fprintf(fp,"%c",'A');
fprintf(fp,"%s\n","abcdeABCDE");
fprintf(fp,"%d\n",1234);
fclose(fp);

if((fp=fopen("bbb.txt","r"))==NULL){
printf("入力ファイルをオープンできません.\n");
exit(1);
}

ch=fgetc(fp);
printf("ch=%c\n",ch);

fscanf(fp,"%s",ss);
printf("ss=%s\n",ss);

fscanf(fp,"%d",&dt);
printf("dt=%d\n",dt);

fclose(fp);

return 0;
}
--------------------------------------------------

以上のプログラムで、プログラムの通り「bbb.txt」は、

AabcdeABCDE
1234

となっております。
そこで疑問なのですが、「ch=fgetc(fp);」は1文字読み込みなので、'A'だけと分かるのですが、「fscanf(fp,"%s",ss);」はfpからの読み込みで何故、

AabcdeABCDE
1234

の全部を読み込まず、'A'を抜かした、「abcdeABCDE」だけを読み込んでくれるのか?
後、「fscanf(fp,"%d",&dt);」は何故「AabcdeABCDE」を抜かした、「1234」だけを読み込んでくれるのかが分かりません。
「fscanf(fp,"%d",&dt);」については数値だけを読み込んでくれるのかと思い、

ch=fgetc(fp);
printf("ch=%c\n",ch);

fscanf(fp,"%s",ss);
printf("ss=%s\n",ss);

の部分を無くせば、「1234」だけを読み込んでくれるのかと思ったのですが、数値は正しく表示されません。

以上教えていただければ嬉しいです。

--------------------------------------------------
#include<stdio.h>
#include<stdlib.h>
int main()
{
FILE*fp;
int ch,dt;
char ss[80];

if((fp=fopen("bbb.txt","w"))==NULL){
printf("出力ファイルをオープンできません.\n");
exit(1);
}

fprintf(fp,"%c",'A');
fprintf(fp,"%s\n","abcdeABCDE");
fprintf(fp,"%d\n",1234);
fclose(fp);

if((fp=fopen("bbb.txt","r"))==NULL){
printf("入力ファイルをオープンできません.\n");
exit(1);
}

ch=fgetc(fp);
printf("ch=%c\n",c...続きを読む

Aベストアンサー

>%dは空白分を読み飛ばすとわかったのですが、以上のプログラムでも正常に動いたので、「%s」も空白文を読み飛ばしてくれるのですかね?

話が逆。

「空白(改行も含む)が読めるのは、%cだけ」ってのが本質。

「%cだけは、空白(改行も含む)の読み飛ばしをせず、今読める文字を1文字読むだけ」になっているのです。

今読める文字が空白だろうが改行だろうが1だろうがAだろうが、とにかく1文字読むだけです。

「%c」以外の「%d」や「%s」や「%何とか」は「まず、空白(改行も含む)を読み飛ばし、空白(改行も含む)以外の何かが出て来たら、読み込みを開始」します。そして「読み込めない文字(空白や改行も)が出て来たら、そこでヤメ」にします。

まとめると

・%cは、とにかく1文字読む。読み飛ばしとかはしない。

・%c以外は、とにかく、空白と改行を読み飛ばしてから読み込みを開始し、空白や改行が出て来たら読み込みをヤメる。

scanf(やfscanf)は「上記の2点がすべて」です。

「%dは~」とか「%sは~」とか、書式指定子個別に悩んではいけません。本質を把握すれば「みんな一緒」で、悩む必要はありません。

>%dは空白分を読み飛ばすとわかったのですが、以上のプログラムでも正常に動いたので、「%s」も空白文を読み飛ばしてくれるのですかね?

話が逆。

「空白(改行も含む)が読めるのは、%cだけ」ってのが本質。

「%cだけは、空白(改行も含む)の読み飛ばしをせず、今読める文字を1文字読むだけ」になっているのです。

今読める文字が空白だろうが改行だろうが1だろうがAだろうが、とにかく1文字読むだけです。

「%c」以外の「%d」や「%s」や「%何とか」は「まず、空白(改行も含む)を読み飛ばし...続きを読む

Q別ファイルの構造体の値を読み込む、変えるには?2

以前質問の内容がたらずにもう一度同じ質問をすることをお許しください。

AとBのファイルに同じ構造体のデーターを読み込んだとして、どのように書けば構造体のデーターをファイルAで変えたものをBのファイルからも値が変わっていたり、Bのファイルで変えた値をAのファイルで読み込んだり、することができますか?


static struct{
char *name[2];
double d_data[2];
int i_data[4];
double s_data[2];
int state[2][3];
int regi[5];
}kya_data[2]={ {
  { "奈美" , "爆弾" },
  {
   43.0000 ,
   54.0000 ,
  } , {
   50 , 50 , 50 , 50
  } , {
   0.100,
   0.100,
  } , {
  { 0 , 0 , 0 } ,
  { 0 , 0 , 0 }
  } , {
   100 , 0 , 0 , 0 , 0
  } },{
  { "由美" , "湖" },
  {
   23.0000 ,
   76.0000 ,
  } , {
   50 , 50 , 50 , 50
  } , {
   0.100,
   0.100,
  } , {
  { 0 , 0 , 0 } ,
  { 0 , 0 , 0 }
  } , {
   0 , 0 , 0 , 0 , 100
  } }
};

以前質問の内容がたらずにもう一度同じ質問をすることをお許しください。

AとBのファイルに同じ構造体のデーターを読み込んだとして、どのように書けば構造体のデーターをファイルAで変えたものをBのファイルからも値が変わっていたり、Bのファイルで変えた値をAのファイルで読み込んだり、することができますか?


static struct{
char *name[2];
double d_data[2];
int i_data[4];
double s_data[2];
int state[2][3];
int regi[5];
}kya_data[2]={ {
  { "奈美" , "爆弾" },
  {
   43.0000 ,
   ...続きを読む

Aベストアンサー

「ファイル」がソースファイルの意味だとして、
・構造体の宣言をヘッダファイルに書く。
・そのヘッダを構造体を読み書きするソースにインクルードする。
・ソースファイルA,Bのどれかに構造体を定義、初期化する。

例えば下のような3つのファイルに分割してコンパイルすればよいでしょう。
(それと char *name[2]; では2つの文字列ではなく、ポインタの配列になってしまいますよ)

/* --- ヘッダファイル (KyaData.h) --- */

struct KyaData { /* KyaData構造体の宣言 */
 char name[2][16];
 double d_data[2];
 int i_data[4];
 double s_data[2];
 int state[2][3];
 int regi[5];
};

/* kya_data配列のextern宣言 */
extern struct KyaData kya_data[2];

/* 関数overwriteのextern宣言 */
extern void overwrite(void);


/* --- ソースファイルA --- */

#include <stdio.h>
#include "KyaData.h" /* ヘッダファイルのインクルード */

struct KyaData kya_data[2] = { /* kya_data配列の定義 */
 {
  { "奈美", "爆弾" },
  { 43.0000, 54.0000 },
  { 50, 50, 50, 50 },
  { 0.100, 0.100 },
  { { 0, 0, 0 } , { 0, 0, 0 } },
  { 100, 0, 0, 0, 0 }
 },
 {
  { "由美", "湖" },
  { 23.0000, 76.0000 },
  { 50, 50, 50, 50 },
  { 0.100, 0.100 },
  { { 0, 0, 0 }, { 0, 0, 0 } },
  { 0, 0, 0, 0, 100 }
 }
};

int main(void)
{
 printf("%s, %f\n", kya_data[0].name[0], kya_data[0].d_data[0]);
 overwrite(); /* kya_data配列の中身を変更 */
 printf("%s, %f\n", kya_data[0].name[0], kya_data[0].d_data[0]);
 return 0;
}


/* --- ソースファイルB --- */

#include "KyaData.h" /* ヘッダファイルのインクルード */

void overwrite(void) /* 関数overwriteの定義 */
{
 kya_data[0].d_data[0] = 11.5;
}

「ファイル」がソースファイルの意味だとして、
・構造体の宣言をヘッダファイルに書く。
・そのヘッダを構造体を読み書きするソースにインクルードする。
・ソースファイルA,Bのどれかに構造体を定義、初期化する。

例えば下のような3つのファイルに分割してコンパイルすればよいでしょう。
(それと char *name[2]; では2つの文字列ではなく、ポインタの配列になってしまいますよ)

/* --- ヘッダファイル (KyaData.h) --- */

struct KyaData { /* KyaData構造体の宣言 */
 char name[2][16];
 double d_da...続きを読む


このQ&Aを見た人がよく見るQ&A

人気Q&Aランキング