みんなの「教えて(疑問・質問)」にみんなで「答える」Q&Aコミュニティ

こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

締切り済みの質問

Cプログラム ファイルの書き込み→読み込み

#include<stdio.h>
void p07a(char *name);
void p07b(char *name);

//メイン関数
int main()
{
char name[100];
printf("File Name?");
scanf("%s",name);
//ファイルへの書き込み
p07a(name);
//ファイルからの書き込み
p07b(name);
puts("!!!!!END!!!!!");
return(0);
}
//ユーザー関数
void p07a(char *name)
{
while(1)
{
int a,b;
FILE *fp;
fp=fopen("name","w");
scanf("%d,%d",&a,&b);
fclose(fp);
}
}

void p07b(char *name)
{
int i,a[i],b[i],sum,sumb,aave,bave;
FILE *fp2;
i=0;
sum=0;
sumb=0;
while((fscanf(fp2,"%d,%d",&a[i],&b[i]))!=EOF){
sum+=a[i];
sumb+=b[i];
i++;
}
aave=sum/i;
bave=sumb/i;

fclose(fp2);
}
のプログラムなのですが、書き込むファイル名を入力しても次の処理へ進みません
ユーザー関数がおかしいのでしょうか?

投稿日時 - 2011-06-29 17:10:17

QNo.6843245

困ってます

このQ&Aは役に立ちましたか?

0人が「このQ&Aが役に立った」と投票しています

回答(6)

ANo.6

No.4様、ご指摘ありがとうございます。
新しいC言語規格には疎いもので助かります。

ひょっとして、次の指摘も新しいものでOKだったりしたら、カッコ悪いのですが…

ヤボを承知でお聞きしますが、No.5の方

char name[MAX / 2];
なのに、
fgets(name, MAX - 1, stdin);
は、大丈夫なのですか?

他にもコンパイルすら通らない部分がありますが・・・

投稿日時 - 2011-07-02 23:59:59

ANo.5

>while(1){
>__int a,b;
>__FILE *fp;
>__fp=fopen(name,"w"); //←訂正
>__scanf("%d,%d",&a,&b);
>__fclose(fp);
>}
>のプログラムなのですが、書き込むファイル名を入力しても次の処理へ進みません
>ユーザー関数がおかしいのでしょうか?

次へ進むもなんの、while(1) の無限ループです。次へ進まないようにプログラムされています。よって、抜本的な改良が必要です。
質問は「Cプログラム ファイルの書き込み→読み込み」ということですので、その1例を示すことにします。

要点は、データは fgets() で一括読み込み、strtok() を用いて各データ項に応じて数値(文字列)などを分離・取り込み、fprintf() の書式付き出力を行うプログラム例にあります。あなたの回答プログラムと何処がどのように違うかを確認して下さい。
なお、簡単な入力ミスに対応したプログラム例ともしてありますので、確認してください。
ファイルの読み込みについては、単に読み込むだけの処理となっています。というのも、プログラムが大きくなるとエラー確認が不明瞭になりがちなので、処理を単純にすることでプログラムの見通しが良くなるからです。

ここでは、データ入力の p07a() 関数、データファイル読み込みの p07b() 関数、そして計算の p07calc() 関数の3つに別けてプログラムしてあります。配列の受け渡しなど、ひとつの事例として参照してください。





#include <stdio.h> // fopen(), fclose(), fgets()
#include <stdlib.h> // exit(), atoi()
#include <string.h> // strtok()
#define SIZE 128 // fgets() 関数用
#define MAX 100 // ファイル名用
/* 使用関数のプロトタイプ宣言 */
void p07a(char *name);
int p07b(char *name, int a[], int b[]);
void p07calc(int n, int a[], int b[]);

//メイン関数
int main(void)
{
int a[MAX], b[MAX], n;
char name[MAX / 2];
printf("File Name? ");
fgets(name, MAX - 1, stdin);
strtok(name, "\n");
//ファイルへの書き込み
p07a(name);
//ファイルからの読み込み
printf("Result\n");
n = p07b(name, a, b);
//計算
p07calc(n, a, b);
puts("!!!!!END!!!!!");
return 0;
}

//ユーザー関数
void p07a(char *name)
{
char buff[SIZE], *tp;
FILE *fp;
int i,a,b;
if((fp=fopen(name,"w+")) == NULL){
fprintf(stderr, "Can't open error.\n");
exit(EXIT_FAILURE);
}
i = 0;
printf("Loop end: Push return key only.\n");
printf("%d> ", ++i);
while(*fgets(buff, SIZE - 1, stdin) != '\n'){
a = atoi(strtok(buff, " ,"));
/* for input miss */
if((tp = strtok(NULL, " \n")) == NULL) {
fgets(buff, SIZE-1, stdin);
tp = strtok(buff, "\n");
}
b = atoi(tp);
fprintf(fp, "%d %d\n", a, b);
printf("%d> ", ++i);
}
fclose(fp);
}

void p07b(char *name, int a[], int b[])
{
int i = 0;
FILE *fp;
if((fp=fopen(name,"r")) == NULL){
fprintf(stderr, "Can't open error.\n");
exit(EXIT_FAILURE);
}
while(fscanf(fp,"%d %d", &a[i], &b[i]) != EOF){
if(++i >= MAX) {
fprintf(stderr, "Buffer overflow error.\n");
exit(EXIT_FAILURE);
}
}
fclose(fp);
return i;
}

void p07calc(int n, int a[], int b[])
{
int i, sum_a, sum_b;
float a_ave, b_ave;
printf("Result\n");
sum_a = sum_b = 0;
for(i = 0; i < n; i++){
printf("%d: %d %d\n", i+1, a[i], b[i]);
sum_a += a[i];
sum_b += b[i];
}
*a_ave = (float)sum_a / i;
*b_ave = (float)sum_b / i;
printf("a= %.2f b= %.2f\n", a_ave, b_ave);
}


/* --- 実行結果例 ---
File Name? dat.txt
Loop end: Push return key only.
1> 90 85
2> 85 92
3> 78
87    ← 再追加入力
4>    ← return キーでループ脱
Result
1: 90 85
2: 85 92
3: 78 87
a= 84.33 b= 88.00
!!!!!END!!!!!
*/

投稿日時 - 2011-07-02 20:04:41

ANo.4

今の C ならブロックスコープで「大きさを変数で指定した配列」を定義することもできます. つまり, 変数 i に対して
int a[i];
が可能です>#2.

まあ, 今挙がっているプログラムではダメですが.

投稿日時 - 2011-06-30 00:03:36

ANo.3

どのように変更したのかわかりませんが、よく良く調べてみてください。

>fprint /var/tmp//ccbQWkDf.o

fprintというシンボルは標準的にはありません。

投稿日時 - 2011-06-29 23:17:56

ANo.2

No.1氏の指摘の意味がご理解出来ていないようなので。

int a[i];

こういう宣言はできません。
配列のサイズは、定数でなければいけません。コンパイル時に大きさが決定している必要があります。

投稿日時 - 2011-06-29 19:13:52

お礼

ありがとうございます

No1の方の指摘で修正したのですが、
未定義の 最初に参照している
シンボル ファイル
fprint /var/tmp//ccbQWkDf.o
ld: 重大なエラー: シンボル参照エラー。P07 に書き込まれる出力はありません。
collect2: ld はステータス 1 で終了しました
のようなエラーがでてしまった時はどうすればよいでしょうか?

投稿日時 - 2011-06-29 22:26:51

ANo.1

・p07a()が無限ループするのでループを抜ける条件を追加する
・p07a()でfopenしているファイル名がnameになっているので、""を外す
・p07a()で入力した値をファイルに書き込んでいないので書きこむ処理を追加する
・p07b()でファイルオープンが抜けてるので追加する
・p07b()でa[i]、b[i]でコンパイルエラー、またファイルから読み込んで
 sum、sumbに追加するだけの一時バッファなので配列にする必要ない

投稿日時 - 2011-06-29 17:34:51

お礼

ありがとうございます

>>p07b()でa[i]、b[i]でコンパイルエラー、またファイルから読み込んで
 sum、sumbに追加するだけの一時バッファなので配列にする必要ない
これは課題で配列にするという条件なので配列にしています

投稿日時 - 2011-06-29 18:14:22

あなたにオススメの質問