問題が解けません

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
フェイ

問題が解けません

#1

投稿記事 by フェイ » 12年前

初めまして。C言語を初めて半年です。
課題で問題が出されてどうも解けません。手伝いをお願いいたします。

ーここからー
Ackley,D.H. 181.5 65.1
Baker,J.E. 185.3 68.3
Keller,K.S. 175.2 63.4
Brent,R.P. 174.4 52.8
Jong,K.A. 186.2 73.4
Goldberg,D.E. 174.0 60.0
Forrest,S. 175.5 60.6
Fletcher,R. 180.3 73.8
Powell,M.J.D. 170.1 55.9
Smith,R.E. 178.7 69.6
Richardson,J. 167.7 51.5
Martin,F.G. 179.2 65.3
Wilson,S.W. 185.8 84.4
Lawler,E.L. 166.5 59.6
Reed,J. 176.3 58.8
Holland,J.H. 186.1 70.4
Jones,W.T. 171.4 63.7

と描かれたテキストファイルがあります。
Cプログラムを作り、以下の要領でコンパイルし、実行モジュールdelcommaを作成します。

標準入力から受け取った名前の中で,カンマ以下を削除して標準出力に表示するコマンドです.

$ gcc -o delcomma delcomma.c

コマンド delcomma にリダイレクト機能を使って入力ファイル bmi.txt の中身を処理させます.
結果は以下のようになります.綺麗に名前のカンマ以下が消えています.

$ ./delcomma < ./bmi.txt
Ackley
Baker
Keller
Brent
Jong
Goldberg
Forrest
Fletcher
Powell
Smith
Richardson
Martin
Wilson
Lawler
Reed
Holland
Jones

と言う問題なんですが
ソースは


#include <stdio.h>

#define MAX_LINE 20
#define MAX_NAME 20

int main(void);
int readfile(char (*)[MAX_NAME]);
void del_comma(char (*)[MAX_NAME], int);
void write_array(char (*)[MAX_NAME], int);

int main(void)
{
char name[MAX_LINE][MAX_NAME];
int n;

n = readfile(name);
del_comma(name, n);
write_array(name, n);

return 0;
}

void write_array(char (*name)[MAX_NAME], int n)
{
int i;

for (i = 0; i < n; i++) printf("%s\n", name);

return;
}
まで何とかなっていて
残りの関数をどうすれば良いの分からなくなってしまいました。

環境は mac osx viエディターです
よろしくお願いします

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

Re: 問題が解けません

#2

投稿記事 by box » 12年前

設計方針として、
・ファイルを全部読む
・配列に読み込んだ内容を一気に処理する
・結果をまとめて出力する
というポリシーで臨んでおられるようですが、

・ファイルを1行読む
・1行分を処理する
・1行分の処理結果を出力する
・上記すべてを、ファイルを読み終わるまで繰り返す
という考え方ではまずいですか?
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

フェイ

Re: 問題が解けません

#3

投稿記事 by フェイ » 12年前

えっと……
一行処理でまとめて表示が出来ますか?
できなければ
それでも構いません。

返信ありがとうございます!

non
記事: 1097
登録日時: 13年前

Re: 問題が解けません

#4

投稿記事 by non » 12年前

最初に書かれているプログラムは課題で渡されたものではないのですか?
だとしたら、変更したらまずいでしょう。

だって、あんなプロトタイプが書けるならプログラムの中身も書けると思える。
non

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

Re: 問題が解けません

#5

投稿記事 by box » 12年前

もともとのコードがだれかから渡されたものであるかどうかはともかく、
フェイ さんが書きました: 一行処理でまとめて表示が出来ますか?
私は「まとめて表示」とは書いていません。

・1行分の処理結果を出力
・ファイルを読み終わるまで(つまり、ファイルの行数分)「繰り返す」
という趣旨のことは書きましたけれど。
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

フェイ

Re: 問題が解けません

#6

投稿記事 by フェイ » 12年前

あ、そうでしたか。どうもすみません……
だったらそれで構いません
すみませんでした

non
記事: 1097
登録日時: 13年前

Re: 問題が解けません

#7

投稿記事 by non » 12年前

boxさんが仰っているのはこんな感じ

コード:

int main(void)
{
	char str[80],*p;
	while(gets(str)!=NULL){
		if((p=strstr(str,","))!=NULL)
			*p='\0';
		puts(str);
	}
	return 0;
}
non

フェイ

Re: 問題が解けません

#8

投稿記事 by フェイ » 12年前

int readfile(char (*)[MAX_NAME]);
void del_comma(char (*)[MAX_NAME], int);

だけを教えてください……

フェイ

Re: 問題が解けません

#9

投稿記事 by フェイ » 12年前

あ、間違えていた……
これは課題で出されているプログラムで

int readfile(char (*)[MAX_NAME]);
void del_comma(char (*)[MAX_NAME], int);

だけを作れば良いそうで
提出が8なんです
急速に必要になりました
よろしくお願いします

non
記事: 1097
登録日時: 13年前

Re: 問題が解けません

#10

投稿記事 by non » 12年前

丸投げは禁止されているのですから、このままでは誰も手助けしませんよ。
解けるところまで解いて、作ったプログラムを載せて、わからないところを質問すること。
non

フェイ

Re: 問題が解けません

#11

投稿記事 by フェイ » 12年前

丸投げではなくて、本当にどうすれば良いのか分からなくて……
二つの関数を作るのも出来なくて……
考えとしては
改行までを読み込み、それらを一つの配列に入れて
delcommaでカンマを消す

と言う風な感じで出来ているんですけど
それがプログラムに出来なくて困っているんです。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: 問題が解けません

#12

投稿記事 by softya(ソフト屋) » 12年前

もう一度整理してみてくださいますか。
まず、フォーラムルールをご確認下さい。 http://dixq.net/board/board.html
で、次の部分に注意して下さい。
引用
課題の丸投げ(問題文だけ書く事)は禁止です。
ただし上のように記載してもらえればこれは当てはまりません。
自分でどこまでやったのか、今どこが解らないのかを明確にして下さい。
さっぱり解らず、手も足も出ない時は、その事を明記の上、
勉強方法からアドバイスを受けましょう。
どうしても提出期限の関係で答えが欲しい時はその事をしっかり明記の上、
回答者さん達の理解を求めるようにしましょう。
また、解決した時は、「解決しました」とだけ言って去らず、ソースコードや解決した方法を明記して下さい。
同じ事で困っている人の為に過去ログに有用な情報を残すようお願いします。
まだ3日あるますので解き方のアドバイスを受けるようにして下さい。
なので、分からないところをもっと明確に説明してくださいね。

まず、このテンプレートを使っていただくのと最初に書かれたコードをcodeタグを使って貼り直して下さい。
[1] 質問文
 [1.1] 自分が今行いたい事は何か
 [1.2] どのように取り組んだか(プログラムコードがある場合記載)
 [1.3] どのようなエラーやトラブルで困っているか(エラーメッセージが解る場合は記載)
 [1.4] 今何がわからないのか、知りたいのか

[2] 環境  
 [2.1] OS : Windows, Linux等々
 [2.2] コンパイラ名 : VC++ 2008EE, Borand C++, gcc等々

[3] その他
 ・どの程度C言語を理解しているか
 ・ライブラリを使っている場合は何を使っているか
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: 問題が解けません

#13

投稿記事 by softya(ソフト屋) » 12年前

>改行までを読み込み、それらを一つの配列に入れてdelcommaでカンマを消す

関数でなければ出来るのでしょうか?
それと
(1)改行までを読み込み
(2)それらを一つの配列に入れて
(3)delcommaでカンマを消す
のそれぞれの分からない点を書きだして下さい。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

non
記事: 1097
登録日時: 13年前

Re: 問題が解けません

#14

投稿記事 by non » 12年前

non さんが書きました:boxさんが仰っているのはこんな感じ

コード:

int main(void)
{
	char str[80],*p;
	while(gets(str)!=NULL){
		if((p=strstr(str,","))!=NULL)
			*p='\0';
		puts(str);
	}
	return 0;
}
前に投稿したこのプログラムでわからないことはなんですか?
non

フェイ

Re: 問題が解けません

#15

投稿記事 by フェイ » 12年前

改めて……
$ cat bmi.txt
Ackley,D.H. 181.5 65.1
Baker,J.E. 185.3 68.3
Keller,K.S. 175.2 63.4
Brent,R.P. 174.4 52.8
Jong,K.A. 186.2 73.4
Goldberg,D.E. 174.0 60.0
Forrest,S. 175.5 60.6
Fletcher,R. 180.3 73.8
Powell,M.J.D. 170.1 55.9
Smith,R.E. 178.7 69.6
Richardson,J. 167.7 51.5
Martin,F.G. 179.2 65.3
Wilson,S.W. 185.8 84.4
Lawler,E.L. 166.5 59.6
Reed,J. 176.3 58.8
Holland,J.H. 186.1 70.4
Jones,W.T. 171.4 63.7

C プログラム delcomma.c を書き,以下の要領でコンパイルし,実行モジュール delcomma を生成します.
delcomma は想像通り,delete comma の略です.
標準入力から受け取った名前の中で,カンマ以下を削除して標準出力に表示するコマンドです.

$ gcc -o delcomma delcomma.c

コマンド delcomma にリダイレクト機能を使って入力ファイル bmi.txt の中身を処理させます.
結果は以下のようになります.綺麗に名前のカンマ以下が消えています.

$ ./delcomma < ./bmi.txt
Ackley
Baker
Keller
Brent
Jong
Goldberg
Forrest
Fletcher
Powell
Smith
Richardson
Martin
Wilson
Lawler
Reed
Holland
Jones

ソース delcomma.c の一部を示します.残りを埋めて完成させて下さい.

コード:

#include <stdio.h>

#define MAX_LINE 20
#define MAX_NAME 20

int main(void);
int readfile(char (*)[MAX_NAME]);
void del_comma(char (*)[MAX_NAME], int);
void write_array(char (*)[MAX_NAME], int);

int main(void)
{
	char name[MAX_LINE][MAX_NAME];
	int n;

	n = readfile(name);
	del_comma(name, n);
	write_array(name, n);

	return 0;
}

void write_array(char (*name)[MAX_NAME], int n)
{
	int i;

	for (i = 0; i < n; i++) printf("%s\n", name[i]);

	return;
}

1] 質問文
 [1.1] 自分が今行いたい事は何か
関数
  int readfile(char (*)[MAX_NAME]);
void del_comma(char (*)[MAX_NAME], int);
 の作成 

 [1.2] どのように取り組んだか(プログラムコードがある場合記載)
   あれこれ考えて、友人にも聞いてみるものの進展が無い。

 [1.3] どのようなエラーやトラブルで困っているか(エラーメッセージが解る場合は記載)
  コンパイルまで辿り着いていない

 [1.4] 今何がわからないのか、知りたいのか
   ある程度の考え等は出来ているが関数二つの構成が出来ない。

[2] 環境  
 [2.1] OS : Mac osX
 [2.2] コンパイラ名 :gcc

[3] その他
 ・理解し切ってはいないが、ポインタ辺りまで

です。ご迷惑をおかけしました

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: 問題が解けません

#16

投稿記事 by softya(ソフト屋) » 12年前

私の質問とnonさんの質問にもお応えくださいね。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

フェイ

Re: 問題が解けません

#17

投稿記事 by フェイ » 12年前

>nonさん
main関数は弄れないようでそれを関数でやらなければいけないんです

>softyaさん
全部どうプログラムにすれば良いかが分からないんです

beatle
記事: 1281
登録日時: 12年前
住所: 埼玉
連絡を取る:

Re: 問題が解けません

#18

投稿記事 by beatle » 12年前

コード:

char (*foo)[MAX_NAME];
の意味が分かりづらいのは確かだと思います。
このへんの型の意味不明さはCの悪いところだと思います。
さて、上記の型をちょっと違う方法で書くとすれば

コード:

typedef char line_type[MAX_NAME];
line_type *foo;
と等価です。これは何を意味しているか。まずtypedefは、ある型に別名をつけるという命令です。
基本的に

コード:

typedef A B;
という感じで書きますが、これはAという型にBという別名をつけるという意味になります。
上の例で言えば、「charの要素数MAX_NAME個の配列」という型に「line_type」という別名をつけています。
別名を付けてしまえば、あとは

コード:

line_type bar;
などと書くだけで、変数barは、MAX_NAME個の要素をもつchar配列ということになります。
つまり、例の2行目ではline_type型へのポインタであるfooを定義しています。

non
記事: 1097
登録日時: 13年前

Re: 問題が解けません

#19

投稿記事 by non » 12年前

フェイ さんが書きました:>nonさん
main関数は弄れないようでそれを関数でやらなければいけないんです
そんなことは百も承知です。
あなたが、どこまでわからないのかを聞きたいのです。
あのプログラムを、入力部分と、処理部分と、出力部分の3つの別々のループに分けて欲しいのです。
関数にするのはその後でいいでしょう。

関数を使わなければ、解けるのかが知りたい。
わからない、わからないというばかりでは、手をさしのべる気になりません。
non

アバター
bitter_fox
記事: 607
登録日時: 13年前
住所: 大阪府

Re: 問題が解けません

#20

投稿記事 by bitter_fox » 12年前

フェイ さんが書きました: 全部どうプログラムにすれば良いかが分からないんです
ファイルから文字列を読み込む方法は習ったりしましたか?
FILE、fgetsやfscanfなどです。


[修正]
標準入力から文字列を読み込む方法は習ったりしましたか?
gets(安全性を考えればfgets)やscanfなどです。

もし習ったのであればこのシチュエーションではどれを用いるのが適切だと思いますか?
習っていない場合はGoogleなどの検索サイトを駆使して調べてみてください。

ちなみに、ある関数を使った場合MAX_NAMEが20だとうまく一行ずつ読み込めない可能性があります。それの対応策も調べるなり考えてみてください。

[hr][追記]
フェイ さんが書きました:  [1.2] どのように取り組んだか(プログラムコードがある場合記載)
   あれこれ考えて、友人にも聞いてみるものの進展が無い。

 [1.4] 今何がわからないのか、知りたいのか
   ある程度の考え等は出来ているが関数二つの構成が出来ない。
手は動かしていますか?
ある程度できるようになると頭の中でプログラムを構成して、それをコードに落とすことは可能ですが、最初からそのようにできるわけではありません。
最初は、今できる所まで作ってコンパイルして確認、それに基づいてもう少し進めてコンパイルして確認、さらに進めてコンパイルして確認・・・と進めていく必要があると思います。
なので考えるだけじゃなく手を動かしましょう。

例えば今回で言えば、まずreadfile内で一行読み込んでそれをただただ出力してみるなどと言った風です。
次はこれに基づいて全ての行を、もしそれで問題が発生したら対応策を考えて手を動かす・・・などです。

[hr]
non さんが書きました:
bitter_fox さんが書きました:ファイルから文字列を読み込む方法は習ったりしましたか?
FILE、fgetsやfscanfなどです。
リダイレクトでいいみたいですよ。
おっ、本当ですね。問題文をしっかり読んでいませんでした。
ご指摘ありがとうございます。
最後に編集したユーザー bitter_fox on 2011年12月06日(火) 09:21 [ 編集 2 回目 ]

non
記事: 1097
登録日時: 13年前

Re: 問題が解けません

#21

投稿記事 by non » 12年前

bitter_fox さんが書きました:ファイルから文字列を読み込む方法は習ったりしましたか?
FILE、fgetsやfscanfなどです。
リダイレクトでいいみたいですよ。
non

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: 問題が解けません

#22

投稿記事 by softya(ソフト屋) » 12年前

私からの提案としては、とりあえず日本語良いので次の3つをもっと細かく分解してみましょう。
私の提案では、日本語化→ソース化→関数化という手順を踏みます。
(1)改行までを読み込み
(2)それらを一つの配列に入れて
(3)delcommaでカンマを消す
では、(1)からですので細かく分解してみてください。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

フェイ

Re: 問題が解けません

#23

投稿記事 by フェイ » 12年前

delcomma関数で
code=C

void delcomma(char (*word)[MAX_WORD],int n)
{
int i;

char *p;
for(i=0;i<MAX_WORD;i++){
while(gets(word)!=NULL){
p=strtok(word,",");
}

}
return;
}

/code

でコンパイル実行すると
warning: this program uses gets(), which is unsafe.
と出ました。
fgetsを使わずにどうしたら消せますか?

beatle
記事: 1281
登録日時: 12年前
住所: 埼玉
連絡を取る:

Re: 問題が解けません

#24

投稿記事 by beatle » 12年前

codeタグの使い方が間違っています。タグは一般にブラケット[と]に挟んで使います。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: 問題が解けません

#25

投稿記事 by softya(ソフト屋) » 12年前

前のcodeタグは、こちらが直したのは書き忘れてました。
codeタグの使い方が間違っていますので見なおして下さい。
http://dixq.net/board/board.html#k10

それと
>warning: this program uses gets(), which is unsafe.
は無視して構いません。

あとdelcommaでgetsするのはフェイ さんが書いた仕様に反していますがわざとでしょうか?まず作るを優先されたってことですよね?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: 問題が解けません

#26

投稿記事 by softya(ソフト屋) » 12年前

それとご本人じゃない(学友?)と思いますが、こっちのコードのままですよね? ご本人なら相互リンクが必要です。
「C言語で分からない置換問題があるのですが…。 - Yahoo!知恵袋」
http://detail.chiebukuro.yahoo.co.jp/qa ... 1176797416
[訂正]これバグってます(正確に言うと仕様違反と中途半端な完成度)ので参考にしないほうが良いと思います。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

フェイ

Re: 問題が解けません

#27

投稿記事 by フェイ » 12年前

いろいろと分かんなくなってきたので
もう止めます
ご迷惑をおかけして本当にすみませんでした…

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: 問題が解けません

#28

投稿記事 by softya(ソフト屋) » 12年前

ここで諦めたらC言語を理解するチャンスを失うことにもなりかねません。
もう少し粘って見ませんか?まだ2日あリますよ。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

フェイ

Re: 問題が解けません

#29

投稿記事 by フェイ » 12年前

分かりました… 頑張ってみます

テキストファイルを読み込む関数で
code=C
int readfile(char (*name)[MAX_NAME])
{
int i;
for(i=0;i<MAX_LINE;i++){
scanf("%s",name);
}
/code

のように作成したのですが、
結果が


Ackley,D.H.
181.5
65.1
Baker,J.E.
185.3
68.3
Keller,K.S.
175.2
63.4
Brent,R.P.
174.4
52.8
Jong,K.A.
186.2
73.4
Goldberg,D.E.
174.0
60.0
Forrest,S.
175.5

のようになります

全部表示されず、人の名前、身長、体重が本来一つの配列にならなければいけない所が
三つになっている為に最後まで表示されないかと思っています。
ここを三つの配列ではなくて一つの配列として読み込みたいのですが
どうすれば良いでしょうか?

<補足>
確認した所、MAX_LINEを51にすると全体表示できました。
それとgets等は使えます。

beatle
記事: 1281
登録日時: 12年前
住所: 埼玉
連絡を取る:

Re: 問題が解けません

#30

投稿記事 by beatle » 12年前

scanfで%sを使用すると、空白文字で区切られたものを一塊として読み込んでしまいますので、
そのようなことになります。

一行を読み込むのならgetsやfgetsを使いましょう。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: 問題が解けません

#31

投稿記事 by softya(ソフト屋) » 12年前

すいませんcodeタグが失敗しています。もう一度フォーラムルールをよく確認して下さい。投稿前にプレビューされることをお勧めします。
問題点は、beatleさんの言われるとおりです。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

フェイ

Re: 問題が解けません

#32

投稿記事 by フェイ » 12年前

fgetsはちらっとと授業中に説明を受けただけでちょっと分からない部分が……

コード:

int readfile(char (*name)[MAX_NAME])
{
int i=0,ch=0;
for(i=0;i<MAX_LINE;i++){
ch=fgets();
}

return i;
}
と、してみました。

error: too few arguments to function ‘fgets’
というエラーが発生したんですが……

アバター
bitter_fox
記事: 607
登録日時: 13年前
住所: 大阪府

Re: 問題が解けません

#33

投稿記事 by bitter_fox » 12年前

フェイ さんが書きました: テキストファイルを読み込む関数で

コード:

int readfile(char (*name)[MAX_NAME])
{
int i;
for(i=0;i<MAX_LINE;i++){
scanf("%s",name[i]);
}
全部表示されず、人の名前、身長、体重が本来一つの配列にならなければいけない所が
三つになっている為に最後まで表示されないかと思っています。
ここを三つの配列ではなくて一つの配列として読み込みたいのですが
どうすれば良いでしょうか?

<補足>
確認した所、MAX_LINEを51にすると全体表示できました。
それとgets等は使えます。
凄く良いと所まで出来てるんじゃないでしょうか。
後は終了判定と読み込んだ行数を返す処理を書いてみてください。
終了処理はファイルの最後まで読み込んだ場合scanfがEOFを返すということに注目するとよいと思います。

それから問題点の分析も正確です。
解決策としてはscanfを使って少数の値2つを読み込んで捨てる、とかgets/fgetsで名前を含む部分を読み込んだのち改行が出てくるまで剰余分を読み捨てるなどがあるでしょう。
一番きれいなのはscanfを使って読み捨てるでしょうか。
最後に編集したユーザー bitter_fox on 2011年12月06日(火) 19:38 [ 編集 1 回目 ]

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: 問題が解けません

#34

投稿記事 by softya(ソフト屋) » 12年前

getsを使って下さい。あとgetcと勘違いしてませんか?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アバター
bitter_fox
記事: 607
登録日時: 13年前
住所: 大阪府

Re: 問題が解けません

#35

投稿記事 by bitter_fox » 12年前

フェイ さんが書きました:fgetsはちらっとと授業中に説明を受けただけでちょっと分からない部分が……

ch=fgets();

error: too few arguments to function ‘fgets’
というエラーが発生したんですが……
fgetsの呼び出しに対して引数が足りていませんというエラーです。
fgetsは、
第一引数に代入先文字列の先頭アドレス、
第二引数に代入先文字列の確保されているバイト数、
第三引数にファイルポインタを受け取り、戻り値に代入先文字列の先頭アドレス(EOFの時はNULL)を返します。
http://ohmoriws1.ms.kagu.tus.ac.jp/1997 ... i/c04.html
[hr][追記]
標準入力から受け取る場合、第三引数のファイルポインタにはstdinを使用してください。

フェイ

Re: 問題が解けません

#36

投稿記事 by フェイ » 12年前

アドヴァイスありがとうございます!

コード:

int readfile(char (*name)[MAX_NAME])
{
int i=0,ch=0;
for(i=0;i<MAX_LINE;i++){
while(ch=fgetc(stdin)!=EOF);
}

return i;
}
としました

そうすると結果が


0?*??u?Ԃ'a?{
k?1??L
u?q6??e???J?N?S?
9j?d?>)y?W?s@w???<??y?O??l?h?Cd??_?
?L
u?q6??e???J?N?S?
9j?d?>)y?W?s@w???<??y?O??l?h?Cd??_?
N?S?
9j?d?>)y?W?s@w???<??y?O??l?h?Cd??_?
@w???<??y?O??l?h?Cd??_?
d??_?
?
??_?
?



?




???_?
と意味が分からない状態になりました
これはどういう状況なんでしょうか?

私的には
空白等が入り交じっているからかな?
と、思うのですが……

beatle
記事: 1281
登録日時: 12年前
住所: 埼玉
連絡を取る:

Re: 問題が解けません

#37

投稿記事 by beatle » 12年前

fgetcは1文字ずつ読み込むための関数なので、今回は使わなくていいと思います。
fgets, gets, scanfの中から選びましょう

アバター
bitter_fox
記事: 607
登録日時: 13年前
住所: 大阪府

Re: 問題が解けません

#38

投稿記事 by bitter_fox » 12年前

フェイ さんが書きました:

コード:

int readfile(char (*name)[MAX_NAME])
{
int i=0,ch=0;
for(i=0;i<MAX_LINE;i++){
while(ch=fgetc(stdin)!=EOF);
}

return i;
}
私的には
空白等が入り交じっているからかな?
と、思うのですが……
chにだけ代入されていてnameの領域に対して何ら変化が起きていないのでnameの領域の初期値が表示されてしまっています。
beatleさんの言うとおりfgets, gets, scanfのうちのいずれかを使うのがベターでしょう。

フェイ

Re: 問題が解けません

#39

投稿記事 by フェイ » 12年前

分かりました!
と言う事で変更してみて、色々考えましたが……

コード:


int readfile(char (*name)[MAX_NAME])
{
int i=0,ch=0;
for(i=0;i<MAX_LINE;i++){
while(ch=fgets(stdin)!=EOF);
}

にすると
エラー

warning: passing argument 1 of ‘fgets’ from incompatible pointer type
error: too few arguments to function ‘fgets’

どうにか対処したいのですが……

追記
stdinの場所は正しいでしょうか?

beatle
記事: 1281
登録日時: 12年前
住所: 埼玉
連絡を取る:

Re: 問題が解けません

#40

投稿記事 by beatle » 12年前

まあ、そのくらいの悩みならココに質問するよりグーグル先生の方が速いときがありますのでご活用下さい。
ちなみに、fgetsで検索したトップが→http://ohmoriws1.ms.kagu.tus.ac.jp/1997 ... i/c04.html

フェイ

Re: 問題が解けません

#41

投稿記事 by フェイ » 12年前

聞いてばかりで本当に申し訳ないんですが…
fgetsはちらりとしかやっていなくて
分かり易く説明して頂けませんか?
本当にすみません……

beatle
記事: 1281
登録日時: 12年前
住所: 埼玉
連絡を取る:

Re: 問題が解けません

#42

投稿記事 by beatle » 12年前

コード:

fgets(s, size, stream);
s : 「読み込んだデータをどこに入れるか」
size : 「sの大きさは何文字分か」
stream : 「どこから読み込むか」
つまるところ「streamからsに、最大size文字を入力する」ということになります。

今回の場合で言えば「stdinからnameに、最大MAX_NAME文字を入力」したいわけですから・・・。
さて?

フェイ

Re: 問題が解けません

#43

投稿記事 by フェイ » 12年前

すごく分かり易い解説ありがとうございます!

つまり、こういう事ですね!?

コード:


int readfile(char (*name)[MAX_NAME])
{
int i=0,ch=0;
for(i=0;i<MAX_LINE;i++){
fgets(name[i],MAX_NAME,stdin);
}

return i;
}

結果に変動がありました! 


Ackley,D.H. 181.5
65.1

Baker,J.E. 185.3
68.3

Keller,K.S. 175.2
63.4

Brent,R.P. 174.4
52.8

Jong,K.A. 186.2
73.4

Goldberg,D.E. 174.0
60.0

Forrest,S. 175.5
60.6

Fletcher,R. 180.3
73.8

Powell,M.J.D. 170.1
55.9

Smith,R.E. 178.7
69.6

です。
あと、空白行と体重を一つにしたいです。
もう少しなんです……
お願いします。

beatle
記事: 1281
登録日時: 12年前
住所: 埼玉
連絡を取る:

Re: 問題が解けません

#44

投稿記事 by beatle » 12年前

fgetsは入力が終了したときにはNULLを返すようになっていますから、fgetsの戻り値がNULLになった瞬間のiを
returnするようにしたらreadfile関数は完成ですね。
出力が3行になっちゃう問題はreadfile以外の関数の問題です。

フェイ

Re: 問題が解けません

#45

投稿記事 by フェイ » 12年前

コード:

int readfile(char (*name)[MAX_NAME])
{
int i;
for(i=0;i<MAX_LINE;i++){
fgets(name[i],MAX_NAME,stdin);
}

return i;
}

void write_array(char (*name)[MAX_NAME],int n)
{
 int i;
  for (i = 0; i < n; i++) printf("%s",name[i]);

return;
}
こんどはnameを表示する関数なんですが、
printfの改行を消した所、一つの行列に収める事が出来ましたが、

結果


Ackley,D.H. 181.5 65.1
Baker,J.E. 185.3 68.3
Keller,K.S. 175.2 63.4
Brent,R.P. 174.4 52.8
Jong,K.A. 186.2 73.4
Goldberg,D.E. 174.0 60.0
Forrest,S. 175.5 60.6
Fletcher,R. 180.3 73.8
Powell,M.J.D. 170.1 55.9
Smith,R.E. 178.7 69.6

でした。

MAX_LINEを45ぐらいにすると
全表示できました。

どうすればいいですか?

beatle
記事: 1281
登録日時: 12年前
住所: 埼玉
連絡を取る:

Re: 問題が解けません

#46

投稿記事 by beatle » 12年前

MAX_LINEはこまめに調整するんじゃなくて、多めに、例えば128くらいにしておくのが良いと思います。
今の段階で、readfileがまだ少し未完成ではありますが、softyaさんのNo22の(2)番までできました。

fgetsで改行まで読み取り、nameに入れる、という作業を最終行まで終わらせましたので。

そしたらあとは、(3)の処理ですね。
日本語で構いませんので、(3)番の処理はどんなふうにやったらいいか、考えてみてください。

フェイ

Re: 問題が解けません

#47

投稿記事 by フェイ » 12年前

情報の入った配列をgetで読み込んで、
コンマまで読み込んで、ヌル文字をぶち込む
みたいな感じですか?

beatle
記事: 1281
登録日時: 12年前
住所: 埼玉
連絡を取る:

Re: 問題が解けません

#48

投稿記事 by beatle » 12年前

fgetsはもう完了したので、get系の関数はもう使いません。

うーん、そうですね。例えば「nameの先頭からコンマを探し、コンマの位置にヌル文字を書き込む」
なんてどうでしょうか。

フェイ

Re: 問題が解けません

#49

投稿記事 by フェイ » 12年前

get以外ですか?
う〜ん、思いつきません。
すみません……

beatle
記事: 1281
登録日時: 12年前
住所: 埼玉
連絡を取る:

Re: 問題が解けません

#50

投稿記事 by beatle » 12年前

ヒント:もう標準関数は使わなくても簡単です

フェイ

Re: 問題が解けません

#51

投稿記事 by フェイ » 12年前

〜〜=’\0’ってことですか?

フェイ

Re: 問題が解けません

#52

投稿記事 by フェイ » 12年前

ん〜、分かりません
どうしたら良いでしょうか?

beatle
記事: 1281
登録日時: 12年前
住所: 埼玉
連絡を取る:

Re: 問題が解けません

#53

投稿記事 by beatle » 12年前

beatle さんが書きました:「nameの先頭からコンマを探し、コンマの位置にヌル文字を書き込む」

これを素直にプログラムにすればいいのですけれども。
for, ifを使うことになりそうですね。

コード:

int j;
for (j = 0; name[i][j] != '\0'; ++j) {
    if (name[i][j] == ',') {
        ...
    }
}
...
という流れにすれば良いと思います。

フェイ

Re: 問題が解けません

#54

投稿記事 by フェイ » 12年前

あぁ、なるほど!
こんな感じですか?

コード:



void delcomma(char (*name)[MAX_NAME],int n)
{
  int i,j;
     for (j = 0; name[i][j] != '\0'; ++j) {
       if (name[i][j] == ',') {
            name[i][j]='\0';
    }
}

return;
}


フェイ

Re: 問題が解けません

#55

投稿記事 by フェイ » 12年前

フェイ さんが書きました:あぁ、なるほど!
こんな感じですか?

コード:



void delcomma(char (*name)[MAX_NAME],int n)
{
  int i,j;
     for (j = 0; name[i][j] != '\0'; ++j) {
       if (name[i][j] == ',') {
            name[i][j]='\0';
    }
}

return;
}

これで実行しても
結果が変わりません、
どこか間違っていませんか?

beatle
記事: 1281
登録日時: 12年前
住所: 埼玉
連絡を取る:

Re: 問題が解けません

#56

投稿記事 by beatle » 12年前

気づきませんか?delcommaの中ではiはまったく初期化されていないのですよ。

フェイ

Re: 問題が解けません

#57

投稿記事 by フェイ » 12年前

はっ、そうだった!

コード:



void delcomma(char (*name)[MAX_NAME],int n)
{
  int i=0,j;
     for (j = 0; name[i][j] != '\0'; ++j) {
       if (name[i][j] == ',') {
            name[i][j]='\0';
    }
}

return;
}
結果


Ackley 65.1
Baker,J.E. 185.3 68.3
Keller,K.S. 175.2 63.4
Brent,R.P. 174.4 52.8
Jong,K.A. 186.2 73.4
Goldberg,D.E. 174.0 60.0
Forrest,S. 175.5 60.6
Fletcher,R. 180.3 73.8
Powell,M.J.D. 170.1 55.9
Smith,R.E. 178.7 69.6
Richardson,J. 167.7 51.5
Martin,F.G. 179.2 65.3
Wilson,S.W. 185.8 84.4
Lawler,E.L. 166.5 59.6
Reed,J. 176.3 58.8
Holland,J.H. 186.1 70.4
Jones,W.T. 171.4 63.7


何かが違うんですよね?

アバター
bitter_fox
記事: 607
登録日時: 13年前
住所: 大阪府

Re: 問題が解けません

#58

投稿記事 by bitter_fox » 12年前

フェイ さんが書きました:はっ、そうだった!

コード:



void delcomma(char (*name)[MAX_NAME],int n)
{
  int i=0,j;
     for (j = 0; name[i][j] != '\0'; ++j) {
       if (name[i][j] == ',') {
            name[i][j]='\0';
    }
}

return;
}
何かが違うんですよね?
それだとiが0の時しか,が除去されませんよ。0~n-1について,を除去しないといけませんよね。

フェイ

Re: 問題が解けません

#59

投稿記事 by フェイ » 12年前

つまり、それはiが引かれていくi--を使うってことで良いんですか?

コード:



void delcomma(char (*name)[MAX_NAME],int n)
{
  int i=0,j;
      for(j=0;name[i][j]!='\0';++j){
       if (name[i][j] == ',') {
            name[i][j]='\0';
              i--;
 }
}

return;

で、やってみましたが
変動なしでした……

フェイ

Re: 問題が解けません

#60

投稿記事 by フェイ » 12年前

あと、話は戻るんですが、
fgetsは入力が終了したときにはNULLを返すようになっていますから、fgetsの戻り値が*NULLになった瞬間のiを
returnするようにしたら
というのは

コード:


int readfile(char (*name)[MAX_NAME])
{
  int i;
   for(i=0;i<MAX_LINE;i++){
    fgets(name[i],MAX_NAME,stdin);
}

return(i);
}
なんですが
return(i)で正しいんでしょうか?

beatle
記事: 1281
登録日時: 12年前
住所: 埼玉
連絡を取る:

Re: 問題が解けません

#61

投稿記事 by beatle » 12年前

1. bitter_foxさんは、今のままだとiは0のままだから、0からn-1についても処理しないとだめだと指摘しました。
それに対して、どうしてi--をしようと思ったのでしょうか。
0からn-1というのは、明らかに0以上の数です。
だからといって、単にi++にしただけではうまく動かないと思いますが。
iを変化させるのは一段上のforループじゃないといけません。

2. インデントをちゃんとやろうという気持ちはありますか?
もしかしたらインデントなんてやる気がないのかもしれませんから、僕がNo59をインデントしておきます。

コード:

void delcomma(char (*name)[MAX_NAME],int n)
{
	int i=0,j;
	for(j=0;name[i][j]!='\0';++j){
		if (name[i][j] == ',') {
			name[i][j]='\0';
			i--;
		}
	}

	return;
3. No60への回答:そもそもfgetsの戻り値をチェックしていない時点で間違っています。

フェイ

Re: 問題が解けません

#62

投稿記事 by フェイ » 12年前

bitter_fox さんが書きました:
フェイ さんが書きました:

コード:



void delcomma(char (*name)[MAX_NAME],int n)
{
  int i=0,j;
     for (j = 0; name[i][j] != '\0'; ++j) {
       if (name[i][j] == ',') {
            name[i][j]='\0';
    }
}

return;
}
何かが違うんですよね?
それだとiが0の時しか,が除去されませんよ。0~n-1について,を除去しないといけませんよね。
についてで0~n-1について,を除去しないといけませんよね
はreadfileがしっかりしていないとまずいんじゃないですか?

beatle
記事: 1281
登録日時: 12年前
住所: 埼玉
連絡を取る:

Re: 問題が解けません

#63

投稿記事 by beatle » 12年前

フェイ さんが書きました: についてで0~n-1について,を除去しないといけませんよね
はreadfileがしっかりしていないとまずいんじゃないですか?
その通りです!

アバター
bitter_fox
記事: 607
登録日時: 13年前
住所: 大阪府

Re: 問題が解けません

#64

投稿記事 by bitter_fox » 12年前

フェイ さんが書きました: についてで0~n-1について,を除去しないといけませんよね
はreadfileがしっかりしていないとまずいんじゃないですか?
readfileがしっかりしていないとまずいというか、全てがしっかりしてないと意味がないですよね。
つまりreadfileもしっかりしていないと意味がないし、delcommaもしっかりしていないと意味がありません。
順番から言えばまずはreadfileをしっかりさせる方が先でしょうかね・・・

readfileの問題点とdelcommaの問題点は既にbeatleさんが指摘されてるので略します。

フェイ

Re: 問題が解けません

#65

投稿記事 by フェイ » 12年前

beatle さんが書きました:1. bitter_foxさんは、今のままだとiは0のままだから、0からn-1についても処理しないとだめだと指摘しました。
それに対して、どうしてi--をしようと思ったのでしょうか。
0からn-1というのは、明らかに0以上の数です。
だからといって、単にi++にしただけではうまく動かないと思いますが。
iを変化させるのは一段上のforループじゃないといけません。

2. インデントをちゃんとやろうという気持ちはありますか?
もしかしたらインデントなんてやる気がないのかもしれませんから、僕がNo59をインデントしておきます。

コード:

void delcomma(char (*name)[MAX_NAME],int n)
{
	int i=0,j;
	for(j=0;name[i][j]!='\0';++j){
		if (name[i][j] == ',') {
			name[i][j]='\0';
			i--;
		}
	}

	return;
3. No60への回答:そもそもfgetsの戻り値をチェックしていない時点で間違っています。
インデントは忘れていました すみません……
一段上のforループということは

コード:


void delcomma(char (*name)[MAX_NAME],int n)
{
  int i,j;
     for(i=0;name[i][j]!='\0';++i){
      for(j=0;name[i][j]!='\0';++j){
       if (name[i][j] == ',') {
            name[i][j]='\0';
  }
 }
}
return;
}

ということですよね?

No,60についてのチェックとはどういう意味ですか?

beatle
記事: 1281
登録日時: 12年前
住所: 埼玉
連絡を取る:

Re: 問題が解けません

#66

投稿記事 by beatle » 12年前

フェイ さんが書きました:インデントは忘れていました すみません……
という発言の直後にそのソースコードを見せられると、全く訳がわからないのですが。
投稿前チェックリストの「チェック3 : インデントを揃えよう」を御覧ください。
フェイ さんが書きました:ということですよね?
外側のfor文の条件式はそれでいいのか、という疑問は無視するとすれば、大体イメージは合ってるかと。

チェック、というのは英語でして、日本語訳すれば「調べる」ということですね。
fgets(...); ←fgetsの戻り値を調べてない
if (fgets(...) == NULL) ←fgetsの戻り値を調べている

フェイ

Re: 問題が解けません

#67

投稿記事 by フェイ » 12年前

う〜ん 分かりません……
教えて頂けませんか?

フェイ

Re: 問題が解けません

#68

投稿記事 by フェイ » 12年前

時間がないんです……
あと、ちょっとのヒントだけで書けるぐらい熟知している訳じゃないんで……
お願いします……

beatle
記事: 1281
登録日時: 12年前
住所: 埼玉
連絡を取る:

Re: 問題が解けません

#69

投稿記事 by beatle » 12年前

int readfile(char (*name)[MAX_NAME]);
void delcomma(char (*name)[MAX_NAME],int n);

readfileはせっかくint型の戻り値なのですから、読み込んだ行数を返すようにして、
delcommaの引数nに渡してやればよさそうです。

ということで、まずはreadfileの改造

コード:

int readfile(char (*name)[MAX_NAME])
{
	int i;
	for(i=0;i<MAX_LINE;i++){
		fgets(name[i],MAX_NAME,stdin);
	}

	return(i); /* このままだと、常にMAX_LINEを返してしまう! */
}
for文の繰り返しから抜けるのは、iが0から増えていって初めて i == MAX_LINE になったときだけですから、
常に return(MAX_LINE); になってしまいます。
ということでこんな感じに。

コード:

int readfile(char (*name)[MAX_NAME])
{
	int i;
	for(i=0;i<MAX_LINE;i++){
		if (fgets(name[i], MAX_NAME, stdin) == NULL) {
			break; /* もうstdinの最後まで読み込み終わったので、ループを抜ける */
		}
	}

	return i; /* これまでに読み込んだ行数を返す */
}
fgets関数は、入力データがもう無いのに読もうとするとNULLを返しますから、fgetsがNULLを返したか
どうかをif文で調べて、もしNULLだったら(つまり、もう入力データが尽きていたら)ループを抜けます。

次に、delcommaです。delcommaを呼び出す際、引数nには読み込んだ行数(つまりreadfileの戻り値)
を指定してあげましょう。その上で、delcommaではn行だけを処理するようにしてあげます。
こんな感じに。

コード:

void delcomma(char (*name)[MAX_NAME], int n)
{
    int i, j;
    for (i = 0; i < n; ++i) /* n行だけ繰り返す */
    {
        for (j = 0; !(name[i][j] == '\0' || name[i][j] == ','); ++j);
            /* ナル文字かカンマが見つかったらfor文を抜ける */
        name[i][j] = '\0';
    }
}
外側のfor文で、引数nを使っているのがミソです。

フェイ

Re: 問題が解けません

#70

投稿記事 by フェイ » 12年前

本当に何度も助けてくださりありがとうございます!
恐らく最後になります。

beatle様の言うとうりに書き換えて実行しました。
すると、結果が


Ackley 65.1
Baker 68.3
Keller 63.4
Brent 52.8
Jong 73.4
Goldberg 60.0
Forrest 60.6
Fletcher 73.8
Powell 55.9
Smith 69.6
Richardson 51.5
Martin 65.3
Wilson 84.4
Lawler 59.6
Reed 58.8
Holland 70.4
Jones 63.7

体重だけが残りました
これは体重だけは別の配列になってしまっているのでしょうか?

non
記事: 1097
登録日時: 13年前

Re: 問題が解けません

#71

投稿記事 by non » 12年前

現在のプログラムがどうなっているのか、全部載せてください。
スレッドが長くて、全部読んで解析するのは面倒ですから。
non

フェイ

Re: 問題が解けません

#72

投稿記事 by フェイ » 12年前

コード:



#include <stdio.h>

#define MAX_NAME 20
#define MAX_LINE 35

int main(void);
int readfile(char (*)[MAX_NAME]);
void delcomma(char (*)[MAX_NAME], int);
void write_array(char (*)[MAX_NAME], int);

int main(void)
{
 char name[MAX_LINE][MAX_NAME];
  int n;

  n = readfile(name);
    delcomma(name, n);
     write_array(name, n);

return 0;
}

int readfile(char (*name)[MAX_NAME])

{
  int i;
     for(i=0;i<MAX_LINE;i++){
        if(fgets(name[i],MAX_NAME,stdin)==NULL){
     break;
   }
 }
return i;
}

void write_array(char (*name)[MAX_NAME],int n)
{
  int i;
    for (i = 0; i < n; i++) printf("%s",name[i]);

return;
}

void delcomma(char (*name)[MAX_NAME],int n)
{
    int i,j;
    for (i = 0; i < n; ++i) {
        for (j = 0;!(name[i][j] =='\0'||name[i][j] == ','); ++j);

        name[i][j] = '\0';
    }


return;
}
 
です。

アバター
bitter_fox
記事: 607
登録日時: 13年前
住所: 大阪府

Re: 問題が解けません

#73

投稿記事 by bitter_fox » 12年前

フェイ さんが書きました:

コード:

#include <stdio.h>

#define MAX_NAME 20
#define MAX_LINE 35

int readfile(char (*name)[MAX_NAME])

{
  int i;
     for(i=0;i<MAX_LINE;i++){
        if(fgets(name[i],MAX_NAME,stdin)==NULL){
     break;
   }
 }
return i;
}

 
です。
主な問題点はMAX_NAME(厳密にはMAX_NAME-1)文字分、つまり20(厳密には19)文字分読み込んだ後から改行までが残ってしまっているためです。

コード:

Ackley,D.H.   181.5  65.1
123456789012345678901234567890
|-----------------||-----|
      name[0]       name[1]
fgetsを読んだ後に改行が来るまで読み捨てる処理を挟んでください。
もしくはscanfを使った方が楽かと

ところでwrite_array内でprintf("%s",name)となっていますがprintf("%s\n", name)でなくていいのですか?

フェイ

Re: 問題が解けません

#74

投稿記事 by フェイ » 12年前

読み捨てるとはどういう処理ですか?

%s\n
とすると表示が3行になってしまうためです。

アバター
bitter_fox
記事: 607
登録日時: 13年前
住所: 大阪府

Re: 問題が解けません

#75

投稿記事 by bitter_fox » 12年前

フェイ さんが書きました:読み捨てるとはどういう処理ですか?
一文字読み込んで\nでなかったらもう一回、一文字読み込んで\n出なかったら・・・としていって\nだったらループ終わりみたいな処理になると思います。
実際には正常に一行読み込めてるかをname[strlen(name)-1]が\nかどうかで調べる必要があるので手間がかかりますが
オフトピック
もっと言えば
・・・・・・・・・・EOF
となっていても対応できるように読み込んだ文字の比較はEOFに対してもしなければいけません。

素直にscanfを使った方がきれいに書けそうです。

フェイ さんが書きました:%s\n
とすると表示が3行になってしまうためです。

今のreadfileの仕様が問題ですので%s\nにしておいてください。もし%sでreadfileがしっかりと出来たら今度はすべてが一行で表示されてしまいます。

フェイ

Re: 問題が解けません

#76

投稿記事 by フェイ » 12年前

コード:

int readfile(char (*name)[MAX_NAME])
{
  int i;
     for(i=0;i<MAX_LINE;i++){
        if(fgets(name[i],MAX_NAME,stdin)==NULL){
      break;
     for(i=0;i<MAX_LINE;i++)
       
   }
 }
return i;
}

ここで詰まりました……
すみません…

non
記事: 1097
登録日時: 13年前

Re: 問題が解けません

#77

投稿記事 by non » 12年前

コード:

#define MAX_NAME 20
#define MAX_LINE 35

int main(void);
int readfile(char (*)[MAX_NAME]);
void delcomma(char (*)[MAX_NAME], int);
void write_array(char (*)[MAX_NAME], int);

int main(void)
{
	char name[MAX_LINE][MAX_NAME];
	int n;

	n = readfile(name);
	delcomma(name, n);
	write_array(name, n);

	return 0;
}
再度確認ですが、この部分は先生から与えられたもので変更不可ですよね。
特にこの数
#define MAX_NAME 20
だとすれば、直接nameにfgetsで読み込まず、別の配列 例えば char str[80];
に読み込んで、名前だけを、nameに入れるようにした方がいいですね。

または、bitter_foxさんがいわれるように、fgetsをやめて、scanfに変更する。

ところで、あれだけ言われても、インデントをしない理由はなんでしょうか?
non

アバター
bitter_fox
記事: 607
登録日時: 13年前
住所: 大阪府

Re: 問題が解けません

#78

投稿記事 by bitter_fox » 12年前

フェイ さんが書きました:

コード:

int readfile(char (*name)[MAX_NAME])
{
  int i;
     for(i=0;i<MAX_LINE;i++){
        if(fgets(name[i],MAX_NAME,stdin)==NULL){
      break;
     for(i=0;i<MAX_LINE;i++) // (*)
       
   }
 }
return i;
}

ここで詰まりました……
すみません…
まず(*)はどのブロックの中にいるか理解できていますか?もし理解できていないのであればインデントをしっかりとつけてみてください。
オフトピック
インデントを付けないというのは、命綱をつけずにロッククライミングをした後に、パラシュートやムササビスーツを着用せずに頂上から飛び降りるようなものです。
絶対に破たんします。
なので理解できていてもつけてください。
でもって、一回日本語で作りたいプログラムを書いてみてください。ソフト屋さんの
softya(ソフト屋) さんが書きました: 私からの提案としては、とりあえず日本語良いので次の3つをもっと細かく分解してみましょう。
私の提案では、日本語化→ソース化→関数化という手順を踏みます。
の実践です。
「~が~の時に~が~になるまで~を~する」などと言った感じです。
あるいは、
~が~ならば
:~が~になるまで
::~を~する
などの様に階層付けてプログラムに近い感じで書いても良いでしょう。

個人的にはこのままfgetsで行くよりもscanfを使った方が簡単だし、データフォーマットにも適していると思いますね。

フェイ

Re: 問題が解けません

#79

投稿記事 by フェイ » 12年前

前にも行っているとおり、初めてばっかりで理解も乏しいんです。 あと、数学的考えも苦手なので…
beatle様のように分かり易く教えて頂けませんか?
インデントは焦っていて忘れてしまいがちになっていました。
ほんとうにすみません……

アバター
bitter_fox
記事: 607
登録日時: 13年前
住所: 大阪府

Re: 問題が解けません

#80

投稿記事 by bitter_fox » 12年前

フェイ さんが書きました:前にも行っているとおり、初めてばっかりで理解も乏しいんです。 あと、数学的考えも苦手なので…
beatle様のように分かり易く教えて頂けませんか?
インデントは焦っていて忘れてしまいがちになっていました。
ほんとうにすみません……
答えがわかっても考えないと理解につながらないですよ。いつまでたっても分かるようにはなりません。

コード:

name[i]の最後が改行文字でなかったら
:一文字入力をして
::それが改行文字あるいはEOFでない間それを行う
日本語で書くとこのような感じでしょうか。

コード:

		if (name[i][strlen(name[i]) - 1] != '\n')
		{
			do
			{
				ch = getc();
			}
			while (ch != '\n' && ch != EOF);
		}
この部分をソース化すればこのような感じになるかと思います。
chはint型です。

ちなみにscanfを使えばもっと美しくて

コード:

scanf("%s%*lf%*lf", name[i])
でOKです。

最後にもう一回言いますが、出来なくても自分で考えることが大事です。
考えた結果がどうであれ考えた過程は必ず自分の糧になります。
筋トレに似ているでしょうか。筋トレはどれだけ重たいバーベルを持ち上げたかなど(つまり結果)には意味がありません。どれだけ筋繊維の損傷を与えれたか(つまり過程)に意味があります(どれだけと言っても損傷の与えすぎはよろしくないでしょうが・・・)。ましてや他人に筋トレをしてもらって他人の筋繊維に損傷を与えても自分の筋トレにはなりません。

non
記事: 1097
登録日時: 13年前

Re: 問題が解けません

#81

投稿記事 by non » 12年前

まず、scanfについて教科書を読むか、インターネットで検索して、使い方を調べてください。

今回のレコードは 名前、身長、体重が スペースで区切られているので
名前と、身長と体重に分けてscanfで読み込むことができます。
名前を入力する配列はnameがありますが、身長、体重を入れる変数は使わないけど用意しましょう。
さらに、scanfで読むデータがなくなったとき、(ファイルのEOFに達したとき)はscanfは何を返すのか
調べましょう。

(追)bitter_foxさんのscanfの書き方でもいいのですが、ダミーの変数に格納した方が初心者には
わかりやすいと思います。
non

フェイ

Re: 問題が解けません

#82

投稿記事 by フェイ » 12年前

もう、どうしたら良いか分かりません……
お願いですので
答えを教えて欲しいです。
我が儘で勝手な事だとは分かっています。
どうか、お願いします…

アバター
asd
記事: 319
登録日時: 13年前

Re: 問題が解けません

#83

投稿記事 by asd » 12年前

フェイ さんが書きました:もう、どうしたら良いか分かりません……
お願いですので
答えを教えて欲しいです。
我が儘で勝手な事だとは分かっています。
どうか、お願いします…
何が分からないのか分からないので、一度落ち着いて何が分からないのかを整理してみましょう。
アドバイスにあるscanfについては調べられたのでしょうか?

ここまででいろいろなアドバイスをしてくれた方がいるのに、そのアドバイスを無碍にするような言い方は
すごい失礼ですよ。
#貴方たちのアドバイスは分からないから答えだけくれって言っているわけですし

わがままで勝手なことだと理解しているなら答えだけを求めるのはやめませんか?
先に謝っておけばどんな失礼でも許されるということはありません。
Advanced Supporting Developer
無理やりこじつけ(ぉ

フェイ

Re: 問題が解けません

#84

投稿記事 by フェイ » 12年前

コード:

int readfile(char (*name)[MAX_NAME])
{
  int i,j,ch;
     for(i=0;i<MAX_LINE;i++){
        if(fgets(name[i],MAX_NAME,stdin)==NULL){
            break;

        if (name[i][strlen(name[i]) - 1] != '\n')
        {
         do{
         ch = getc(*name);
            } while (ch!='\n'&&ch!=EOF);
    }
   }
 } 
return i;
}
に更新してみました。

warning: incompatible implicit declaration of built-in function ‘strlen’
warning: passing argument 1 of ‘getc’ from incompatible pointer type

です。
おそらくポインタが違うような気がするのですが
どうしたら良いでしょうか?

アドバイスはかなり有り難く感じています。
ですが、時間がないのでscanf関数を使っている暇がないんです。

アバター
bitter_fox
記事: 607
登録日時: 13年前
住所: 大阪府

Re: 問題が解けません

#85

投稿記事 by bitter_fox » 12年前

フェイ さんが書きました: warning: incompatible implicit declaration of built-in function ‘strlen’
warning: passing argument 1 of ‘getc’ from incompatible pointer type

です。
おそらくポインタが違うような気がするのですが
どうしたら良いでしょうか?

アドバイスはかなり有り難く感じています。
ですが、時間がないのでscanf関数を使っている暇がないんです。
インデントをしっかりとつける気は毛頭ないという事でしょうか?
再掲です
bitter_fox さんが書きました: インデントを付けないというのは、命綱をつけずにロッククライミングをした後に、パラシュートやムササビスーツを着用せずに頂上から飛び降りるようなものです。
絶対に破たんします。
さて、プログラムの問題点ですがgetcという関数は引数を受け取りません。
bitter_fox さんが書きました:

コード:

        if (name[i][strlen(name[i]) - 1] != '\n')
        {
            do
            {
                ch = getc();
            }
            while (ch != '\n' && ch != EOF);
        }
これと見比べてみてください間違いに気づくはずです。
それからstrlenを使うときはstring.hをインクルードするかプロトタイプ宣言する必要がありますが、まぁなくても動くとは思います。

焦ってらっしゃいますけど提出日は8日じゃないんですか?
フェイ さんが書きました: 提出が8なんです
急速に必要になりました
よろしくお願いします

non
記事: 1097
登録日時: 13年前

Re: 問題が解けません

#86

投稿記事 by non » 12年前

MAX_NAME を 20から変更してはいけないのだから、fgetsを止めてscanfを使いましょうとアドバイスしているのに
なぜそうしないのですか?

8行目から13行目までは、scanfを使えば必要ありません。削除してください。
non

ISLe
記事: 2650
登録日時: 13年前
連絡を取る:

Re: 問題が解けません

#87

投稿記事 by ISLe » 12年前

MAX_NAMEを変更していけない流れになってますけど、質問者さんMAX_LINEは変更してますよね。

non
記事: 1097
登録日時: 13年前

Re: 問題が解けません

#88

投稿記事 by non » 12年前

ISLe さんが書きました:MAX_NAMEを変更していけない流れになってますけど、質問者さんMAX_LINEは変更してますよね。
あら本当だ。最初は20ですね。データは17行だから20のままで大丈夫ですね。なぜ、変更されたのかな。
non

フェイ

Re: 問題が解けません

#89

投稿記事 by フェイ » 12年前

こちらでどうにかする事が出来ました。
本当にありがとうございました!!

コードはちょっとあげる事が出来ませんが、
何度も相談に乗って頂きありがとうございました!

宿題スレ住人

Re: 問題が解けません

#90

投稿記事 by 宿題スレ住人 » 12年前

こちらで、じゃなくて2chの宿題スレで、じゃないですかね。
http://hibari.2ch.net/test/read.cgi/tec ... 62648/330-

アバター
asd
記事: 319
登録日時: 13年前

Re: 問題が解けません

#91

投稿記事 by asd » 12年前

フェイ さんが書きました: コードはちょっとあげる事が出来ませんが、
何度も相談に乗って頂きありがとうございました!
自分は答えのコードを求めておいて問題が解決したらそのコードは提示なしですか。
最後の最後までインデントは守らないところとかも含めあんまりじゃないですかね。
Advanced Supporting Developer
無理やりこじつけ(ぉ

閉鎖

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