質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.10%

EOFの使い方が分かりません。

解決済

回答 4

投稿

  • 評価
  • クリップ 1
  • VIEW 416

ht3433

score 5

前提・実現したいこと

C言語で、EOFの使い方を調べてもよく分かりません。
下記のソースコードでは、
./tr abc def
abc
def
のように、文字の変換が正常に動作していましたが、
EOFをソースコードに加えてみると、
./tr abc def
abc
aec
のように、文字の変換が正常に動作しませんでした。

お力添えいただければ幸いです。

該当のソースコード

ソースコード
#include<stdio.h>
#include<string.h>
#include<ctype.h>

int main(int argc, char *argv[]){

// 入力する文字の変数を定義
char moji1[100];
int c;
size_t i;
size_t j;
// 何度も文字を入力可能にする
while( ( c = getchar() ) != EOF ){
putchar( c );
memset(moji1, 0, sizeof(moji1));

// 文字の入力
scanf( "%c", moji1 );

// 入力した文字分だけ繰り返す
for( i = 0; i < strlen( moji1 ); i++ ){
// trの変換先の文字分だけ繰り返す
for( j = 0; j < strlen( argv[1] ); j++ ){
// 入力した文字と変換先の文字が同じか判定
     if( moji1[i] == argv[1][j] ){
// trの変換先と変換元の文字が同じか判定
if( argv[1][j] != argv[2][j] ){
printf( "%c", argv[2][j] );
i++;
}else{
printf( "%c", moji1[i] );

}
}
}
if( moji1[i] != argv[1][j] ){
printf( "%c", moji1[i] );
}
}
}
return( 0 );
} 
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • dodox86

    2019/10/09 17:57

    >cateyeさん
    回答欄に書かれてはいかがでしょうか。ただ、CTRL-CはBREAKだと思います。プログラムはDOS、Windowsのコマンドプロンプト、UNIX端末でも強制終了かと。DOS/WindowsコマンドプロンプトですとCTRL-Z(0x1b)ですね。

    キャンセル

  • cateye

    2019/10/09 18:17

    ご助言有難うございます。・・・コメントの追加になってしまった^^;

    キャンセル

  • dodox86

    2019/10/09 20:01

    CTRL-ZのEOF間違えました。
    正:CTRL-Z 0x1a
    誤:CTRL-Z 0x1b (ESC)
    0x1bはエスケープシーケンス始まりでした。

    キャンセル

回答 4

checkベストアンサー

0

自分が何をするのかをちゃんと整理しないでプログラムをいじってしまって混乱に陥っているように思います。(いじる元のプログラムもちゃんと理解していなかったのかも知れませんが)

質問のプログラムをベースにプログラムを書いてみましたが、コメント空行有りで20行でした。質問のプログラムのおよそ半分は無駄、というか間違いと言ってしまっても...

擬似言語で書くならば

1文字入力して EOFでなかったら (EOFだったら終わり)
    変換元の文字を探索
        入力文字と変換元の文字が一致したら
            変換先の文字に置き換えて
            探索終わり
    文字を表示
繰り返し

終わり


こんな感じでしょうか。

端折りましたが、
./tr abc    (パラメータが足りない)
./tr abcdef ghi (変換先の文字数が少ない)
なんて場合も妙なことが起こらないように対策する必要があるでしょう。

これだけ時間を使って解決しない時は、一度真っ白な状態から作り直してみるのも一案ではないでしょうか。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/10/21 10:14

    コメントしていただき、ありがとうございます。
    thkanaさんのおっしゃるとおり、一度整理してプログラムをかいてみると、上手くいきました!
    ありがとうございました。

    キャンセル

0

標準入出力を使う限りにおいては、ファイルの終わりというのが存在しないので、EOFというものは来ません。
なので使わないほうがいいです

#実際にはCtrl-CだかCtrl-Dだかを入れると出すことができるということだけど

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/10/10 13:45

    putcharを使ってEOFを作る。。。ちょっと違います。EOFとは、getcharを使うのであれば、ファイルの末端まで読んだことを示す「ファイル終了のお知らせ」です。端末からのキー入力であればそのキー入力全体が「ファイル」にあたります。それがgetcharの返り値/戻り値EOF(-1)となるので、それで入力の終了が分かる、ということです。たくさん回答をいただいているのですから、実際に試してみましょうよ。

    キャンセル

  • 2019/10/10 14:00 編集

    一応補足をしておきますと、ht3433さんのもとのコードのようにscanfとprintfでもやってやれないことはありません。しかしながら1文字ずつの入出力なのだから、一般的にgetchar/putcharを使うのが適切なので、私含め、他の回答者さんらもそれらを使っている、というわけです。C言語の一般的な入門書でもそうなっています。(参考: fgetc, fputc)
    y_waiwaiさんの回答へのコメント欄なので、回答含め、これ以上は控えたいと思います。(失礼いたしました)

    キャンセル

  • 2019/10/17 21:03

    > 標準入出力を使う限りにおいては、ファイルの終わりというのが存在しないので、EOFというものは来ません。
    一応。標準入力にファイルをリダイレクトで流し込んで終わったり、パイプで繋いでいたのを元で閉じるとEOFになります。それを考えるとEOFで終わる動きも有りでは。

    キャンセル

0

c = getchar()

で読み込んだ1文字を何も処理せずに直後で

putchar( c );

しているからです。
つまり、

繰り返し開始
1文字読んでそのまま書く
1文字読んで変換対象なら変換してして書く
繰り返し終わり

という処理になっています。

moji1scanfするのをやめて、c = getchar()で入力したcに対して、変換処理を行えばいいと思います。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/10/15 18:36

    回答していただき、ありがとうございます。
    scanfをやめて、c = getchar()で入力したcに対して変換をしてみたのですが、1文字目が表示されないようになりました。
    何が原因なのでしょうか?
    なにかヒントをいただけると、ありがたいです

    ソースコード
    #include<stdio.h>
    #include<string.h>
    #include<ctype.h>

    int main(int argc, char *argv[]){

    // 文字の変数を定義
    char moji1[100];
    char c;
    int count = 0;
    int i;
    size_t j;
    // 何度も文字を入力可能にする
    while( ( c = getchar() ) != EOF ){
    memset(moji1, 0, sizeof(moji1));

    //文字列をキーボードから入力する
    for(count = 0; count < 100; count++){
    c = getchar();
    //改行なら終了
    if(c == '\n'){
    break;
    //それ以外なら保存する
        }else{
    moji1[count] = c;
    }
    }
    // 入力した文字分だけ繰り返す
    for( i = 0; i < count; i++ ){
    // trの変換先の文字分だけ繰り返す
    for( j = 0; j < strlen( argv[1] ); j++ ){
    // 入力した文字と変換先の文字が同じか判定
    if( moji1[i] == argv[1][j] ){

    // trの変換先と変換元の文字が同じか判定
    if( argv[1][j] != argv[2][j] ){
    putchar( argv[2][j] );

    i++;
    }else{
    putchar( moji1[i] );
           }
    }
    }
    if( moji1[i] != argv[1][j] ){
    putchar( moji1[i] );
    }
    }
    }
    return( 0 );
    }

    キャンセル

  • 2019/10/15 19:44

    getchar()をあちこちで実行しているからです。
    while( ( c = getchar() ) != EOF ){
    以外のgetchar()を全部消して、プログラム全体を書き直しましょう。

    キャンセル

  • 2019/10/17 10:54

    回答していただき、ありがとうございます。
    早速、
    //文字列をキーボードから入力する
    for(count = 0; count < 100; count++){
    c = getchar();
    のc = getchar();を消して、
    //文字列をキーボードから入力する
    for(count = 0; count < 100; count++){
    にして実行してみたのですが、
    ./tr a b
    a
    babababababababababababababababababababababababababababababababababababababababababababababababababa
    という結果になってしまいました。
    コードを見返してみたのですが、なぜこうなってしまったのか分かりません。
    指摘していただけるとありがたいです。
    宜しくお願い致します。

    キャンセル

  • 2019/10/17 21:18

    「プログラム全体を書き直しましょう。 」と書きましたが、
    while( ( c = getchar() ) != EOF ){
    まで残して、それ以降全部消して書き直しましょうということです。
    最初のプログラム構造が間違っているので、それをベースに書き直しても駄目です。

    キャンセル

0

https://teratail.com/questions/214923#reply-316588(2つの文字列の変換をしたいです)
このコードは参考にならなかったようですね。
EOF まで読み込むので Linux なら Ctrl-D で終了したのに。

では、変換テーブルを使わないやり方にしてみます。

#include <stdio.h>  // getchar, putchar, fprintf
#include <string.h> // strlen

int main(int argc, char *argv[])
{
    int n, c, t, i;
    if (argc != 3 || (n = strlen(argv[1])) != strlen(argv[2])) {
        fprintf(stderr, "usage: %s string1 string2\n", argv[0]);
        return 1;
    }
    while ((t = c = getchar()) != EOF) {
        for (i = 0; i < n; i++)
            if (c == argv[1][i])
                t = argv[2][i];
        putchar(t);
    }
}


これは参考になりますか?
分からないところは質問してください。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/10/10 14:10

    回答していただき、ありがとうございます。
    fprintf(stderr, "usage: %s string1 string2\n", argv[0]);
    というコードですが、これはなにをしているのでしょうか?
    理解力がなくて大変申し訳ないのですが、教えていただけるとありがたいです。

    キャンセル

  • 2019/10/10 22:19

    その前の行に
    if (argc != 3 || (n = strlen(argv[1])) != strlen(argv[2])) {
    とありますが、これが何かは分かっているんですよね。

    プログラムを実行するのに必要な引数が正常に与えられているかどうかを
    チェックしています。fprintf の行では、
    引数が不正の場合にエラーメッセージ(正しい使用方法)を出力しています。

    エラーメッセージを printf で出力すると、
    ./tr abc de <file1.txt >file2.txt
    のように、入出力をファイルにリダイレクトした場合、出力ファイルに
    エラーメッセージが入って、エラーであることがすぐには分かりません。
    そこで標準出力 stdout ではなく、標準エラー出力 stderr に出力するように
    しています。

    ところで、文字の変換の部分は参考にならなかったんでしょうか?

    キャンセル

  • 2019/10/15 18:30

    回答していただき、ありがとうございます。
    返事が遅くなり、大変申し訳ございません。
    詳しい説明をしていただき、ありがとうございます。
    正直にいいますと、文字の変換の部分は参考にならなかったです。
    貴重なお時間を使って回答してくださったのに、このようなことを述べてしまい、申し訳ございません。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.10%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る