fork download
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4.  
  5. /* cucv: cutcsv アクセステキストのフィールド切り出し */
  6. /* 第8段階 cucv8.c 20180511
  7. 最後の改行いらないが、取り合えず何とか、linuxはでないことに気づく
  8. 第2項から切り出しの時の先頭のコンマもいらないが、なんとなくこのまま
  9. しかし難関”、”処理に挑戦 何とか
  10. 7.バイナリの時もエラーになるようにした、本処理の中
  11. 8.オプション引き取りにしたい、先頭が'-'で始まる引数をモード指定にする
  12. -u オプションでダブルコーテーション内のコンマをアンダーバーにする
  13. これはcatの引数処理の場合難しそうだ、オプション指定はモード指定として取り出し、
  14. あとのargvを前に詰めるそのうえでエラーチェックにする
  15. */
  16. /* K&R のCAT第2版を流用 
  17. 引数を入力ファイル名、切り出しフィールドの文字列にする
  18. 副関数はいらない 構造をシンプルに
  19. */
  20.  
  21. int main(int argc, char *argv[])
  22. {
  23. FILE *fp;
  24. char *prog = argv[0]; /* プログラム名。エラー表示で使う */
  25. int c,n,hl;
  26. int fldno = 1; /*フィールド番号 */
  27. int dqflag = 0; /*ダブルコーテーション内のコンマ処理のためのフラグ boolでよいかも*/
  28. int hikino; /* 引数番号比較*/
  29. char h; /* 引き数の文字 */
  30. int mode = 0;
  31. /*アンダーバー出力のためのモード、boolでよいかも、
  32. とりあえずオプション増えるときのためint
  33. */
  34.  
  35. /*エラー処理 引き数チェックなど*/
  36. if (argc == 1 || argc ==2){ /* 引数なし又はファイル名のみの場合:簡単な使い方 */
  37. fprintf(stderr, "%s:アクセステキストのフィールド切り出し\n", prog);
  38. exit (1);
  39. }
  40. if ((fp = fopen(argv[1], "r")) == NULL){ /* ファイルオープンは第一引数のみにする*/
  41. fprintf(stderr, "%s:ファイルオープン失敗 %s\n", prog, argv[1]);
  42. exit(1);
  43. }
  44. for (hikino = 2; hikino < argc; hikino++){
  45. /*第2引数以降が'-'&'u'の時
  46. 'u'じゃない時エラー、'u'の時
  47. モード設定し、argvを前に詰める
  48. error かえれない
  49. */
  50. h = argv[hikino][0];
  51. if ( h == '-'){
  52. h = argv[hikino][1];
  53. if( h== 'u'){
  54. mode = 1;
  55. for (n = hikino ; n < argc ; n++) strcpy (argv[n], argv[n+1]);
  56. argc --;
  57. }
  58. else{
  59. fprintf(stderr,"%s:オプションは-uだけ \n", prog);
  60. exit (1);
  61. }
  62. }
  63. }
  64. for (hikino = 2; hikino < argc; hikino++){
  65. /*第2引数以降が自然数でない時
  66. 最大255くらいだから 文字列の各桁がASCI数値であることを確かめる
  67. 引数の長さ3文字以下、各文字が数であること、
  68. argv を 2次元配列としてアクセス こっちが難関だった
  69. */
  70. hl = strlen(argv[hikino]);
  71. if ( hl > 3){
  72. fprintf(stderr,"%s:フィールド指定は整数3桁まで\n", prog);
  73. exit (1);
  74. }
  75. for ( n = 0 ; n < hl ; n++){
  76. h = argv[hikino][n];
  77. if (h < '0' || h > '9'){
  78. fprintf(stderr,"%s:フィールド指定は整数\n", prog);
  79. exit (1);
  80. }
  81. }
  82. }
  83.  
  84. /*本処理*/
  85. while((c = getc(fp)) != EOF){
  86. /*xlsなんかの時もエラー処理
  87. ここ以外に場所がない気がするが、
  88. 構造的に分かりにくくなった気がする
  89. いっそ先に全部読みたくなる
  90. */
  91. if (c <= 8 ){
  92. fprintf(stderr,"%s:おそらくバイナリファイルです。%sを閉じ終了します\n",prog,argv[1]);
  93. fclose (fp);
  94. exit (1);
  95. }
  96. /*ダブルコーテーションの処理 2個までコンマを数えないこと */
  97. if (c == '"' ) ++dqflag;
  98.  
  99. if (c == ',') {
  100. if( dqflag == 0) ++fldno;
  101. else if( dqflag == 2) {
  102. ++fldno;
  103. dqflag = 0;
  104. }
  105. }
  106.  
  107. /*あとは全部の残った引数文字列の数値とfldnoが同じ時だけ出力する、でよいはず
  108. 1 フィールド数のカウント、変数fldnno 1で初期化か
  109. 2 第3以降の引数との比較
  110. 3 合致してたら出力
  111. 4 そのうえで改行かどうかチェック、改行の時、fldnoを更新し、改行を出力する
  112. */
  113. for (hikino = 2; hikino < argc; hikino++)
  114. if (fldno == atoi(argv[hikino])){
  115. if ( c == ',' && dqflag == 1 && mode == 1) putc('_', stdout);
  116. else putc(c, stdout);
  117. }
  118. if (c == '\n') {
  119. fldno = 1;
  120. putc(c, stdout);
  121. }
  122. }
  123. fclose(fp);
  124.  
  125. if (ferror(stdout)) {
  126. fprintf(stderr, "%s: 書き出し失敗\n", prog);
  127. /* K&Rから2つ目のエラー処理、書き出し失敗*/
  128. exit (2);
  129. }
  130. exit (0);
  131. }
  132.  
  133.  
Runtime error #stdin #stdout #stderr 0s 4372KB
stdin
Standard input is empty
stdout
Standard output is empty
stderr
./prog:アクセステキストのフィールド切り出し