前回の復習 ファイル入出力①
何かソフトウェアで作ったデータを保存したもの ファイルとは? 何かソフトウェアで作ったデータを保存したもの C言語では それだけとは限らない
ファイルの種類の例 テキストファイル バイナリファイル 文字として読めるもの 文字として読めないもの (ソースコードやHTMLなど) (機械語のプログラムや画像データなど)
ファイルを扱う手順 ファイルポインタを宣言 対象のファイルを開き、ファイルポインタを得る ファイルポインタを通して読み書きする 操作が終わったら、ファイルを閉じる
今日の練習問題① キーボードからファイル名を読み込んで、その名前のファイルが存在すれば「そのファイルは存在します」と表示し、そうでなければ「そのファイルは存在しません」と表示するプログラムを作成せよ。
#include <stdio.h> int main(void) { char st[20]; scanf("%s", st); FILE *fp; fp = fopen(st, "r"); if (fp == NULL) { printf("そのファイルは存在しません\n"); return 0; } else { printf("そのファイルは存在します\n"); fclose(fp);
今日の練習問題② ファイルのコピーするプログラムを作成せよ。キーボードからコピー元のファイル名とコピー先のファイル名を読み込むこと。
#include <stdio.h> int main(void) { char i[20], o[20]; FILE *ifp, *ofp; int c; scanf("%s", i); ifp = fopen(i, "r"); if (ifp == NULL) return 0; scanf("%s", o); ofp = fopen(o, "w"); if (ofp == NULL) while ((c = fgetc(ifp)) != EOF) fputc(c, ofp); fclose(ofp); fclose(ifp); }
今日の練習問題③ キーボードからファイル名を読み込んで、その名前のファイルの中身を消去するプログラムを作成せよ
#include <stdio.h> int main(void) { char st[20]; FILE *fp; scanf("%s", st); fp = fopen(st, “w"); fclose(fp); return 0; }
今日の練習問題④ キーボードからファイル名を読み込んで、そのファイル中の行数(改行文字の個数)をカウントして表示するプログラムを作成せよ
#include <stdio.h> int main(void) { char st[20]; FILE *fp; int ch, cnt = 0; scanf("%s", st); fp = fopen(st, "r"); while ((ch = fgetc(fp)) != EOF) if (ch == '\n') cnt++; fclose(fp); printf("ファイルの改行数は%dです\n", cnt); return 0; }
今日の練習問題⑤ キーボードからファイル名を読み込んで、そのファイル中の各数字文字の個数をカウントして表示するプログラムを作成せよ
#include <stdio.h> int main(void) { char st[20]; FILE *fp; int i, ch, cnt[10] = { 0 }; scanf("%s", st); fp = fopen(st, "r"); while ((ch = fgetc(fp)) != EOF) if ('0' <= ch && ch <= '9') cnt[ch - '0']++; fclose(fp); for (i = 0; i < 10; i++) printf("%dの数は%dです\n", i, cnt[i]); return 0; }
今日の練習問題⑥ 任意のファイルの中身を、すべて英小文字を英大文字に変換して別ファイルへコピーするプログラムを作成せよ。
#include <stdio.h> int main(void) { char s[20], d[20]; FILE *sfp, *dfp; int i, ch, cnt[10] = { 0 }; scanf("%s", s); scanf("%s", d); sfp = fopen(s, "r"); if (sfp == NULL) return 0; dfp = fopen(d, "w"); while ((ch = fgetc(sfp)) != EOF) if ('a' <= ch && ch <= 'z') fputc(ch - 32, dfp); fclose(sfp); fclose(dfp); }
今日の練習問題⑦ ファイルに保存されている名前、身長、体重の個人データを読み込んで、身長順にソートしたうえで画面に表示するとともに、平均身長と平均体重を表示するプログラムを作成せよ。 テキストデータ Aiba 160 59.3 Kurata 162 51.6 Masaki 182 76.5 Tanaka 170 60.7 Tsuji 175 83.9 Washio 175 72.5
#include <stdio.h> #include <string.h> int main(void) { FILE *fp; int i, j, num = 0; char n[100][50]; double h[50], w[50], hsum = 0.0, wsum = 0.0; fp = fopen("hw.dat", "r"); if (fp == NULL) return 0; for (i = 0; i < 6; i++) { fscanf(fp, "%s%lf%lf", n[i], &h[i], &w[i]); hsum += h[i]; wsum += w[i]; num++; } //ソート for (i = 0; i < num - 1; i++) { for (j = num - 1; j > i; j--) { if (h[j - 1] > h[j]) { char tn[100]; double td; strcpy(tn, n[j]); strcpy(n[j], n[j - 1]); strcpy(n[j - 1], tn); td = h[j]; h[j] = h[j - 1]; h[j - 1] = td; td = w[j]; w[j] = w[j - 1]; w[j - 1] = td; } for (i = 0; i < 6; i++) printf("%s %5.1f %5.1f\n", n[i], h[i], w[i]); printf("平均 %5.1f %5.1f\n", hsum / num, wsum / num); fclose(fp); return 0;
今日の練習問題⑧ 次の手順でキーボードから入力したデータをファイルに書き込むプログラムを作成しなさい。 追加モードで "car.dat" をオープンする。 無限ループで以下の処理を行う。 メーカー名を文字列で入力する。 メーカ名に "end" が入力されたら無限ループを終了する。 車種を文字列で入力する。 排気量を 10進数で入力する。 これらのデータを 1. でオープンしたファイルに書き込む。 1. でオープンしたファイルを閉じる。 実行例 メーカー名を入力して下さい(終了条件:end) HONDA 車種を入力して下さい CIVIC 排気量を入力して下さい 1500 メーカー名を入力して下さい(終了条件:end) TOYOTA 車種を入力して下さい LEVIN 排気量を入力して下さい 1600 メーカー名を入力して下さい(終了条件:end) end
#include <stdio.h> #include <string.h> int main(void){ FILE *fp; char maker[10], name[12]; int cc; fp = fopen("car.dat", "a"); if (fp == NULL) return 0; while (1) { printf("メーカー名を入力して下さい(終了条件:end) "); scanf("%s", maker); if (strcmp(maker, "end") == 0) break; printf("車種を入力して下さい "); scanf("%s", name); printf("排気量を入力して下さい "); scanf("%d", &cc); fprintf(fp, "メーカー名:%s ", maker); fprintf(fp, "車種:%s ", name); fprintf(fp, "排気量:%d\n", cc); } fclose(fp);
プログラミング応用 ファイル入出力②
CSVファイル 「( )で値を区切ったもの」が入っているファイ ル 「( )で値を区切ったもの」が入っているファイ ル ( )などの表計算ソフトやAccessなどのデータ ベースソフトに取り込んで使用できる オープンデータなどの( )で使われることが 多い
CSVファイル書き出し 「コンマ」で区切ることでExcelで開くことができる #include <stdio.h> int main(void){ FILE *fp; char *fname = "comma.csv"; char *s1 = "test01", *s2 = "test02", *s3 = "test03"; int n1 = 10, n2 = 20, n3 = 30; float f1 = 1.0, f2 = 2.0, f3 = 3.0; fp = fopen(fname, "w"); fprintf(fp, "%s,%d,%f,\n", s1, n1, f1); fprintf(fp, "%s,%d,%f,\n", s2, n2, f2); fprintf(fp, "%s,%d,%f,\n", s3, n3, f3); fclose(fp); return 0; } 「コンマ」で区切ることでExcelで開くことができる
バイナリファイル操作
バイナリファイルの読み書き テキストファイルの場合は、関数が自動的に改行などを認識していたが、( )では制御コードなど関係なく、( )のデータとして扱う。 “Hello” テキスト バイナリ バッファ (メモリ領域) H e l o \n \0 文字列 同じデータ
バイナリファイルを開く FILE *fp; fp = fopen(“file.dat”, ”rb”); ファイルポインタ モード バイナリの場合は()を追記する ファイル名 rb 読み出し wb 書き込み ab 追加書き込み
バイナリファイルの開閉 #include <stdio.h> int main(void) { FILE *fp; fp = fopen(“text.dat”, “wb”); fclose(fp); return 0; }
バイナリファイルの書き込み #include <stdio.h> int main(void) { int buf = 100; FILE *fp; fp = fopen(“text.dat”, “wb”); fwrite(&buf, sizeof(int), 1, fp); fclose(fp); return 0; } バイナリで100を書き込み ファイルをメモ帳などで開くと、変な表示になっている バイナリエディタを使うと64と表示される
バッファを書き出す fwrite(&buf, sizeof(int), 1, fp); バッファの 書き出しの( ) 先頭アドレス 書き出しの( ) 書き出しの基本単位 (バイト) ファイル ポインタ
配列で書き出し #include <stdio.h> int main(void) { int buf[] = {10, 100, 1000, 1000}; FILE *fp; fp = fopen(“text.dat”, “wb”); fwrite(buf, sizeof(int), 4, fp); fclose(fp); return 0; } 配列に注意
バイナリファイルの読み込み バイナリファイルの1番目を読み込み 10が表示される #include <stdio.h> int main(void) { int buf; FILE *fp; fp = fopen(“text.dat”, “rb”); fread(&buf, sizeof(int), 1, fp); if(fp == NULL) return 0; fclose(fp); printf(“%d \n”, buf); } バイナリファイルの1番目を読み込み 10が表示される
配列の読み込み #include <stdio.h> int main(void) { int buf[4]; FILE *fp; fp = fopen(“text.dat”, “rb”); fread(buf, sizeof(int), 4, fp); if(fp == NULL) return 0; fclose(fp); for(int i = 0; i < 4; i++) printf(“%d \n”, buf[i]); } 配列に注意
Windows系は改行が()バイトになる fseek()関数 ファイルポインタの先頭位置を10バイト後ろの位置にずらす fseek(fp, 10, SEEK_SET); ファイル ポインタ モード SEEK_SET:ファイルの先頭から SEEK_CUR:ファイルの現在位置から SEEK_END:ファイルの終端から 移動するバイト数 Windows系は改行が()バイトになる
#include <stdio. h> int main(void){ FILE. fp; fp = fopen(“text #include <stdio.h> int main(void){ FILE *fp; fp = fopen(“text.txt”, "rb"); if(fp == NULL ) return 0; fseek(fp, 10, SEEK_SET); printf("ファイル位置 = %ld\n",ftell(fp)); fseek(fp, -5, SEEK_CUR); fseek(fp, 0, SEEK_END); fseek(fp, 0, SEEK_SET); fclose(fp); }
コマンドライン引数
main関数にも引数がある 今まではint main(void) int main(int argc, char *argv[])にすることでコ マンドライン引数を使うことができる コマンドライン引数によって実行の段階で mainに引数を渡すことができる ( )を読み込むこともできる
コマンドライン引数を表示 引数として「ABC DEF GHI」を指定する #include <stdio.h> int main(int argc, char *argv[]) { int i; printf("引数の総個数 = %d\n", argc); for (i = 0; i < argc; i++) { printf("%d番目の引数 = %s\n", i, argv[i]); } return 0; 引数として「ABC DEF GHI」を指定する
実行のやりかた Visual Studioの場合 CPadの場合 プロジェクト → プロパティ → 構成プロパティ → デバッグ → コマンド引数の欄に、スペースで区切った文字列を並べる CPadの場合 実行 → コマンド入力 → メニュー([Ctrl+F7]キー)で任意のコマンドを実行できる…らしい。
引数の意味 int main(int argc, char *argv[]) … 引数の総個数 引数の文字列を指す (プログラム名も含む) ポインタの配列 argv[0]:実行ファイルの場所 argv[1]:コマンドライン引数の1番目 argv[2]:コマンドライン引数の2番目 argv[n]:コマンドライン引数のn番目 …
scanfを使わなくてもいい コマンドライン引数としてtext.txtと指定する #include <stdio.h> int main(int argc, char *argv[]) { FILE *fp; fp = fopen(argv[1], "r"); if (fp == NULL) { printf("そのファイルは存在しません\n"); return 0; }else { printf("そのファイルは存在します\n"); } fclose(fp); コマンドライン引数としてtext.txtと指定する
コマンドライン引数でオプションを作れる UNIX系のコマンドの後に-(ハイフン)と一緒に 英語を付けたオプションがある。 例えば、ls –a、ln –s、rm -d -fなど。 コマンドライン引数を使えば、そういった実行 ファイルにオプションを追加できる。
今週はここまで 何か質問はありませんか?
今日の練習問題① コマンドライン引数からファイル名を読み込んで、その名前のファイルが存在すれば「そのファイルは存在します」と表示し、そうでなければ「そのファイルは存在しません」と表示するプログラムを作成せよ。
今日の練習問題② 縦横10×10の1~1000までのランダムとなる整数が書き込まれたcsvファイルを作成するプログラムを記述せよ。
今日の練習問題③ 次の表をExcelでも開ける形式で作成するプログラムを作成せよ 番号 名前 テストの平均点 1 野比のび太 2 源静香 2 源静香 90 3 剛田武 40 4 骨川スネ夫 70
今日の練習問題④ double型で{0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0}となっている配列の全要素をバイナリファイルに書き込み、その後、そのファイルを読み込んでprintfで表示するプログラムを作成せよ。
今日の練習問題⑤ 任意のファイルの中身を、別ファイルへコピーするプログラムを作成せよ。ただしfread関数とfwrite関数を利用してバイナリファイルとして読み書きすること
今日の練習問題⑥ コマンドライン引数で、ファイル名と任意の文字列を入力として、バイナリファイルを書き出すプログラムを記述せよ。
今日の練習問題⑦ プログラム起動時に入力された複数個のプログラム仮引数の文字数('\0'は除く)を数えて、例のように文字列とともに表示するプログラムを作成せよ。 なお、プログラムは次の2つの関数を含まなければならない。 1. 文字数を数える関数 1つの文字列のアドレスを受け取り、その文字列の文字数を返す。 2. 文字列を表示する関数 1つの文字列のアドレスと文字数を受け取り、これを表示する。 例 C:\>smple tokyo shinbashi shinagawa kawasaki yokohama n = 5 tokyo n = 9 shinbashi n = 9 shinagawa n = 8 kawasaki n = 8 yokohama
今日の練習問題⑧ ファイルに保存されている名前、身長、体重の個人データを、ファイルの終端10バイトだけ読み込んで、表示するプログラムを作成せよ。ただしfseek関数を使用すること。 テキストデータ Aiba 160 59.3 Kurata 162 51.6 Masaki 182 76.5 Tanaka 170 60.7 Tsuji 175 83.9 Washio 175 72.5