【掲示板ご利用上の注意】

 ※題名は具体的に!
 ※学校の課題の丸投げ禁止!
 ※ソースの添付は「HTML変換ツール」で字下げ!
 ※返信の引用は最小限に!
 ※環境(OSとコンパイラ)や症状は具体的に詳しく!
 ※マルチポスト(多重投稿)は慎んで!

 詳しくはこちら



 本当はこんなに大きく書きたくはないのですが、なかなか守っていただけなくて…。
 守ってくださいね。お願いします。(by管理人)

C言語ソース⇒HTML形式ツール   掲示板2こちら


管理者用メニュー    ツリーに戻る    携帯用URL    ホームページ    ログ    タグ一覧

No.20739

コマンドラインでオプションとして指定された処理をする
投稿者---ひか(2005/04/22 13:04:41)


未熟者のためたびたびスイマセン。
コマンドラインからファイルを指定し、コマンドラインのオプションとして-eを指定された時出力から空行を削除をし、-lなら小文字に変換し、-uなら大文字に変換するというのを作っています。ただし-lまたは-uと-eは同時に使え、-uと-lは同時には使えないです。

大文字、小文字はわかるのですが空行がわかりません。
判定として\nが連続したら空行ということはわかるのですが、その後の削除する処理ができませんでした。
以下かいてみたソースです。

#include <ctype.h>
#include <stdio.h>
#include <unistd.h>

int     vanilla_filter(FILE *);
int     toupper_filter(FILE *);
int     tolower_filter(FILE *);

int
vanilla_filter(FILE *fp)//入力したものをそのまま出力
{
  int   c;

  while ((c = getc(fp)) != EOF) {//ファイル終端まで
    if (putchar(c) == EOF) {//文字列なし
      return -2;
    }
  }
  if (!feof(fp)) {//fpでファイルの終わりにならないと
    return -1;
  }
  return 0;
}

int
toupper_filter(FILE *fp)//小文字から大文字
{
  int   c;

  while ((c = getc(fp)) != EOF) {//ファイル終端まで
    if (putchar(toupper(c)) == EOF) {//文字列なし(おわり)
      return -2;
    }
  }
  if (ferror(fp)) {//fpでエラーが発生したら
    return -1;
  }
  return 0;//問題なく進めた
}

int
tolower_filter(FILE *fp)//大文字から小文字
{
  int   c;

  while ((c = getc(fp)) != EOF) {
    if (putchar(tolower(c)) == EOF) {
      return -2;
    }
  }
  if (ferror(fp)) {
    return -1;
  }
  return 0;
}

int deli_filter(FILE *fp)
{
  int c;
  while ((c = getc(fp)) != EOF){
    if (c == '\n' && c+1 == '\n'){//もし\nの次も\nの時
      c+1 = 0;//あとの\nを0にする
      putchar(c);{//cをかえす
        return -2;
      }
    }
    if (ferror(fp)){
      return -1;
    }
    return 0;
  }
}

int
main(int argc, char *argv[])
{
  int   ch;
  char  uflag = 0, lflag = 0, eflag = 0;
  int   (*filter)(FILE *);
  int   retval = 0;

  while ((ch = getopt(argc, argv, "lu")) != -1) {//"lu"をオプションとする
    switch (ch) {
    case 'l':
      lflag = 1;
      break;
    case 'u':
      uflag = 1;
      break;
    case 'e':
      eflag = 1;
      break;
    default:
      return 1;
    }
  }
  if (uflag) {
    if (lflag) {
      fprintf(stderr, "%s: both of options -u and -l are set\n", argv[0]);
      //リダイレクションの時にエラーがでなくなるからエラーメッセージを標準出力\\
にだしてはいけない。
      return 1;
    } else {
      filter = toupper_filter;
    }
  } else {
    if (lflag) {
      filter = tolower_filter;
    } else {
      filter = vanilla_filter;
    }
  }
  if (eflag) {
    if (uflag) {
      filter = toupper_filter && deli_filter;
    } else {
      if (lflag){
        filter = tolower_filter && deli_filter;
      } else {
        filter = vanilla_filter;
      }
    }
  }
}


エラー処理は省かせもらいました。
助言お願いいたします。


この投稿にコメントする

削除パスワード

発言に関する情報 題名 投稿番号 投稿者名 投稿日時
<子記事> Re:コマンドラインでオプションとして指定された処理をする 20742 REE 2005/04/22 13:15:01
<子記事> Re:コマンドラインでオプションとして指定された処理をする 20743 επιστημη 2005/04/22 13:34:10
<子記事> 空行の削除とint型からchar型への変換 20774 ひか 2005/04/23 23:39:56


No.20742

Re:コマンドラインでオプションとして指定された処理をする
投稿者---REE(2005/04/22 13:15:01)


> if (c == '\n' && c+1 == '\n'){//

この条件が成立することはありません。

> filter = toupper_filter && deli_filter;

このような記述は出来ません。(少なくとも意図した通りには動きません)



この投稿にコメントする

削除パスワード

No.20743

Re:コマンドラインでオプションとして指定された処理をする
投稿者---επιστημη(2005/04/22 13:34:10)


# あなたの'知りたいこと'と'題名'が一致していません。

>大文字、小文字はわかるのですが空行がわかりません。
>判定として\nが連続したら空行ということはわかるのですが、その後の削除する処理ができませんでした。

直前に書いた文字が'\n'で、今読んだ文字も'\n'ならば、
今読んだ文字を 「書かなければいい」 のでは?
そのために、最後に書いた文字をなにかしらの変数にとっておくといい。



この投稿にコメントする

削除パスワード

No.20774

空行の削除とint型からchar型への変換
投稿者---ひか(2005/04/23 23:39:56)


ご指摘ありがとうございます。
題名も変えさせていただきました。
一度、削除関数を変えたのですがメイン文の方でエラーが出てしまいます。
*str=filter;の部分です。
「警告: 代入により、キャストなしでポインタから整数を作りました」
削除処理でポインタを使うために削除関数ではchar型で処理をしています。しかし読み込んだファイルがint型で読み込まれているのでcharに変えるために上のように処理したのですがうまくいきません。
以下書き直した削除関数とメイン関数です。

int deli_filter(char *str)
{
  char *p, *q;

  p = str;
  while (p != '\0'){
    if (*p == '\n' && *(p+1) == '\n'){//もし\nともう一つ先のアドレスが\nなら
      q = p +2;                    //qにもう二つ先のアドレスを代入
      memmove(p, q, strlen(q));    //qから文字列の末尾までをこの位置にコピー
    }
    p++;                           //ポインタの指す位置を進める
    return -2;
  }
  return 0;
}

int
main(int argc, char *argv[])
{
  int   ch;
  char  uflag = 0, lflag = 0, eflag = 0;
  int   (*filter)(FILE *);
  int   retval = 0;
  char *str;

  while ((ch = getopt(argc, argv, "lue")) != -1) {//"lue"をオプションとする
    switch (ch) {
    case 'l':
      lflag = 1;
      break;
    case 'u':
      uflag = 1;
      break;
    case 'e':
      eflag = 1;
      break;
    default:
      return 1;
    }
  }
  if (uflag) {
    if (lflag) {
      fprintf(stderr, "%s: both of options -u and -l are set\n", argv[0]);
      //リダイレクションの時にエラーがでなくなるからエラーメッセージを標準出力\\
にだしてはいけない。
      return 1;
    } else {
      filter = toupper_filter;
    }
  } else {
    if (lflag) {
      filter = tolower_filter;
    } else {
      filter = vanilla_filter;
    }
  }
  if (eflag){
    *str = filter;
    deli_filter(str);
  }
}



この投稿にコメントする

削除パスワード

No.20777

Re:空行の削除とint型からchar型への変換
投稿者---おでん(2005/04/24 05:43:46)


>*str = filter;
は、何をしたいのでしょう?
関数へのポインタを文字として代入していますが?

*str = (char)filter(fp);・・・・??


この投稿にコメントする

削除パスワード

No.20779

Re:空行の削除とint型からchar型への変換
投稿者---ひか(2005/04/24 10:28:29)


おはようございます。

>*str = filter;
>は、何をしたいのでしょう?
>関数へのポインタを文字として代入していますが?
>*str = (char)filter(fp);・・・・??
toupper_filterもしくはtolower_filter関数はint型で処理されているので実行した文字列をint型からchar型に変える処理のつもりだったんですけど…。やはりこのような書き方はありませんか?


この投稿にコメントする

削除パスワード

No.20780

Re:空行の削除とint型からchar型への変換
投稿者---おでん(2005/04/24 11:18:36)


>おはようございます。
>
>>*str = filter;
>>は、何をしたいのでしょう?
>>関数へのポインタを文字として代入していますが?
>>*str = (char)filter(fp);・・・・??
>toupper_filterもしくはtolower_filter関数はint型で処理されているので実行した文字列をint型からchar型に変える処理のつもりだったんですけど…。やはりこのような書き方はありませんか?


int   (*filter)(FILE *); ←intを返す関数へのポインタ
char *str; ←文字列へのポインタ
    ・
    ・
    ・
    ・
    ・
*str = filter; ←文字列の先頭にfilter(intを返す関数へのポインタ)を入れる・・・おかしいでしょ?

ポインタ宣言(char *str)とポインタの指している変数(今の場合は
ポインタの初期化:配列なりcharの領域なりを指すようにする事が必要)
にデータをセットする(*str= 〜)事はまったく違います。
*str = filter;は、str[0] = filter;とするのと同じことです。

で、“intを返す関数”の結果を受け取りたいなら
int   (*filter)(FILE *);と宣言されていますから、

int r ;
r= (*filter)(fp) ;
といった形になると思います。
もし、結果を文字列として受け取りたいなら

int   (*filter)(FILE *, char *);
int r ;
char buf[256] ;
r= (*filter)(fp,buf) ;
で、bufに文字列が入ります。

あとは、
char * (*filter)(FILE *); ←文字へのポインタを返す関数へのポインタ
かな?

filterの実態(vanilla_filter等)の作りによりますが・・・

・・・それともその関数は一文字しか返ってこないんですか?
であれば、

char r ;
r= (char)(*filter)(fp) ;
でもOK




この投稿にコメントする

削除パスワード

No.20782

ありがとうございます
投稿者---ひか(2005/04/24 15:18:06)


皆様いろいろご指導ありがとうございます!
まだ不安な部分もありますが、がんばってみます。
またお聞きするかもしれませんがその時はよろしくお願いします。


この投稿にコメントする

削除パスワード

管理者用メニュー    ツリーに戻る    携帯用URL    ホームページ    ログ    タグ一覧