【C言語】ファイルの拡張子だけを変更する方法

この記事では、C言語を使ってファイルの拡張子を変更する方法をわかりやすく解説します。

具体的には、コマンドラインからファイル名を取得し、現在の拡張子を判定して新しい拡張子を設定し、新しいファイルを作成する手順を紹介します。

また、ファイル操作中に発生する可能性のあるエラーについても説明し、エラーハンドリングの方法を学ぶことができます。

これを通じて、C言語の基本的なファイル操作について理解を深めましょう。

目次から探す

拡張子変更の手順

ファイルの拡張子を変更するためには、まずファイル名を取得し、現在の拡張子を判定し、新しい拡張子を設定して新しいファイルを作成する必要があります。

以下にその手順を詳しく解説します。

ファイル名の取得方法

ファイル名を取得するためには、コマンドライン引数を使用します。

C言語では、main関数の引数としてargc(引数の数)とargv(引数の配列)を受け取ります。

コマンドライン引数からのファイル名取得

argvとargcの使い方

argcはコマンドライン引数の数を示し、argvは引数の文字列を格納した配列です。

例えば、以下のようにプログラムを実行した場合:

./change_extension file.txt

argcは3(プログラム名、ファイル名、拡張子)になり、argvは次のようになります:

引数
argv[0]./change_extension
argv[1]file.txt

このようにして、ファイル名を取得することができます。

#include <stdio.h>
int main(int argc, char *argv[]) {
    if (argc < 2) {
        printf("使用法: %s <ファイル名>\n", argv[0]);
        return 1;
    }
    char *filename = argv[1];
    printf("指定されたファイル名: %s\n", filename);
    return 0;
}

拡張子の判定

次に、ファイル名から拡張子を取得します。

これには、strrchr関数を使用します。

この関数は、指定した文字(この場合はドット .)が最後に現れる位置を返します。

strrchr関数を使った拡張子の取得

以下のコードでは、ファイル名から拡張子を取得し、表示します。

#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[]) {
    if (argc < 2) {
        printf("使用法: %s <ファイル名>\n", argv[0]);
        return 1;
    }
    char *filename = argv[1];
    char *extension = strrchr(filename, '.');
    
    if (extension != NULL) {
        printf("拡張子: %s\n", extension);
    } else {
        printf("拡張子が見つかりませんでした。\n");
    }
    return 0;
}
文字列操作の基本

C言語では、文字列は配列として扱われます。

文字列の操作には、strlenstrcpystrcatなどの関数がよく使われます。

これらを使って、拡張子の変更を行います。

新しい拡張子の設定

新しい拡張子を設定するためには、既存のファイル名を基に新しいファイル名を作成します。

文字列の結合方法

新しいファイル名を作成するためには、既存のファイル名のベース部分と新しい拡張子を結合する必要があります。

sprintf関数の利用

sprintf関数を使って、新しいファイル名を作成します。

以下の例では、拡張子を.bakに変更しています。

#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[]) {
    if (argc < 2) {
        printf("使用法: %s <ファイル名>\n", argv[0]);
        return 1;
    }
    char *filename = argv[1];
    char new_filename[256];
    char *extension = strrchr(filename, '.');
    if (extension != NULL) {
        // 拡張子を新しいものに変更
        snprintf(new_filename, sizeof(new_filename), "%.*s.bak", (int)(extension - filename), filename);
        printf("新しいファイル名: %s\n", new_filename);
    } else {
        printf("拡張子が見つかりませんでした。\n");
    }
    return 0;
}

新しいファイルの作成

新しいファイル名が決まったら、実際に新しいファイルを作成します。

新しいファイル名でのファイルオープン

fopen関数を使って、新しいファイルを作成します。

モードはwを指定します。

FILE *new_file = fopen(new_filename, "w");
if (new_file == NULL) {
    perror("ファイルオープンエラー");
    return 1;
}

既存ファイルからのデータコピー

既存のファイルからデータをコピーするためには、元のファイルを読み込み、新しいファイルに書き込みます。

FILE *old_file = fopen(filename, "r");
if (old_file == NULL) {
    perror("元ファイルオープンエラー");
    fclose(new_file);
    return 1;
}
// データコピー
char buffer[256];
while (fgets(buffer, sizeof(buffer), old_file) != NULL) {
    fputs(buffer, new_file);
}
// ファイルを閉じる
fclose(old_file);
fclose(new_file);

完成したコード

以上の手順をすべて組み合わせると、以下のようなプログラムが完成します。

#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[]) {
    if (argc < 2) {
        printf("使用法: %s <ファイル名>\n", argv[0]);
        return 1;
    }
    
    char *filename = argv[1];
    char new_filename[256];
    char *extension = strrchr(filename, '.');
    if (extension != NULL) {
        snprintf(new_filename, sizeof(new_filename), "%.*s.bak", (int)(extension - filename), filename);
        
        FILE *old_file = fopen(filename, "r");
        if (old_file == NULL) {
            perror("元ファイルオープンエラー");
            return 1;
        }
        FILE *new_file = fopen(new_filename, "w");
        if (new_file == NULL) {
            perror("新ファイルオープンエラー");
            fclose(old_file);
            return 1;
        }
        char buffer[256];
        while (fgets(buffer, sizeof(buffer), old_file) != NULL) {
            fputs(buffer, new_file);
        }
        fclose(old_file);
        fclose(new_file);
        printf("拡張子を変更したファイル: %s\n", new_filename);
    } else {
        printf("拡張子が見つかりませんでした。\n");
    }
    return 0;
}

このプログラムを実行すると、指定したファイルの拡張子を.bakに変更した新しいファイルが作成されます。

エラーハンドリング

プログラムを作成する際には、エラーハンドリングが非常に重要です。

特にファイル操作においては、さまざまなエラーが発生する可能性があります。

ここでは、ファイル操作におけるエラーの種類と、それに対するエラーチェックの実装方法について解説します。

ファイル操作におけるエラーの種類

ファイル操作を行う際に考慮すべき主なエラーには、以下の2つがあります。

ファイルが存在しない場合

指定したファイルが存在しない場合、プログラムはエラーを返します。

例えば、ファイルをオープンしようとした際に、そのファイルが見つからない場合、fopen関数NULLを返します。

この場合、エラーの原因を特定するために、errnoを確認することが重要です。

アクセス権限の問題

ファイルが存在していても、アクセス権限がない場合もエラーが発生します。

たとえば、読み取り専用のファイルに書き込もうとした場合や、他のユーザーが所有するファイルにアクセスしようとした場合、fopen関数は再びNULLを返します。

この場合も、errnoを使ってエラーの詳細を確認できます。

エラーチェックの実装

エラーチェックを実装することで、プログラムの信頼性を向上させることができます。

以下に、エラーチェックの実装方法を示します。

errnoの利用

C言語では、エラーの種類を特定するためにerrnoというグローバル変数を使用します。

errnoは、エラーが発生した際にそのエラーコードを格納します。

以下は、fopen関数を使用してファイルをオープンする際のエラーチェックの例です。

#include <stdio.h>
#include <errno.h>
#include <string.h>
int main() {
    FILE *file = fopen("example.txt", "r");
    if (file == NULL) {
        // エラーが発生した場合の処理
        printf("ファイルを開けませんでした: %s\n", strerror(errno));
        return 1;
    }
    // ファイル操作
    fclose(file);
    return 0;
}

このコードでは、fopenNULLを返した場合に、strerror関数を使ってエラーメッセージを表示しています。

エラーメッセージの表示方法

エラーメッセージを表示する際には、strerror関数を使用することで、errnoに基づいた人間にわかりやすいエラーメッセージを取得できます。

これにより、プログラムのデバッグが容易になります。

例えば、上記のコードでは、ファイルが開けなかった理由を表示するためにstrerror(errno)を使用しています。

このようにすることで、ユーザーは何が問題だったのかを理解しやすくなります。

エラーハンドリングを適切に実装することで、プログラムの堅牢性を高め、予期しない動作を防ぐことができます。

ファイル操作においては、特に注意が必要ですので、しっかりとエラーチェックを行いましょう。

目次から探す