1つだけ過去を変えられるとしたら?

データファイルの入力方法についての質問です。

フォーマットは以下↓の通り、1,2列目が日付,時間となっています。
(表記の都合上、半角スペースを_で置換しています。)
各行それぞれ3列目から最後の列までの和を計算したいと思っています。

問題点は以下の3点です
・1,2列目をとばしたい
・行によって列の数が異なる
・列の区切りのスペースの数がバラバラ

上の場合以外(つまりデータのみで列の数がそろっていて区切りも統一されている)
のファイルでしたらfscanfを使ってできます。
ご助言をよろしくお願いします。





2006/06/10____10:10:10____320.25____351.2____561.00___2646.00
2006/06/10____10:10:11____320.000___310.00___561.00
2006/06/10____10:10:12____320.000___310.00___561.00___2646.0
2006/06/10____10:10:13____320.000___310.00___561.0____2646.00
2006/06/10____10:10:14____320.0_____310.00___561.00___260.0
2006/06/10____10:10:15____310.00____561.00___2646.00
2006/06/10____10:10:16____320.00____310.00___561.00___2646.00
2006/06/10____10:10:17____320.000___310.00___561.0____2646.0
2006/06/10____10:10:18____310.0_____561.00___2646.00
2006/06/10____10:10:19____320.000___310.00___561.00___2646.0
2006/06/10____10:10:20____320.000___310.00___561.00___2646.00



_

A 回答 (8件)

No.1です。


再び考えてみました。これなら理論的に何列・何行でも合計が計算できると思います。
ただ結果は出ますがプログラムがスマートでない!
もうちょっと考える余地があるかもしれません。
でも、何千・何万も列があるデータっていったい…

#include<stdio.h>

void main(void)
{
char date[12],time[10];
double data,total;
int col,c;
FILE *fp;

fp = fopen("sample.dat", "rt");

do {
fscanf(fp, "%s %s", date, time);
col = 0;
total = 0.0;
while ((c = getc(fp)) != '\n' && feof(fp) == 0) {
ungetc(c, fp);
col += fscanf(fp, "%lf", &data);
total += data;
}
if (col)
printf("%s %s (%d) %.3lf\n", date, time, col, total);
} while (feof(fp) == 0);

fclose(fp);
}
    • good
    • 0
この回答へのお礼

ご親切に2度のもの投稿ありがとうございます。
すばらしいですね。
無事に動作し、問題を解決することができました。

お礼日時:2006/06/11 22:16

Ano.6 を書いたものです。


失礼しました。カラムごとの合計と勘違いしました。
全部の合計で良いのなら、Ano.7のプログラムで正解ですね。
ただし、行末に空白が入っていると不味いですが。
    • good
    • 0
この回答へのお礼

2度のもの投稿ありがとうございます。
みなさまのご親切に感謝いたします。

お礼日時:2006/06/11 22:17

strtokなどを使わずにかいてみるとこんな感じになります。


空白(または改行)で区切られた文字列を「カラム」として、それを読み込んでくる手続きを使っています。
ungetcとかをつかっていて、教科書的に言うと悪いプログラムですが。
なお、質問の例示された以外の文字が混入しているとかカラム数が1の行があるとか、空行場合などの処理はしていません。
#include <stdlib.h>
#include <ctype.h>

#define MAXCOL 70000
double sums[MAXCOL];
#define MAXCOLLEN 1024

int getcolumn( char *data)
{
int ch;
do {
ch=getchar();
}while(ch==' ');
if(ch==EOF)
return -1;
if(ch=='\n')
return 0;
while(!isspace(ch)){
*data++ = ch;
ch=getchar();
if(ch==EOF)return EOF;
}
ungetc(ch, stdin);
*data = '\0';
return 1;
}

main()
{
int col, maxcol,r;
double num;
char data[MAXCOLLEN];
col=maxcol=0;
(void)getcolumn(data);
(void)getcolumn(data);
while((r=getcolumn(data))!=EOF) {
if(r==0) {
col=0;
(void)getcolumn(data);
(void)getcolumn(data);
} else {
sscanf(data,"%lf", &num);
sums[col]+= num;
printf("%d %g\n", col, sums[col]);
if(++col>maxcol)
maxcol=col;
}
}
for(col=0;col<maxcol;col++)
printf("%g\n", sums[col]);
return 0;
}
    • good
    • 0

プログラミングの初心者というなら、プログラムを組むことそれ自体に意味があるならともかく、使う道具を選ぶのは大切かと。


たとえば awk なら、例にあるデータの場合

{
 sum = 0
 for (i=3; i<=NF; i++)
  sum += $i

 printf "%d行目のデータの合計は %6.3fです。", FNR, sum
}

こんだけですむんですが。
    • good
    • 0
この回答へのお礼

ありがとうございます。
そうですね、確かに同感です。
本質的でないところでつまずくのはもったいない気がします。
awkというものも調べてみます。

お礼日時:2006/06/11 08:57

 


 訂正
>for(i = 1; (data = strtok(NULL, TOKEN)) != NULL; i ++){
>if(i >= 2){

for(i = 2; (data = strtok(NULL, TOKEN)) != NULL; i ++){
if(i > 2){
 
    • good
    • 0

和の計算をしたいとのことですが、


awkとかperlとかrubyとかpythonとか使っちゃいかんのですか?

この回答への補足

回答ありがとうございます。
現在の私の知識はC言語の初歩程度しかありません。
できればCを使ってやりたいと思っています。

補足日時:2006/06/11 01:22
    • good
    • 0

 


#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define TOKEN " \n"

int main(void)
{
FILE *fp;
char str[256];
char *data;
int i, j;
float sum;

if((fp = fopen("data.txt","r")) == NULL){
puts(" File Open Error");
exit(1);
}
for(j = 1; fgets(str, 256, fp) != NULL; j ++){
if((data = strtok(str, TOKEN)) == NULL) continue;
printf(" Line(%d) ", j);
sum = 0;
for(i = 1; (data = strtok(NULL, TOKEN)) != NULL; i ++){
if(i >= 2){
printf(" %s ", data);
sum += atof(data);
}
}
printf(" Sum == %.2f\n", sum);
}
return 0;
}
    • good
    • 0
この回答へのお礼

回答ありがとうございます。
見慣れない関数がたくさん出てきて、解読に時間がかかりそうです。
がんばってみます。

お礼日時:2006/06/11 01:22

C言語しかわかりませんが、自分の勉強の意味も含めてプログラムを書いてみました。


fscanf()で直接ファイルから読み込もうとすると改行も区切り文字とみなしてしまう
らしくうまくいきませんでした。
以下のように一度 fgets() で buf に行ごと読み込んでそれを sscanf() でデータに
分けると、うまく読み込めて読み込んだデータの個数も知ることができます。

以下はご質問のデータが sample.dat というファイルにあるとして各行を読み込み、
データの個数とそのデータの合計を表示するだけのものですが、参考になればと思い
そのままのかたちで載せておきます。
1・2列目は %*s で完全に無視しています。
行頭の空白が削られることがあるので見にくくなるかも知れません。
ただし、エラー処理が不十分であることや即値を使っているなど、結果は出るものの
プログラムとしては不完全です。

#include<stdio.h>

void main(void)
{
char buf[128];
float data[4],total;
int col,i;
FILE *fp;

fp = fopen("sample.dat", "rt");
while (fgets(buf, 128, fp) != NULL) {
col = sscanf(buf, "%*s %*s %f %f %f %f", data, data + 1, data + 2, data + 3);
printf("(%d) ", col);
total = 0.0;
for (i = 0; i < col; i++)
total += data[i];
printf("%9.3f\n", total);
}
fclose(fp);
}
    • good
    • 0
この回答へのお礼

回答ありがとうございます。
誤解を生んでしまう書き方をしてしまいましたが、
実際に扱うデータでは数字列の最大数は4ではありません(65536列以上ある行もある)。
ですので改行を読み込んだら~というものを使わなければいけないかなと思っています。

お礼日時:2006/06/11 01:21

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