0016. 透過率-吸光度変換(C言語)

戻る

convta.cのソースコード】


/*
 * 透過率-吸光度変換プログラム
 * convta.c(convert transmittance-absorbance)
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h> /* strlen(), strcmp(), strcpy(), strcat() */
#include <ctype.h>  /* tolower() */
#include <math.h>   /* log10(), log(), exp() */

#define BUF_SIZE 256
#define NUM_DATA 4000





/* 
 * 自作のbool型の定義
 */
typedef enum {
    false, /* 0 */
    true   /* 1 */
} bool;





/*
 * ユーザー定義関数のプロトタイプ宣言
 */
void print_title(void);
void input_fnamein(void);
char *strtolower(char *ss);
void open_fin(void);
void read_data(void);
void select_dir(void);
void conv_data(void);
void gen_fname(char *fnamein, char *fnameout);
void open_fout(void);
void write_data(void);
void close_f(void);
bool retry(void);





/*
 * グローバル変数
 */
FILE *finp, *foutp;
char fnamein[BUF_SIZE], fnameout[BUF_SIZE];
char conv_dir;
int n, last_n;
long double x_tmp, x[NUM_DATA], y_tmp, y[NUM_DATA];





/*
 * メイン関数
 */
int main(void)
{
    /* 標題および説明の表示 */
    print_title();
    
    while (1) {
        n = last_n = 0;
        
        /* 入力ファイルの名前の入力 */
        input_fnamein();
        
        /* 入力ファイルを開く処理 */
        open_fin();
        
        /* 入力ファイルからのデータの読み込み */
        read_data();
        
        /* 変換の向きの選択 */
        select_dir();
        
        /* 変換処理 */
        conv_data();
        
        /* 出力ファイルの名前の生成 */
        gen_fname(fnamein, fnameout);
        
        /* 出力ファイルを開く処理 */
        open_fout();
        
        /* 出力ファイルへのデータの書き込み */
        write_data();
        
        /* ファイルを閉じる処理 */
        close_f();
        
        /* 操作を続けるかどうかの選択 */
        if (!retry())
            break;
    }
    return EXIT_SUCCESS;
}





/*
 * 標題および説明を表示する関数
 */
void print_title(void)
{
    printf("【透過率-吸光度変換プログラム】\n\n");
    printf("CSV形式のスペクトルデータの\n");
    printf("「パーセント透過率⇔吸光度」\n");
    printf("の変換を行います。\n\n");
}



/*
 * 入力ファイルの名前を入力する関数
 * strtolower()関数を使用する。
 */
void input_fnamein(void)
{
    while (1) {
        printf("入力ファイルの名前(*.csv)を入力してください。\n");
        
        fgets(fnamein, sizeof fnamein, stdin);
        fnamein[strlen(fnamein) - 1] = '\0';
        
        if (strcmp(strtolower(&fnamein[strlen(fnamein) - 4]), ".csv") != 0) {
            printf("ファイル名が正しくありません。\n");
            continue;
        } else
            break;
    }
}



/*
 * 文字列単位で英大文字を小文字に変換する関数
 */
char *strtolower(char *ss)
{
    char *p;
    
    for (p = ss; *p; p++)
        *p = tolower(*p);
    
    return ss;
}



/*
 * 入力ファイルを開く関数
 */
void open_fin(void)
{
    finp = fopen(fnamein, "r");
    if (finp == NULL) {
        printf("ファイル%sを開けません。", fnamein);
        printf("終了します。\n");
        exit(EXIT_FAILURE);
    }
}



/*
 * 入力ファイルからデータを読み込む関数
 */
void read_data(void)
{
    char zz;
    
    while(fscanf(finp, "%lf,%lf%c", &x_tmp, &y_tmp, &zz) != EOF) {
        x[n] = x_tmp;
        y[n] = y_tmp;
        n++;
    }
    last_n = n;
}



/*
 * 変換の向き(conv_dir)を選択する関数
 * conv_dir == '1': 「パーセント透過率→吸光度」
 * conv_dir == '2': 「吸光度→パーセント透過率」
 */
void select_dir(void)
{
    char buf[BUF_SIZE], zz;
    
    while (1) {
        printf("変換の向き(1または2)を入力してください。\n");
        printf("\t「パーセント透過率→吸光度」なら1\n");
        printf("\t「吸光度→パーセント透過率」なら2\n");
        
        fgets(buf, sizeof buf, stdin);
        sscanf(buf, "%c%c", &conv_dir, &zz);
        
        if (((conv_dir != '1') && (conv_dir != '2'))
         || (zz != '\n')) {
            printf("無効な入力です。\n");
            printf("1または2を入力してください。\n\n");
            continue;
        } else
            break;
    }
}



/*
 * データの変換をする関数
 */
void conv_data(void)
{
    int i;
    
    switch (conv_dir) {
    case '1':
        for (i = 0; i < last_n; i++)
            y[i] = 2.0 - log10(y[i]);
        break;
    case '2':
        for (i = 0; i < last_n; i++)
            y[i] = exp((2.0 - y[i]) * log(10.0));
        break;
    default:
        break;
    }
}



/*
 * 出力ファイルの名前を生成する関数
 */
void gen_fname(char *fnamein, char *fnameout)
{
    int i;
    char fnamebodyin[BUF_SIZE];
    
    strcpy(fnamebodyin, fnamein);
    for (i = strlen(fnamebodyin) - 1; i > 0; i--)
        if (fnamebodyin[i] == '.') {
            fnamebodyin[i] = '\0';
            break;
        }
    strcpy(fnameout, fnamebodyin);
    
    switch (conv_dir) {
    case '1':
        fnameout = strcat(fnameout, "_a.csv");
        break;
    case '2':
        fnameout = strcat(fnameout, "_t.csv");
        break;
    default:
        break;
    }
}



/*
 * 出力ファイルを開く関数
 */
void open_fout(void)
{
    foutp = fopen(fnameout, "w");
    if (foutp == NULL) {
        printf("ファイル%sを開けません。", fnameout);
        printf("終了します。\n");
        exit(EXIT_FAILURE);
    }
}



/*
 * 出力ファイルへデータを書き込む関数
 */
void write_data(void)
{
    int i;
    
    for (i = 0; i < last_n; i++)
        fprintf(foutp, "%LE,%LE\n", x[i], y[i]);
}



/*
 * ファイルを閉じる関数
 */
void close_f(void)
{
    fclose(finp);
    fclose(foutp);
}



/*
 * 操作を続けるかどうかを選択する関数
 * true: 繰り返す、false: 終了する。
 */
bool retry(void)
{
    bool ret;
    char buf[BUF_SIZE], ch, zz;
    
    while (1) {
        printf("\n続けますか?(y/n) ");
        
        fgets(buf, sizeof buf, stdin);
        sscanf(buf, "%c%c", &ch, &zz);
        
        if (((ch == 'y') || (ch == 'Y')) && (zz == '\n')) {
            printf("\n+++++\n\n");
            ret = true;
            break;
        } else if (((ch == 'n') || (ch == 'N')) && (zz == '\n')) {
            ret = false;
            break;
        }
        printf("無効な入力です。\n");
        printf("yまたはnを入力してください。\n\n");
    }
    return ret;
}


convtaの実行結果】赤字はキーボードからの入力を表す。

D:\test>dir
(中略)
2023-05-14  07:35            50,436 sk232201d.csv      ←元の(パーセント透過率の)データファイル。

D:\test>convta
【透過率-吸光度変換プログラム】

CSV形式のスペクトルデータの
「パーセント透過率⇔吸光度」
の変換を行います。

入力ファイルの名前(*.csv)を入力してください。
sk232201d.c
ファイル名が正しくありません。
入力ファイルの名前(*.csv)を入力してください。
sk232201d.csv
変換の向き(1または2)を入力してください。
        「パーセント透過率→吸光度」なら1
        「吸光度→パーセント透過率」なら2
1                                                      ←1を入力する。

続けますか?(y/n) n

D:\test>dir
(中略)
2023-05-14  07:35            50,436 sk232201d.csv      ←元の(パーセント透過率の)データファイル。
2023-05-22  20:32            50,436 sk232201d_a.csv    ←作成された吸光度のデータファイル。


【作成された吸光度データのファイル(*_a.csv)をエクセルでグラフ化した様子】

グラフ

戻る