アルゴリズムの授業で出された課題で,
8:34,>>,>>,>>,>>,>>,9:06,>>,>>,>>,>>,>>,>>,9:28,>>,>>,>>,9:39
9:33,>>,>>,>>,>>,>>,10:00,>>,>>,>>,>>,>>,>>,10:23,>>,>>,>>,10:35
8:39,8:44,8:49,9:02,9:07,9:12,9:17,9:21,9:28,9:32,9:36,9:41,9:45,9:51,9:56,10:01,10:04,10:09
,,,,,,8:54,8:59,9:05,9:09,9:12,9:24,9:28,9:35,9:40,9:45,9:48,9:53
この要領でcsvファイルに18*48行に渡って記されている時刻を
構造体
typedef struct CELL{
int hour;
int min;};
に定義され,main関数で宣言された
struct CELL jikoku[18][48];
に、時間、分と的確に格納する関数を定義しようとしてます.
自分でしらべてfgetsでファイルfpから1行ずつ取得のお約束に
sscanfでやってみましたが空白や>>のパターンの多さに苦戦してできませんでした.
分解して格納使用かと考えたのですが調べても見つからず,学校ではrndくらいしかやってないので全くわかりません。
どなたか分解の仕方,またどう分解されるかなど教えていただけないでしょうか。
csvファイルからの取得
- bitter_fox
- 記事: 607
- 登録日時: 15年前
- 住所: 大阪府
Re: csvファイルからの取得
これはstrtokを使うと簡単に分解できますね。kana さんが書きました:アルゴリズムの授業で出された課題で,
8:34,>>,>>,>>,>>,>>,9:06,>>,>>,>>,>>,>>,>>,9:28,>>,>>,>>,9:39
分解して格納使用かと考えたのですが調べても見つからず,学校ではrndくらいしかやってないので全くわかりません。
どなたか分解の仕方,またどう分解されるかなど教えていただけないでしょうか。
http://www9.plala.or.jp/sgwr-t/lib/strtok.html
http://www1.cts.ne.jp/~clab/hsample/Func/Func08.html
-
kana
Re: csvファイルからの取得
bitter_foxさん、アドバイスありがとうございます。
8:34,>>,>>,>>,>>,>>,9:06,>>,>>,>>,>>,>>,>>,9:28,>>,>>,>>,9:39
9:33,>>,>>,>>,>>,>>,10:00,>>,>>,>>,>>,>>,>>,10:23,>>,>>,>>,10:35
8:39,8:44,8:49,9:02,9:07,9:12,9:17,9:21,9:28,9:32,9:36,9:41,9:45,9:51,9:56,10:01,10:04,10:09
,,,,,,8:54,8:59,9:05,9:09,9:12,9:24,9:28,9:35,9:40,9:45,9:48,9:53
の各行をchに格納しstrtokを使ってみました
これを応用してforループで18*48行分格納できるよう繰り返させたかったのですが、
まず上記の最初の検出の際、どうも4行目の時刻のような場合は、,,,,,,を飛ばしていきなり8:54から検出されてしまいます.
ここではelseの方にひっかけたいのですが、どこを訂正したらいいでしょうか?
8:34,>>,>>,>>,>>,>>,9:06,>>,>>,>>,>>,>>,>>,9:28,>>,>>,>>,9:39
9:33,>>,>>,>>,>>,>>,10:00,>>,>>,>>,>>,>>,>>,10:23,>>,>>,>>,10:35
8:39,8:44,8:49,9:02,9:07,9:12,9:17,9:21,9:28,9:32,9:36,9:41,9:45,9:51,9:56,10:01,10:04,10:09
,,,,,,8:54,8:59,9:05,9:09,9:12,9:24,9:28,9:35,9:40,9:45,9:48,9:53
の各行をchに格納しstrtokを使ってみました
tp = strtok(ch, "," );
if(tp != NULL || tp != ">>")
sscanf(tp,"%d:%d",jikoku[0][0].hour,&jikoku[0][0].min);
else { jikoku[0][0].hour=NULL;
jikoku[0][0].min=NULL;}
まず上記の最初の検出の際、どうも4行目の時刻のような場合は、,,,,,,を飛ばしていきなり8:54から検出されてしまいます.
ここではelseの方にひっかけたいのですが、どこを訂正したらいいでしょうか?
- bitter_fox
- 記事: 607
- 登録日時: 15年前
- 住所: 大阪府
Re: csvファイルからの取得
NULLはポインタですので本来はポインタに対してのみ用いられるべきです。ですので、NULLをint型に代入するのは控えるべきです。kana さんが書きました:これを応用してforループで18*48行分格納できるよう繰り返させたかったのですが、tp = strtok(ch, "," ); if(tp != NULL || tp != ">>") sscanf(tp,"%d:%d",jikoku[0][0].hour,&jikoku[0][0].min); else { jikoku[0][0].hour=NULL; jikoku[0][0].min=NULL;}
まず上記の最初の検出の際、どうも4行目の時刻のような場合は、,,,,,,を飛ばしていきなり8:54から検出されてしまいます.
ここではelseの方にひっかけたいのですが、どこを訂正したらいいでしょうか?
(恐らく0という意味で使ってるのかと思うのですが処理系によってはNULLが0でない可能性もあるのでよろしくありません)
それからjikokuを0で初期化しておけばelseに0を代入する文を入れる必要はなくなりますね。
あと、tp != ">>"はかなりの確率で真となってしまいますよ。
というのも、比較演算子は値の比較です。ですので、この際に比較しているのはtpのアドレスと">>"のアドレスを比較しているのであって中身を比較しているのではありません。
中身の比較にはstrcmpを用いてください。
http://www9.plala.or.jp/sgwr-t/lib/strcmp.html
本題のstrtokですが、strtok相当の,,を飛ばさない関数を作るか、strtokを実行する前に今変換してる物の末尾のアドレスを残しておいてstrtokの戻り値を比較することによって飛ばされた数を算出すればよいのではないでしょうか?
// _はヌル文字('\0')
+----------------+
|1234567890123454|
+----------------+
|8:54,,,16:24,...| // 元
+----------------+
|8:54_,,16:24,...|
| ^ | // strtokを行う前に今変換している物の末尾(直近の\0)のアドレスを残しておく
+----------------+
|8:54___16:24,...| // strtok実行、戻り値は後ろの^に当たるところを指してる
| ^ ^ | // 前の^と後の^を比較することで飛ばされた数を算出する
+----------------+
それからインデントをしっかりと行わないとバグの温床になってしまったり、何が書いてあるのか分からなくなったりするのでしっかりと行ってください。
Re: csvファイルからの取得
,,,,,,8:54,8:59,9:05,9:09,9:12,9:24,9:28,9:35,9:40,9:45,9:48,9:53
1行読んだ後、中身をサーチして、上記のような場合は
>>,>>,>>,>>,>>,>>,8:54,8:59,9:05,9:09,9:12,9:24,9:28,9:35,9:40,9:45,9:48,9:53
に変換してからstrtokする、という方法はどうでしょうか。
変換するロジックは自分で考えないといけませんけれど。
1行読んだ後、中身をサーチして、上記のような場合は
>>,>>,>>,>>,>>,>>,8:54,8:59,9:05,9:09,9:12,9:24,9:28,9:35,9:40,9:45,9:48,9:53
に変換してからstrtokする、という方法はどうでしょうか。
変換するロジックは自分で考えないといけませんけれど。
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。
プログラムは思ったとおりには動かない。書いたとおりに動く。
-
かずま
Re: csvファイルからの取得
scanf を使えばよいのでは?
#include <stdio.h>
#define N_COL 18
#define N_LINE 48
struct CELL { int hour, min; };
int get(struct CELL *p, FILE *fp)
{
int c;
p->hour = p->min = 0;
fscanf(fp, "%d:%d", &p->hour, &p->min);
while (c = getc(fp), c != EOF && c != ',' && c!= '\n') ;
return c == EOF;
}
int main(void)
{
struct CELL jikoku[N_LINE][N_COL]; int i, j, n;
for (i = 0; i < N_LINE; i++)
for (j = 0; j < N_COL; j++) {
if (get(&jikoku[i][j], stdin)) break;
}
if (i < N_LINE) fprintf(stderr, "less data\n");
n = i;
for (i = 0; i < n; i++) {
for (j = 0; j < N_COL; j++)
printf(" %d:%02d", jikoku[i][j].hour, jikoku[i][j].min);
printf("\n");
}
return 0;
}