りーまの日記

特に外向けに配信しているわけではないので読みにくいかもしれませんが参考になれば幸いです

コマンドライン引数

ここ3週間ほどずっとVisual Studio(以下VS) を利用したC言語コマンドライン引数を使ったファイルの開き方が分かりませんでした…

 

ここあさんに教えてもらいました

解説してもらったブログ

https://koron0902.ddns.net/index.php/2017/02/15/cmd-arg-vs/

 

ここにやり方が書いてあります

本当にありがとうございます

 

苦戦した理由の一番大きな勘違いは

・argc,argvがそのパソコン上では全てのプログラムで同一なものと思ってた事

 

今回苦戦した理由は4つあります

1.テキストファイルの意味がわかってなかった

  テキストファイルは何かのファイルとだけ思っていた

 

2.コマンドライン引数がわかってなかった

  引数なのでどこからか別の所からやってくる、そういうイメージがありましたが

  main関数の外側が一体何なのか…

 

3.そもそもファイルの開き方がわかってなかった

  ファイルをコマンドライン引数で開くと始めにargc,argvが出てくるが

  それに謎の疑問を抱いてしまった

 

4.VSのフォルダ分けがわかっていなかった

  ソースプログラムと同じフォルダに入れる、という記述を見てやってみようと

  思ったのですがVSのprojectファイルが複雑で混乱した

 

苦戦した理由の解決策

1.テキストファイルの意味がわかってなかった

  テキストファイルとは文字データだけのファイルの事であり

  「.txt」の拡張子を持つ物

  Wordは行間の幅など「書式設定」を含んでいるので文字だけのデータでありません

 

2.コマンドライン引数がわかってなかった

  コマンドライン引数は自分で設定するものではなくコンピュータが勝手に

  作ってくれるものだと勝手に思っていたので解釈が進みませんでした…

  さらにargc,argvがそのパソコン上では全てのプログラムで同一なものと

  思ってことも原因にあります。

  ここあさんに教えてもらい自分でいくつかプログラムを実行しようとした

  ときプログラムごとにコマンドライン引数の中身のファイルが違ったので

  気づきました…

 

3.そもそもファイルの開き方がわかってなかった

  ファイルをコマンドライン引数で開くと始めにargc,argvが出てくるが

  それに謎の疑問を抱いてしまった

  ↑

  これはどうやらコマンドライン引数を使ってファイルを開いたとき

  すべてのプログラムで現れます

 

4.VSのフォルダ分けがわかっていなかった

  ソースプログラムと同じフォルダに入れる、という記述を見てやってみようと

  思ったのですがVSのprojectファイルが複雑で混乱した

  ↑

  これもあれますが

  カレントディレクトリ、パスなどの言葉を忘れていたのも原因にあります

  VSの拡張子「.vcxproj」について勉強すると少しわかります

 

/*一応なぜコマンドラインの話になったかということと失敗した経緯*/

まず始まりは僕が使っている参考書「独習C」9章はファイルの取り扱いの章でした。コマンドライン引数については7章でチラッと出てきてVSの仕様をいろいろ調べたんですがあまり見たことない形式(main関数に引数がついているプログラム)だったし検索してもピンポイントにVSの記事が見つからず放っておいた(今思うと検索ワードがまずかった)のです。

すると9章でほぼすべてのプログラムがコマンドライン引数を使用してファイルを開いていたのでVSでどうにかする方法を探していました。

まず、写経して半角英数字で書かれたテキストファイルを開いてAが何文字含まれているか数えろというと所で既にわかりませんでした。

 

テキストファイルをただ「何かのファイル」とだけ思っていてそのファイルをどこに作るのかプログラムの中なのか外なのか、外だとしたらどこに作れば良いのかパソコンの中ならどこでもよいのか

 

テキストファイルがまずなんなのかを気にする前にいろいろな疑問が出てきてかつコマンドライン引数がわからないという状況で

 

・動画の説明を見ているときになぜメモ帳を開いたのかわからない

・他の人の参考記事を見てファイルを開くプログラムを実行したときにコマンドプロンプトの初めにargv,argvが出てくるのがそういうものだと認識できずずっと悩んでいた

 

などと今思うと本当に何やってるかわからない事をしていて、

コマンドライン引数について調べるためmain関数がどのように処理されるのかやパソコンの内部、カーネルやOSやシェルの分野の話を勉強し始める

・さらに物理メモリやハードディスクとしてのCPUの内部構造を勉強し始める

 

など違う方向ですべてを理解しようとしたのでかなり遠回りなことをしてしまいました…(いろいろわかったことが増えたので結果的には良かったです)

 

まとめ

ブログの書き方がわからなかったので読みにくいかもしれません。

本当に何をやってるかわかりませんがとりあえずVSでコマンドライン引数が使えるようになりました。

いろいろ語ったようですがこれでようやくファイル操作、コマンドライン引数が使えるスタート地点に立てたのでこれから何ができるか、どこまでできるかなどを学んでいきます

いろいろ遠回りしてすこしは予習もできたのでこの3週間を無駄にはしません

日々気になっていたプログラムの事-1

おそらくこれから突発的に何度か不定期あるシリーズです
https://twitter.com/strimuer213p/status/823854746498789376

すべての始まりのツイートです

今から書くことはこのツイートのリプライから指摘をいただいた物を自分なりに調べてみました

-------1月27日----------------------------------------
Visual Studioのセキュリティ
  VSにおいて古くセキュリティが弱い(Microsoftが奨励しない)関数には
  毎回エラーメッセージが出る。(調べるとよくぶつかるのが標準ライブラリ関数で
  あるscanf()。)
  
  このエラーを防ぐ方法は二つある
    1.MSではPOSIX仕様のセキュリティに強い関数を作成しており(scanf()であるならば
     scanf_s())そちらを使う
     ・良い点
       実際にセキュリティが高くなりプログラムを安全に取り扱える
     ・悪い点
       これは Visual Studio特有のもので他のエディタ等では使えない
       (少なくとも競技プログラミングAtcoderでは「WA(Wrong Answer)」ではなく
                「CE(Compilation Error)」というエラー)
       
    2.#define _CRT_SECURE_NO_WARNINGSで「奨励しない関数である」という警告を
                                     除去する
     ・良い点
       競プロを行う上では先頭のこの文章を消去するだけでVSでプログラムの動きを確
       認しながら競プロで提出できる
     ・悪い点
       セキュリティの脆弱性は一切解決されていない
       バッファーオーバーランなど深刻なエラーが起きても奨励しない関数にはエラー検
       知機能がなく(そのため非奨励)そのまま実行しプログラムがクラッシュしたりパソコ
       ンの思わぬところに被害が出る。
    
    まとめ
     競プロを行う上では#define _CRT_SECURE_NO_WARNINGSを使う方が良さそう
     しかし、開発などを手掛けるのであればセキュリティに強い関数を使うべきである。
     
    /*すこし調べましたが文章や具体例はすべて僕なので間違いや不適切な表現はあります
     //_CRT_SECURE_NO_WARNINGSってただの臭いものには蓋をするの原理だった
     //んですね…
     //適当に調べたというか自分の経験的に2種類しか思い浮かばなかったのですが他にあ
     //りますか?
     //あと間違いがあれば教えて頂けると嬉しいです 
       
POSIX(ポシックスまたはポジックス)
  各種UNIXを始めとする異なるOS実装に共通のAPIを定め、移植性の高いアプリケーション
  ソフトウェアの開発を容易にすることを目的としてIEEEが策定したアプリケーションイン
  ターフェイス規格である。

 

ファイルのオープン
  2種類のファイルのオープンモード
   ・バイナリモード
   ・テキストモード
  
  2つの違い
   ・バイナリモード
    OS環境に依存しない
    どんな環境でも1バイトも変更せずに取り扱える

 

   ・テキストモード
    OS依存、いわゆる環境依存文字
  
   例:改行\r\n
          windowsにおいての読み込み
     ・バイナリモード
       \r\n
          ・テキストモード
       \n
          /*同じファイルなのに違う文字で保存されてしまう*/
       //参考文献

 

ディレクトリとパス
  カレントディレクトリ(現行ディレクトリ)
    コンピューティングの分野で、階層型ファイルシステムを使用している場合にそのプロセス
              が現在関連付けられている(現在の位置にある)ディレクトリの事である。windowsでは作
              業フォルダともよばれることがある。
  パス
    個々のディレクトリやファイルが、ディレクトリツリーの中のどの位置にあるか
    つまりディレクトリやファイルの住所などのような情報の事をパスと言う

 

  絶対パス表記
    ルートディレクトリ「/」からのカレントディレクトリをたどる
    /Ri_ma/C/wakaranai

 

  ソリューション
    問題を解決するためのコンピュータシステム

 

C言語の文字
  C言語の文字をintで扱うのはアセンブリレベルではどうせintで扱うため
    またchar型がint型と比較するときchar型の値が自動的に同等のint型に変換される
                                                                                                (integral promotion)
  
  /*C言語高級言語*/
   //ソースプログラム→コンパイラ→オブジェクトプログラム==機械語==アセンブリレベル

 

   /*int型は計算が一番早い型*/
      //いくつか調べましたがshort int型の方が速い(単純にint=32ビット,short=16ビット)
   //というのをいくつか見かけたので…
   //「前置詞 int型」以外の型(char型やfloat型)と比べれば速いみたいです

 

integral promotion
  int型よりrankの低い整数値型の値はすべての値が表現できるのであればint型に変換できる

 

  
典型的なビット長
        型      ビット                     最小範囲
                   char    8                       -128~127
         signed char     8                       -128~127
     unsigned char     8                            0~255
                short int     16                       -32,768~-32,767  
    signed short int     16                             -32,768~-32,767
unsigned short int     16                                       0~65,535
                     int   32(稀に16)  -2,147,483,648~2,147,483,647
             signed int     32(稀に16)    -2,147,483,648~2,147,483,647 
         unsigned int     32(稀に16)          0~4,294,967,295
                 long int     32                 -2,147,483,648~2,147,483,647
     signed long int     32                 -2,147,483,648~2,147,483,647
 unsigned long int     32                                       0~4,294,967,295
              float    32                                       小数精度6桁
              double   64               小数精度10桁
         long double   80            小数精度10桁

 

     /*C言語の規格では*/
      //char<=short<=int<=long<=longlong
                   //longlongはちょっとわかりませんでした…
      //大きさを超える値を代入すると
      //char ch=128 printf("%d",ch);→→-128
                   //char ch=129 printf("%d",ch);→→-127
                   //char ch=130 printf("%d",ch);→→-126
      //範囲を超えると最小値からスタートする
      //VS、wandboxも同じ結果

 

<stdint.h>
  C言語の標準ヘッダ
  指定の幅を持つ整数型を宣言し、それらの宣言に対応するマクロを定義します
  例:
   typedef==int8_t→signed char型
        解釈
     8バイト(上記に記したバイト数)と一致するのはchar型
    
      typedef==int32_t→int
        解釈
     int型の32バイト(上記に記したバイト数)よりint型

 

sizeof演算子
     sizeofに渡された型や変数のメモリサイズを調べる物



    
ストリーム
  ・バイトストリーム
    バイトのシーケンスとしてファイルを扱う
    プログラム内ではストリームはバイトシーケンス
  ・ワイドストリーム
    柔軟なストリームは、エンコーディング規則の広い範囲を持つことができ
    る汎用的なマルチバイト文字のシーケンスとしてファイルを扱います



   /*ここらへんはMSDNを書き写しましたが具体的にストーリムとは何かからわかりません*/
    //ストリームとはユーザ・プロセスとデバイスまたは疑似デバイス間の二重結合のこと
    //である…

 

YSRさんのまとめ
  1.ビット演算→uint_ナントカ
  2.unsignedなループ変数→size_t
       3.64bitなど長い幅を必要とする変数→int64_t
       4.その他基本的な整数→int

 

ビット演算
  固定長のワードなどといった「ビットの塊」に対して各のビットすべてに対する論理演算を
  いっぺんい行う演算操作である

 

ループ変数
  for(i=0;i<10;i++){}
     一般的にこのfor文においてiをループ変数という
    
    /*白山風露さんの部分はまったく何も…*/
     //とりあえずint型とchar型は注意

 

まとめ
  今作られている計算機は数学的な整数を格納できないから場合によっていろんな整数型が必
       要だから場合を問わず一気にintを使うのは現実の複雑さから逃げるということだけ恥であり役
       に立たない

 

  /*今までint型,char型と参考書に書いてあることだけを無意識に書き写していたので耳が*/

   //痛いですね…

独C9.2-2

独習Cの進捗状況

ここあさんにVSのコマンドラインの使い方教えてもらいました!
-------1月24日----------------------------------------
最重要

/*分からない関数などのネット検索*/
  //man 関数名
 //関数名 MSDN
 //と検索するとわかりやすいサイトに誘導される


 //よくわかってないので飛ばしています…

Visual Studioでのコマンドラインの使い方
 プロジェクトのプロパティ > 構成プロパティ > デバッグ > コマンド引数
でできましたよ~

 
/*分からない関数などのネット検索*/
  //man 関数名
 //関数名 MSDN
 //と検索するとわかりやすいサイトに誘導される



 //よくわかってないので飛ばしています…

 

if判定式内での変数代入
  if*1==EOF)
  ただif判定式内でも変数代入できるという確認

 

ifの扱い
  while文内でのif()はどんなに長かろうと1行とみなされる

 

   例
    while(*p)
   if(fputc(*p++,fp)==EOF){
printf("ファイルを開くことができません");
exit(1);
   }
    /*いろいろ応用効きそう(?)*/
//ただ今は危ないのですべてに{}をつけていきます…

 

exit
  <stdlib.h>必須!
  使用時は毎回確認




一般的なファイルの扱い
  
/*読み込みようにmyfileを開く*/
if *2 == NULL) {
printf("ファイルを開くことができません\n");
exit(1);
}

 

/*典型パターン例*/
 //if判定式中にFILEを指定する
 //作業をする関数(ファイル,作業内容)
 //がNULLの時(大抵操作が失敗するとNULLが返る)
 //printfでエラーを報告し
 //exitでプログラムを終了させる

 

プロジェクトのプロパティ > 構成プロパティ > デバッグ > コマンド引数
でできましたよ~

 

*1:ch=fgetc(fp

*2:fp = fopen("myfile", "r"

独C9.2-1

独習Cの進捗状況

-------1月22日----------------------------------------   

 

fgetc()
 ・「ストリーム」が示すファイルから次のバイトを
  unsigned char型の値として読み込み、int型の値として返す
 ・エラーが起こるとEOFを返す
 ・ファイルの終わりに到達したときもEOFを返す
 ・戻り値をchar型の変数に代入可能

 

fputc()
 ・「文字」の以下バイトを「ストリーム」に結びつけているフ
  ァイルにunsign char型の値として書き込みます。
  「文字」はint型と定義されていますが、単にchar型を渡して
  も問題ありません。これは一般によくとられる手法です。
 ・成功すると書き込んだ文字を返し、エラーが発生するとEOFを返す



/*文字がchar型とかint型とかピント来ないイマイチわからない*/

 

exit()
 ・<stdlib.h>
 ・現在実行中のプログラムを終了させる

 

break;
 ・for,do,while,ループを一つ脱出する

独C9.2-1

独習Cの進捗状況

-------1月22日----------------------------------------   

 

fgetc()
 ・「ストリーム」が示すファイルから次のバイトを
  unsigned char型の値として読み込み、int型の値として返す
 ・エラーが起こるとEOFを返す
 ・ファイルの終わりに到達したときもEOFを返す
 ・戻り値をchar型の変数に代入可能

 

fputc()
 ・「文字」の以下バイトを「ストリーム」に結びつけているフ
  ァイルにunsign char型の値として書き込みます。
  「文字」はint型と定義されていますが、単にchar型を渡して
  も問題ありません。これは一般によくとられる手法です。
 ・成功すると書き込んだ文字を返し、エラーが発生するとEOFを返す



/*文字がchar型とかint型とかピント来ないイマイチわからない*/

 

exit()
 ・<stdlib.h>
 ・現在実行中のプログラムを終了させる

 

break;
 ・for,do,while,ループを一つ脱出する

独9.1

独習Cの進捗状況
-------1月21日----------------------------------------
fopen
  :VS仕様→fopen
    ↓
    #define _CRT_SECURE_NO_WARNINGSでエラー非表示
  
  必要ヘッダファイルは<stdio.h>
  ファイルを開いてストリームと結びつける
  開く操作によってファイルに結び付けられた構造体へポ
  インタを返す
  開く作業が失敗するとヌルポインタを返す

 

モード
  編集の内容を表す(簡略自己解釈)
  たくさんある。→独習C:P.246
  例:
    r:読み込み用にテキストファイルを開く
  w:書き込み用にテキストファイルを開く

 

FILE型
  サイズ、ファイルの現在位置、アクセスモードなど
  ファイルに関する様々な情報を格納する構造体

 

構造体
  1つの名前でアクセスすることのできる変数の集まり

 

NULL
  <stdio.h>ではNULLというマクロがヌルポインタとして定
  義されている

 

 ※ファイル操作ではポインタが深く結びついているため
  ポインタを変更したり、それの指しているオブジェト
  を変更すると幸せになれない
 
 ※有効なファイルが返されたかどうかは非常に重要なので戻
  り値がNULLでないことを"必ず"確認してください

 

ファイルを開く正しい方法
  例:
  テキスト入力のためにmyfileという名前のファイルを開く

 

  FILE *fp;

 

  if*1==NULL){
    printf("ファイルを開く際にエラーが発生しました\n");
    exit(1);/*または自分で作成したエラーハンドラに置き換える*/
  }

 

 ※ファイルの存在についてそれぞれのモードによって対応が
  異なるのでチェックが必要
  (ファイルが新規作成されたり、上書きされたりする)

 

fclose
  必要ヘッダファイルは<stdio.h>
  ファイルを閉じストリームをファイルから切り離す
  「ストリーム」はfopen()で取得した有効なファイルでなけ
  ればならない
  成功すると0を返し、エラーが起きるとEOFを返す
  
  バッファをフラッシュ
    ファイルシステムの実装の多くは効率を上げるためにデ
    ィスクへのデータの書き込みを1セクタずつ行う。その
    ため出力されたデータは、まずバッファに蓄えられ、1
    セクタ分のデータが溜まったところでバッファからディ
    スクに物理的に書き込まれます。一般にこれを「バッフ
    ァをフラッシュする」と言います。

 

  注意:fclose()
    fclose()には決して無効な引数を渡してはなりません。
    無効な引数を渡すと、ファイルシステムが損傷を受け、
    場合によってはデータを失って復旧できなくなることも
    あります。

*1:fp=fopen("myfile","r"