C言語関係掲示板

過去ログ

No839 構造体のポインタ

[戻る] [ホームページ]
No.10686

構造体のポインタ
投稿者---ペペ(2003/11/19 22:00:44)


↓のプログラムのscanf部分が間違ってるようでうまくいきません。
どこをどう書けばいいのか・・・プログラミング上級者の方、教えてください。
#include<stdio.h>
struct syain{
char name[15];
int age;
int nensyu;
};
void main(void){
int i;
struct syain meibo[5];
struct syain *p;
p=&meibo[0];

for(i=0;i<5;i++){
printf("氏名 >>");
scanf("%s",p->name);
printf("年齢 >>");
scanf("%d",p->age);
printf("年収 >>");
scanf("%d",p->nensyu);
p++;
}
for(i=0;i<5;i++){
printf(" %10s | %3d | %d\n",p->name,p->age,p->nensyu);
p++;
}
}

No.10688

Re:構造体のポインタ
投稿者---RAPT(2003/11/19 22:07:09)


> 【掲示板ご利用上の注意】
> ソースを添付する際には「HTML変換ツール」で字下げしてください。
の通り、「HTML変換ツール」を使うようにして下さい。
# 私の推奨オプションは、コメントを強調する、と、タブ=2、です。

▼最大の問題点
最初のfor文を抜けたとき、pの指し示す先はどこでしょうか?


No.10690

Re:構造体のポインタ
投稿者---ペペ(2003/11/19 22:21:04)


「HTML変換ツール」ですか。使ったこと無いんでわかりませんでした。
でももう使い方、分かったので今度からつかわせてもらいます"^_^"

pにはmeiboの先頭アドレス[0]が入っているのでインクリメントして
meibo[1]となるんじゃないですかね?
そんな感じでうまいこと回ってくれると思ったんですが・・


No.10691

Re:構造体のポインタ
投稿者---RAPT(2003/11/19 22:35:16)


YuOさんが指摘された、&演算子の問題点、見逃していました(--;

>pにはmeiboの先頭アドレス[0]が入っているのでインクリメントして
>meibo[1]となるんじゃないですかね?
>そんな感じでうまいこと回ってくれると思ったんですが・・
私が書いた内容をしっかりと読みましたか?

> 最初のfor文を抜けたとき、pの指し示す先はどこでしょうか?
です。確かに、「最初の」for文では、うまくいくことでしょう。
ここで示している問題点は、「2つ目の」for文です。



No.10693

Re:構造体のポインタ
投稿者---ペペ(2003/11/19 22:46:11)


勘違いしてました・・
for文を抜けたとき、pはmeibo[5]となるん・・ですか?


No.10695

Re:構造体のポインタ
投稿者---RAPT(2003/11/19 23:21:07)


>for文を抜けたとき、pはmeibo[5]となるん・・ですか?
そうです。ところが、
> struct syain meibo[5];
と、実体は、meibo[0]〜meibo[4]までの5つ分しか確保していないため、
pは、確保されていない、範囲外を指し示していることになります。

> pに&をつけるとpにはmeibo[0]のアドレスが代入されてるので、
> &&meibo[0]になるんじゃないですか?
見るところが浅すぎます。

struct syain{
  char name[15];
  int age;
  int nensyu;
};
struct syain meibo[5];
struct syain *p;
p=&meibo[0]; 

としたとき、
syain[0].age も、p->age も、int型です。そこで、
scanf("%d", xxx);
では、xxx は、(int *)型を要求します。通常は
scanf("%d", &(syain[0].age));
と書くことでしょう。

ところが、
syain[0].age と p->age は同一の型なので、
scanf("%d", &(p->age));
と書くことになります。

ここで、&演算子はpを修飾しているのではなく、ageを修飾している点
に着目してください。

&演算子に関しては、色々とあるので、ここには書ききれません。
「配列とポインタの完全制覇」
で勉強してください。


No.10696

Re:構造体のポインタ
投稿者---ペペ(2003/11/19 23:31:33)


ありがとうございました。
感謝!!

No.10689

Re:構造体のポインタ
投稿者---YuO(2003/11/19 22:13:30)


>↓のプログラムのscanf部分が間違ってるようでうまくいきません。
>どこをどう書けばいいのか・・・プログラミング上級者の方、教えてください。

  • 「HTML変換ツール」を使って下さい。
  • インデントをちゃんとつけて下さい。
  • 「うまくいかない」の内容を書いて下さい。


でもって,本題。

struct syain{
    char name[15];
    int age;
    int nensyu;
};
struct syain *p;

ですから,
    printf("氏名 >>");
    scanf("%s",p->name);
    printf("年齢 >>");
    scanf("%d",p->age);
    printf("年収 >>");
    scanf("%d",p->nensyu);

のうち,age,nenshuはちゃんとそのメンバへのポインタを渡す必要があります。
    scanf("%d",&p->nensyu);

のように。ただ,&->の演算子の優先順序がわかりにくいので,
    scanf("%d",&(p->nensyu));

と書いた方がわかりやすいかもしれません。


No.10694

Re:構造体のポインタ
投稿者---ペペ(2003/11/19 23:01:06)


pに&をつけるとpにはmeibo[0]のアドレスが代入されてるので、
&&meibo[0]になるんじゃないですか?イメージ的には
どんな感じなんですか?

頭悪くてすいません(-"-)

No.10699

Re:構造体のポインタ
投稿者---YuO(2003/11/20 00:23:46)


>pに&をつけるとpにはmeibo[0]のアドレスが代入されてるので、
>&&meibo[0]になるんじゃないですか?イメージ的には
>どんな感じなんですか?

&よりも->の方が優先順位が高いので,&p->nenshup->nenshuを指すポインタを返します。
see) 14-5. 演算子の優先順位と結合規則
わかりにくいと思うなら括弧を付けることです。


でもって,多分ポインタまわりで勘違いをしていそうなので補足。

基本的なこと。
#面倒なので,関数へのポインタとか不完全型へのポインタなんかは割愛。
  • T * p;は,pが「T型のオブジェクトへのポインタ」型の識別子である,という宣言です。
  • T o;は,oが「T」型の識別子である,という宣言です。
  • T o;とある時に,部分式&oは「T型のオブジェクトoへのポインタ」を生成します。
  • 部分式p = &o;は,pに「T型のオブジェクトoへのポインタ」を代入します。

ちなみに,オブジェクトというのは変数のようなもの,と思ってもらっていいです(本当の意味はもっと広い)。
上にある中だと,poがオブジェクトになります。

また,識別子というのは変数名のことだと思ってもらっていいです(やっぱり本当の意味はもっと広い)。

前段落を再帰適用。
#前の段落でTと書いていた物が実はU *であったと思って下さい。
  • U * * pp;は,ppが「『U型のオブジェクトへのポインタ』型のオブジェクトへのポインタ」型の識別子である,という宣言です。
  • U * p;は,pが「U型のオブジェクトへのポインタ」型の識別子である,という宣言です。
  • U * p;とある時に,部分式&pは「『U型のオブジェクトへのポインタ』型のオブジェクトpへのポインタ」を生成します。
  • 部分式pp = &pは,ppに「『U型のオブジェクトへのポインタ』型のオブジェクトpへのポインタ」を代入します。



ポインタがわかっていれば&p&&meibo[0]になる,などということは考えつかなくなるのですが……。