statを使ったファイルサイズの取得方法を覚えたところで、まだまだしょぼい自作truncateのプログラムを改造します。
これが先回作ったtruncateプログラムです。
takk@deb9:~/tmp$ cat -n mytruncate.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <unistd.h>
4
5 int main(int argc, char* argv[])
6 {
7 FILE *fp;
8 int i,len,size=0;
9 int value=0;
10 int ch,tmp[100];
11
12 while ((ch = getopt(argc, argv, "s:v:")) != -1){
13 switch (ch) {
14 case 's':
15 size = atoi(optarg);
16 break;
17 case 'v':
18 value = atoi(optarg);
19 break;
20 default:
21 printf("parameter error\n");
22 return 1;
23 }
24 }
25
26 if(optind >= argc){
27 printf("parameter error\n");
28 return 1;
29 }
30
31 for(; optind<argc; optind++){
32 fp = fopen(argv[optind],"r");
33 if(fp == NULL){
34 fp = fopen(argv[optind],"w");
35 for(i=0; i<size; i++)
36 fputc(value,fp);
37 fclose(fp);
38 }else{
39 fp = fopen(argv[optind],"r");
40 for(len=0; (ch=fgetc(fp)) != EOF; len++){
41 tmp[len]=ch;
42 }
43 fclose(fp);
44 if(len < size){
45 fp = fopen(argv[optind],"a");
46 for(i=len; i<size; i++)
47 fputc(value,fp);
48 fclose(fp);
49 }else if(len > size){
50 fp = fopen(argv[optind],"w+");
51 for(i=0; i<size; i++)
52 fputc(tmp[i],fp);
53 fclose(fp);
54 }
55 }
56 }
57 return 0;
58 }
59
takk@deb9:~/tmp$
statを使うためのヘッダを追加
変更前
#include <stdio.h> #include <stdlib.h> #include <unistd.h>
変更後
#include <stdio.h> #include <stdlib.h> #include <sys/types.h> 追加 #include <sys/stat.h> 追加 #include <unistd.h>
statを使うための構造体変数定義追加。
変更前
int main(int argc, char* argv[])
{
FILE *fp;
int i,len,size=0;
int value=0;
int ch,tmp[100];
変更後
int main(int argc, char* argv[])
{
FILE *fp;
int i,len,size=0;
int value=0;
int ch,tmp[100];
struct stat buf; 追加
fopen~fgetc~floseで全部読み込んでファイルサイズ算出していた部分を、statでファイルサイズ取得するように置き換える。
変更前
}else{
fp = fopen(argv[optind],"r");
for(len=0; (ch=fgetc(fp)) != EOF; len++){
tmp[len]=ch;
}
fclose(fp);
}else{
stat(argv[optind],&buf); 変更
len =buf.st_size; 変更
ここが問題。
パラメータで指定したサイズがファイルサイズより小さい場合の処理。
前より処理が長くなってしまいます。
変更前
}else if(len > size){
fp = fopen(argv[optind],"w+");
for(i=0; i<size; i++)
fputc(tmp[i],fp);
fclose(fp);
}
変更後
}else if(len > size){
fp = fopen(argv[optind],"r"); 追加
for(len=0; (ch=fgetc(fp)) != EOF; len++){ 追加
tmp[len]=ch; 追加
} 追加
fclose(fp); 追加
fp = fopen(argv[optind],"w+");
for(i=0; i<size; i++)
fputc(tmp[i],fp);
fclose(fp);
}
ファイルを短くする場合に、元データをtmp配列にコピーしてから、上書きしているので、
どうしても読み込み処理が増えてしまいます。次回はこの辺りも改造します。
改造後の全ソースです。
takk@deb9:~/tmp$ cat -n mytruncate.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <sys/types.h>
4 #include <sys/stat.h>
5 #include <unistd.h>
6
7 int main(int argc, char* argv[])
8 {
9 FILE *fp;
10 int i,len,size=0;
11 int value=0;
12 int ch,tmp[100];
13 struct stat buf;
14
15 while ((ch = getopt(argc, argv, "s:v:")) != -1){
16 switch (ch) {
17 case 's':
18 size = atoi(optarg);
19 break;
20 case 'v':
21 value = atoi(optarg);
22 break;
23 default:
24 printf("parameter error\n");
25 return 1;
26 }
27 }
28
29 if(optind >= argc){
30 printf("parameter error\n");
31 return 1;
32 }
33
34 for(; optind<argc; optind++){
35 fp = fopen(argv[optind],"r");
36 if(fp == NULL){
37 fp = fopen(argv[optind],"w");
38 for(i=0; i<size; i++)
39 fputc(value,fp);
40 fclose(fp);
41 }else{
42 stat(argv[optind],&buf);
43 len =buf.st_size;
44 if(len < size){
45 fp = fopen(argv[optind],"a");
46 for(i=len; i<size; i++)
47 fputc(value,fp);
48 fclose(fp);
49 }else if(len > size){
50 fp = fopen(argv[optind],"r");
51 for(len=0; (ch=fgetc(fp)) != EOF; len++){
52 tmp[len]=ch;
53 }
54 fclose(fp);
55 fp = fopen(argv[optind],"w+");
56 for(i=0; i<size; i++)
57 fputc(tmp[i],fp);
58 fclose(fp);
59 }
60 }
61 }
62 return 0;
63 }
64
takk@deb9:~/tmp$
ビルドして確認。
takk@deb9:~/tmp$ gcc mytruncate.c
takk@deb9:~/tmp$ echo HELLO > 1.bin
takk@deb9:~/tmp$ ./a.out -s10 1.bin
takk@deb9:~/tmp$ wc -c 1.bin
10 1.bin
takk@deb9:~/tmp$ ./a.out -s4 1.bin
takk@deb9:~/tmp$ wc -c 1.bin
4 1.bin
takk@deb9:~/tmp$ od -tx1c 1.bin
0000000 48 45 4c 4c
H E L L
0000004
takk@deb9:~/tmp$
まだまだです。


コメント