任意の空白で区切られた文字情報の読み出し

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

任意の空白で区切られた文字情報の読み出し

#1

投稿記事 by slei » 14年前

たびたび申し訳ありません、またしてもどうにもこうにもわからなくなってしまい質問させていただきたく・・・・・・
あるデータファイルを読み込み、指定した任意の月のスケジュールをすべて表示するプログラムを作成せよ、との課題なのですが
データファイルに含まれる月・日・メモの3つの情報は任意の空白で区切られており、すべて半角英数で記述されています。
これら3つの情報を分けて取得するための処理にミスがあることはデバッグで想定がついたのですが、どのように修正すればいいかがわからずに困っています。
(構造体は利用する条件となっています)
どうかアドバイスをお願いします。

コード:

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

struct schedule{
  int month;
  int mday;
  char memo[80];
};

int main()
{ 
  FILE *fp;
  int mon ;  /* 入力月 */
  struct schedule list; /* 構造体 */
  int x; /* 読み込み管理 */
  int i = 0; /* 文字管理 */
  int hit = 0; /* listにかかったか */
  int flug; /* ループ管理フラグ */
  char cmonth[5];
  char chk = ' '; /* 1文字前の管理 */
  char chk2; /* 2文字前の管理 */

  fp = fopen("schedule.dat", "r"); /* データベースを開く */

  printf("What month do you want to check? [1-12] : ");
  scanf("%d", &mon); /* 月入力 */

  if(mon == 1)  /* 月を英語表記にする処理 */
    strcpy(cmonth,"Jan");

  else if(mon == 2)
    strcpy(cmonth,"Feb");

  else if(mon == 3)
    strcpy(cmonth,"Mar");

  else if(mon == 4)
    strcpy(cmonth,"Apr");

  else if(mon == 5)
    strcpy(cmonth,"May");

  else if(mon == 6)
    strcpy(cmonth,"Jun");

  else if(mon == 7)
    strcpy(cmonth,"Jul");

  else if(mon == 8)
    strcpy(cmonth,"Aug");

  else if(mon == 9)
    strcpy(cmonth,"Sep");

  else if(mon == 10)
    strcpy(cmonth,"Oct");

  else if(mon == 11)
    strcpy(cmonth,"Nov");

  else if(mon == 12)
    strcpy(cmonth,"Dec");

  else{
    printf("month error.\n");
    return -1;}

  while((x = getc(fp)) != EOF){  /* 検索処理 */
      if(x == ' ' && chk != ' ' && flug == 0){ /* 月処理 */
	if(chk2 != ' ') /* 2文字前が空白でない(数字) */
	  list.month = (int)chk + (int)chk2 * 10; /* 桁あげ処理して加算 */
	else
	  list.month = (int)chk;
	flug = 1;}

      if(x == ' ' && chk != ' ' && flug == 1){ /* 日処理 */
	if(chk2 != ' ')
	  list.mday = (int)chk + (int)chk2 * 10;
	else
	  list.mday = (int)chk;
	flug = 2;}

      chk2 = chk; /* 2文字前になる文字を代入 */
      chk = x; /* 次に前の文字となる文字を代入 */

      printf("%d %d %d\n",list.month,list.mday, flug); /* デバッグ用 */
 
      if(flug == 2){ /* メモ処理 */
	while(x != '\n'){ /* 改行に達するまで */
	  list.memo[i] = x;
	  i++;}
	list.memo[i] = '\0';
	i = 0;
	flug = 0;
	if(mon == list.month){ /* 入力つきと読んだデータの月が一致した場合 */
	  printf("%s %d : %s\n",cmonth,list.mday,list.memo);
	  hit++;}
      }
   }

  if(hit == 0) /* 一致がなかった場合 */
    printf("schedule is nothing.\n");
	
  fclose(fp); /* ファイルを閉じる */
  return 0;
}

読み出すデータファイル

1 1 New Year's Day
1 14 Coming-of-Age Day
2 11 National Foundation Day
3 21 Vernal Equinox Day
4 29 Greenery Day
5 3 Constitution Day
5 5 Children's Day
7 20 Marine Day
9 15 Respect-for-the-Aged Day
9 23 Autumnal Equinox Day
10 14 Sports Day
11 3 Culture Day
11 23 Labor Thanksgiving Day
12 23 The Emperor's Birthday
(掲示板の仕様か消えていますが、1~9の月の前に半角スペースがあり、日の前にも列揃えの任意の半角スペースがあります)

実行結果

What month do you want to check? [1-12] : 1
191 0 0 (char型とint型の受け渡し・ループ処理などに問題あり?)
191 0 0
49 49 2
(入力待ち状態)(メモ処理の辺りで無限ループに入った?)

アバター
h2so5
副管理人
記事: 2212
登録日時: 14年前
住所: 東京
連絡を取る:

Re: 任意の空白で区切られた文字情報の読み出し

#2

投稿記事 by h2so5 » 14年前

char型の変数をint型にキャストした場合、文字コード番号に変換されてしまいますよ。

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

Re: 任意の空白で区切られた文字情報の読み出し

#3

投稿記事 by box » 14年前

1文字前とか2文字前とかの管理って、何をしてるんでしょうね。

schedule.datっていうファイルをオープンできなくても強引に処理を進めちゃってますが、いいんでしょうか。

月を英語表記にするという、たったそれだけのことが、
プログラム全体の中ですっごくメジャーな位置を占めてしまっているように思えます。
もっと簡単に書けるはずです。

字下げのやり方や閉じカッコ } の位置が独特すぎて、何だか読みづらいです。

flugっていう英単語があるんですか?flagなら知ってますけど。
最後に編集したユーザー box on 2011年5月26日(木) 21:30 [ 編集 1 回目 ]
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

フリオ

Re: 任意の空白で区切られた文字情報の読み出し

#4

投稿記事 by フリオ » 14年前

 ファイルを読み込むのはこれで良いんじゃないでしょうか。

コード:

#include <stdio.h>

int main(void)
{
	char s[128];
	int m, n;
	FILE *fp;
	
	if(!(fp = fopen("test000.txt", "r"))) return 1;
	while(fscanf(fp, "%d %d %[^\n]", &m, &n, s) == 3) printf("%2d/%2d \"%s\"\n", m, n, s);
	fclose(fp);
	return 0;
}

slei

Re: 任意の空白で区切られた文字情報の読み出し

#5

投稿記事 by slei » 14年前

h2so5 さんが書きました:char型の変数をint型にキャストした場合、文字コード番号に変換されてしまいますよ。
なるほど・・・・・・atoiは使えなかったので、この場合何を使えばいいんでしたか・・・・・・
box さんが書きました: 1文字前とか2文字前とかの管理って、何をしてるんでしょうね。

schedule.datっていうファイルをオープンできなくても強引に処理を進めちゃってますが、いいんでしょうか。

月を英語表記にするという、たったそれだけのことが、
プログラム全体の中ですっごくメジャーな位置を占めてしまっているように思えます。
もっと簡単に書けるはずです。

字下げのやり方や閉じカッコ } の位置が独特すぎて、何だか読みづらいです。

flugっていう英単語があるんですか?flagなら知ってますけど。
1字前、2字前はこのプログラムを書いた想定だと空白を読み込んだときに前も空白、というのでなければ月か日の数字を読んだと考えて処理に入るというフラグ的な仕事と前に読んだ数字をとっておいてまた呼び出す一時保存場所的な想定でした。
そういえばファイルオープンに失敗したときの処理を入れるのを忘れていましたね・・・・・・ちゃんと癖つけないといけませんね、ありがとうございます。
記述が乱雑というのはそのとおりですね、もっと簡潔に書けるよう努力します。
flugは・・・・・・スペルミスですね・・・・・・英語苦手なのに無理に使うからですね、お恥ずかしい・・・・・・
フリオ さんが書きました: ファイルを読み込むのはこれで良いんじゃないでしょうか。

コード:

#include <stdio.h>

int main(void)
{
char s[128];
int m, n;
FILE *fp;

if(!(fp = fopen("test000.txt", "r"))) return 1;
while(fscanf(fp, "%d %d %[^\n]", &m, &n, s) == 3) printf("%2d/%2d \"%s\"\n", m, n, s);
fclose(fp);
return 0;
}
あぁ、fscanfを改行コードをキーにして区切る方法がありましたか・・・・・・
ありがとうございます。
一度固まるとなかなかそれから離れられなくなって、もっと柔軟に考えないといけませんね・・・・・・

slei

Re: 任意の空白で区切られた文字情報の読み出し

#6

投稿記事 by slei » 14年前

フリオ さんが書きました: ファイルを読み込むのはこれで良いんじゃないでしょうか。

コード:

#include <stdio.h>

int main(void)
{
	char s[128];
	int m, n;
	FILE *fp;
	
	if(!(fp = fopen("test000.txt", "r"))) return 1;
	while(fscanf(fp, "%d %d %[^\n]", &m, &n, s) == 3) printf("%2d/%2d \"%s\"\n", m, n, s);
	fclose(fp);
	return 0;
}
すみません、また初歩的なことかもしれませんが追加で質問いいでしょうか?
whileのループ条件になっている3は何を指したものなのでしょうか?文字読み込みの制御はEOFぐらいしかよくわかっていなくて・・・・・・

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

Re: 任意の空白で区切られた文字情報の読み出し

#7

投稿記事 by box » 14年前

slei さんが書きました: whileのループ条件になっている3は何を指したものなのでしょうか?
「fscanf 戻り値」あたりでググるか、お手元に文法書があればそれで調べるかすれば、
すぐにわかると思います。
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

slei

Re: 任意の空白で区切られた文字情報の読み出し

#8

投稿記事 by slei » 14年前

アドバイスをもとに、一応想定するような動作を組むことはできました。本当にありがとうございます。
ただ自分自身で仕様を把握し切れていない面があるので、改めていろいろと調べてみたいと思います。

閉鎖

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