一文字ずつ読み書き

ファイル処理3

fgets関数やfprintf関数は文字列を読み取り/書き込みをする関数でしたが、一文字ずつ処理する関数もあります。

以下は、指定したテキストファイルを別名で保存するサンプルコードです。

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

void Quit()
{
    printf("Enterキーで終了。\n");
    getchar();
    exit(0);
}

int main()
{
    const char *fileIn = "C:\\test.txt";
    const char *fileOut = "C:\\test_Copy.txt";

    printf("%sを%sにコピーしますか?\n", fileIn, fileOut);
    printf("y/n\n");

    int input = getchar();
    if(input != '\n')
        while (getchar() != '\n');

    if (input != 'y')
    {
        printf("キャンセルしました。\n");
        Quit();
    }

    FILE *fpIn, *fpOut;

    //fpIn = fopen(fileIn, "r");
    fopen_s(&fpIn, fileIn, "r");
    if (fpIn == NULL)
    {
        printf("%sのオープンに失敗しました。\n", fileIn);
        Quit();
    }

    //fpOut = fopen(fileOut, "w");
    fopen_s(&fpOut, fileOut, "w");
    if (fpOut == NULL)
    {
        printf("%sのオープンに失敗しました。\n", fileOut);
        fclose(fpIn);
        Quit();
    }

    printf("\n%s\n- - - - -\n", fileIn);
    while ((input = fgetc(fpIn)) != EOF)
    {
        putchar(input);
        fputc(input, fpOut);
    }

    fclose(fpIn);
    fclose(fpOut);

    printf("\n- - - - -\n処理が終了しました。\n");

    getchar();
}

今回は読み取り側のファイルと書き込み側のファイルの二つを使用するので、ファイルを二つ同時に開きます。
それぞれオープンモードが異なることに注意してください。

Cドライブに適当な文字を入力した「test.txt」というファイルを配置した上でコードを実行してください。
場所を変える場合はコード上のファイルパスも変更してください。

少し長いコードですが、コピー処理をしているのは49~53行目です。
それ以外はファイルのオープンや画面へのメッセージ表示などの処理です。

fgetc/fputc関数

int fgetc(
 FILE *stream
);
ファイルストリームstreamから一文字読み取る。
戻り値は読み取られた値。
ファイルの終端、もしくはエラーを検出した場合はEOFを返す。

fgetc関数はファイルから一文字だけ読み取る関数です。
fgets関数は文字列(string)を読み取る、fgetc関数は文字(character)を読み取る、という意味です。

49行目の処理を複数行に分割すると、以下のようになります。

while (1)
{
    input = fgetc(fpIn);
    if(input != EOF)
    {
        //何らかの処理
        continue;
    }
    break;
}

読み取り側のファイルから一文字読み取り、そのまま書き込み側ファイルに一文字書き込む処理をwhile文でファイルの終端に達するまで繰り返します。
ファイルの終端に達した場合はEOFを返すので、ループを終了しプログラムを終了します。

ファイルに一文字を書き込むにはfputc関数を使用します。

int fputc(
 int c,
 FILE *stream
);
文字cをファイルストリームstreamに書き込む。
戻り値は書き込んだ文字。
エラーが発生した場合はEOFを返す。

getした文字をそのまま別ファイルにputする、というごく単純な処理です。

putchar関数

ついでの処理として、putchar関数でファイルに書き込まれる内容を画面に表示しています。

int putchar(
 int c
);
文字cを標準出力に出力する。
戻り値は書き込んだ文字。
エラーが発生した場合はEOFを返す。

getchar関数の逆の働きをする関数で、標準出力に文字を出力する関数です。
printf関数を使用しても構いませんが、単に一文字を表示するだけならばこちらの方が簡潔に書けます。

ちなみにfputc関数の第二引数に「stdout」を指定しても同じ動作になります。

exit関数

今回のサンプルコードではプログラムの終了条件が複数存在するので、どこからでも簡単に終了させるためにプログラム終了処理を関数化しています。
(4~9行目の関数Quit)
ここでexit関数というものが登場しています。

void exit(
 int status
);
終了コードstatusをシステムに返し、プログラムを終了する。

exit関数が呼び出されると、直ちにプログラムは終了します。

引数には終了コードを指定します。
正常終了ならば0を指定します。
0以外は異常終了を示す値となりますが、どのような動作をするかは呼び出し元のシステムによります。

通常のWindowsアプリケーションでは終了コードは利用されず、どのような値を指定しても変わらないことが多いです。
自作プログラムと連携させる場合に終了コードを利用することはあります。

exit関数は<stdlib.h>に定義されていますので、インクルード(#include)するのを忘れないようにしましょう。