ポインタの基本部分についての質問

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
kikku
記事: 2
登録日時: 10年前

ポインタの基本部分についての質問

#1

投稿記事 by kikku » 10年前

初学者です。下は3人分の名前と年齢と性別を入力、表示するプログラムなのですが
main関数内でscan_student関数とprint_student関数を呼び出す行でエラーが起こりました。
しかしどうしてエラーになるのか分かりません。どういう理由でエラーが起こっているのかどなたか教えてくださいませんか。

コード:

#include<stdio.h>

typedef struct{

	char name[64];
	int age;
	char sex[4];

}student;

void scan_student(student *data[]);
void print_student(student data[]);

int main(void){

	student data[3];

	scan_student(&data[]);
	print_student(data[]);

	return 0;

}

void scan_student(student *data[]){

	int i;
	for(i=0;i<3;i++){
		scanf("名前:%s\n",(*data[i]).name);
		scanf("年齢:%d\n",(*data[i]).age);
		scanf("性別:%s\n",(*data[i]).sex);
	}
}

void print_strdent(student data[3]){
	
	int i;
	for(i=0;i<3;i++){
		printf("名前:%s\n",data[i].name);
		printf("年齢:%d\n",data[i].age);
		printf("性別:%s\n",data[i].sex);
	}
}

Rittai_3D
記事: 525
登録日時: 12年前

Re: ポインタの基本部分についての質問

#2

投稿記事 by Rittai_3D » 10年前

引数の[]は要らないと思います。
[]を外したところコンパイルは通りました。 →Ideoneでの結果
オフトピック
ドット演算子ではなくアロー演算子を使いましょう。その方が見やすいです。
初心者です

アバター
usao
記事: 1889
登録日時: 12年前
連絡を取る:

Re: ポインタの基本部分についての質問

#3

投稿記事 by usao » 10年前

なんかいろいろと間違っている気がします.
コレ↓

コード:

void scan_student(student *data[]){
    int i;
    for(i=0;i<3;i++){
        scanf("名前:%s\n",(*data[i]).name);
        scanf("年齢:%d\n",(*data[i]).age);
        scanf("性別:%s\n",(*data[i]).sex);
    }
}
…の,student *data[] は, student **data と同じ意味ですが,
studentの配列を渡す型として果たして適切でしょうか.

仮に,強引にこの型を使うとしても,
(*data).name
等は,意図したところを指していないでしょう.
(  ( (*data) ).name  なら意図した場所を指すかな.)
(あと,scanfには入れる場所を指定する必要があるので,ageの行はさらに間違っている)


一度,studentの配列ではなく,intの配列とかで考えてみてはどうでしょうか.例えば
int data[3];
とかいうのを関数の引数に引き渡したいのだとして,関数を
void f( int **p ){ ... }
とは書かないですよね.

かずま

Re: ポインタの基本部分についての質問

#4

投稿記事 by かずま » 10年前

配列、ポインタ、構造体以前の問題をまず解決しましょう。

次のプログラムは、間違っているわけではありません。
しかし、あなたの思っている通りの動作はしないでしょう。

コード:

#include <stdio.h>

int main(void)
{
    char name[64];
    scanf("名前:%s\n", name);
    printf("名前:%s\n", name);
    return 0;
}
起動しても何も表示されないので、

コード:

kikku [Enter]
と入力してみると、

コード:

名前:$%&'()
のように表示されます。

コード:

名前:kikku [Enter]
q [Enter]
と入力すると

コード:

名前:kikku

と表示されます。

プログラムを次のように書き換えると、
思っていた通りの動くのではありませんか?

コード:

#include <stdio.h>

int main(void)
{
    char name[64];
    printf("名前:"); scanf("%s", name);
    printf("名前:%s\n", name);
    return 0;
}
次は、単独の age の読み込みに挑戦してみてください。
その次は、age の配列でやってみてください。
それから、関数 scan_student、print_student へ進みます。
そのあと、構造体というように順を追って進めていきましょう。

box
記事: 2002
登録日時: 14年前

Re: ポインタの基本部分についての質問

#5

投稿記事 by box » 10年前

kikku さんが書きました: main関数内でscan_student関数とprint_student関数を呼び出す行でエラーが起こりました。
どんなエラーが出ているのか明記する方がよいでしょう。
なお、仮にコンパイルが通ったとしても、
kikku さんが書きました:

コード:

void print_strdent(student data[3]){
この関数の名前はおそらくprint_studentが正しいはずで、
スペル違いによるリンク時の外部参照エラーが出ると思います。
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

taaayu
記事: 2
登録日時: 10年前
住所: 元関西    現北陸

Re: ポインタの基本部分についての質問

#6

投稿記事 by taaayu » 10年前

正しくコンパイル出来ました。
► スポイラーを表示
しょうもないところから一つ一つ見ていきますと
まず初めに性別の配列なんですがsex[4]は少なすぎて危険です。
sex[10]でも怪しいのですが…、name[64]のようにすこし大き目にサイズを用意するのが良いと思います

次にscanfなんですが何人かの指摘が入ってますのでそちらを参考に
ちなみにscanfはint scanf(const char* format, ...);のような形式であり、
format:フォーマット指定文字列
…:入力された値を受け取るアドレスとなっています。
ポインタではざっくり言うと*(間接演算子)を用いずに表記することでアドレスを示すのでscanfでは*を使わない書き方のほうがよいでしょう
また、今回のようにscanfを使用してアドレスを渡す場合、各メンバの型を考慮して引数の指定を行う必要があります。
(たまたま文字列指定%sでは&をつけなくてもよかった。というか&をつけても問題なく動いちゃいますが何故かは自分で確認するといいと思います。)


また、おそらく質問主さんは配列のアドレスのアドレスを引数に渡したいのかなと思ったので、それで考えてみると…やりたいこととは違う気がしますが一応コンパイルは通りました。
► スポイラーを表示
void scan_student(student *data[]);
void scan_student(student (*data)[]);
void scan_student(student (*data)[3]);はどれも別物です。(おそらく三つめしかうまく動作しません)
結合の関係上うまくいかないみたいです
2014年10月からの初学者です
とりあえずなんでもかんでも書いてみることを目標として楽しんでいます
間違ってることを言っていたり書いていたりしていたら是非指摘をしてほしいです

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: ポインタの基本部分についての質問

#7

投稿記事 by みけCAT » 10年前

taaayu さんが書きました:まず初めに性別の配列なんですがsex[4]は少なすぎて危険です。
sex[10]でも怪しいのですが…、name[64]のようにすこし大き目にサイズを用意するのが良いと思います
バッファオーバーランの危険がある実装であれば、要素数に関係なくバッファオーバーランの危険があります。
危険を減らすためには、配列の要素数を上げるだけではなく、scanfで最大の入力の長さを指定するといいと思います。

コード:

#include <stdio.h>

int main(void) {
	char sex[10];
	printf("input sex:");
	scanf("%9s", sex); /* 終端文字のぶん要素数-1を指定する */
	printf("input = \"%s\"\n", sex);
	return 0;
}
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

taaayu
記事: 2
登録日時: 10年前
住所: 元関西    現北陸

Re: ポインタの基本部分についての質問

#8

投稿記事 by taaayu » 10年前

みけCAT さんが書きました: バッファオーバーランの危険がある実装であれば、要素数に関係なくバッファオーバーランの危険があります。
危険を減らすためには、配列の要素数を上げるだけではなく、scanfで最大の入力の長さを指定するといいと思います。
確かにそうですね…すいません
scanf関数自体、柔軟性が高いのであまり理解できてないんですよね・・・("%[^\n]"や"[0123456789]"や"*c"などなど)
自分が作るとこんな感じになるのかなあ・・・
► スポイラーを表示
でもこれだと一つの入力が長ったらしいんですよねえ
なら確かに、

コード:

scanf("%9s", sex);
fflush(stdin);
のほうが全然読みやすいんですよね。なるほど
結構考えずにfgets+sscanfでやってたので見直したほうがよさそうですね
(まあでも個人的にscanfで扱いにくい理由はマクロ置換してくれないとこていう・・・)
2014年10月からの初学者です
とりあえずなんでもかんでも書いてみることを目標として楽しんでいます
間違ってることを言っていたり書いていたりしていたら是非指摘をしてほしいです

YuO
記事: 947
登録日時: 14年前
住所: 東京都世田谷区

Re: ポインタの基本部分についての質問

#9

投稿記事 by YuO » 10年前

taaayu さんが書きました:

コード:

scanf("%9s", sex);
fflush(stdin);
のほうが全然読みやすいんですよね。
fflush(stdin);の意図はなんでしょうか。
未定義の振る舞いなので使うべきでは無いですし,特定の環境においての動作を想定しているのであればその環境を提示する必要があります。
# scanfだけなら標準の範囲内なので意味がわかるけれども,fflush(stdin);があるので意図が全く想像できない。
► スポイラーを表示

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: ポインタの基本部分についての質問

#10

投稿記事 by みけCAT » 10年前

taaayu さんが書きました: fflush(stdin); //C言語では定義されていないためC++での利用になってしまう…
C++では定義されているのですか?そのことを示す出典は提示できますでしょうか?

N1256(C言語について書かれた文章)では、7.19.5.2 The fflush functionにおいて
If stream points to an output stream or an update stream in which the most recent
operation was not input, the fflush function causes any unwritten data for that stream
to be delivered to the host environment to be written to the file; otherwise, the behavior is
undefined.
と書かれており、確かにffush(stdin);のふるまいは未定義のようです(stdinが指しているものが入力ストリームの場合)。

しかし、C++について書かれたN3337およびN4296をSumatraPDFの検索機能を用いてチェックしましたが、
fflushのふるまいがC言語と異なるという記述は見つかりませんでした。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

超初級者
記事: 56
登録日時: 10年前

Re: ポインタの基本部分についての質問

#11

投稿記事 by 超初級者 » 10年前

質問者さんがいないところで
当初の話とは全然違う方向へ
向かっています。

標準入力に対するfflushの是非に
ついての話を続けたいならば、
別トピックを立てるなどしてください。

このトピックの趣旨とはかけ離れていて、
邪魔です。

閉鎖

“C言語何でも質問掲示板” へ戻る