野鳥紀トップページへ 野鳥の写真集・総合目次へ 観察野鳥一覧表へ 制作メモのページへ ご案内のページへ 一シギ二タカ三ツグミへ移動 動画集「ビデオカメラと野鳥」のサイトへ移動

VisualStudioメモ

VisualStudioCommunity2019

(200506)フリーのVSをインストールしました。
事の始まりは、いつも使っているHSPで、テキストファイルの操作に11分かかる
スクリプトを作った事でした。
これではどうしようもないと思い、C言語か何か、コンパイラを探しました。
結局、VSに挑戦してみる事にしました。
色々かじってみたのですが、Cでは画面が作れない、C++は難しい、
という事で、現在、C#で右往左往しています。
以下は、極めて個人的なドタバタの記録です。
なお、先の11分の件、今は解決しています。
CやC#を調べていくうちに、HSPでの私のスクリプトの欠陥に気付きました。
改良した結果、HSPでも500ミリ秒で終わります。

200915
C#、キーイベント

プログラミングの過程で、当初は、マウスでのボタンクリックから作業を始める、という段取りで行きます。
最近の言語は、全部、そのようにボタン類から作業を始めるようになっているようです。

ただ、プログラムや作業の段取りが固まってくると、操作性の問題になります。
作業が単純で大量の処理が必要なものになると、マウス操作よりキーボードからの操作の方が簡単かつ素早く処理できます。
コードが高速に処理されるという事ではなく、実際の作業が簡単になる、という意味です。
そこで、マウスでボタンクリックから始まる作業を、キーイベントでも代替できるようにしていきます。

例えば、「下へ」というボタンが作ってあって、このボタンをクリックすると、次の写真を表示する、という動作をさせていた場合です。
キーイベントを拾うようにして、キーボードの下カーソルが押された事が分かれば、その「下へ」のボタンのルーチンへ飛ぶようにします。
同様にボタンとマウスで操作していた作業を、どれかのキーの押下げにも対応させ、結局、キーボードでほとんどの操作できるようにします。
こうすると、実際の作業の効率が格段に上がります。プログラムの処理速度の問題ではありません。

このキーイベントの事を色々調べました。
当初は、特殊キーの補足に関して、面倒そうな記事が多かったのですが、まず試してみることにしました。

最初に、フォームのKeyPreviewプロパティをTrueにしました。
これで、Form1_KeyDown等で、大半のキーは取得できました。

しかしながら、色々試すうち、この方法ではうまく行かないと気付きました。
多くの記事にある様に、ボタンにフォーカスがあると、まったく役に立ちません。ボタンにフォーカスがある状態で、上カーソルを押すと、上のボタンにフォーカスが移動するだけです。
下カーソルだと下のボタンに移動してしまいます。
つまり、プログラムでキーイベントを補足できない状態です。

試していく内に、解決策を見つけした。
何故か、フォーカスがボタンではなく、テキストボックスにある状態だと、キーコードを取得出来ます。
(想像ですが、テキストボックスでのイベントを作っていないからだろうと思います。)

そこで、当たり障りのないテキストボックスに常時フォーカスが行くようにします。
private void button1_Click()などのボタンのクリックを拾う関数の末尾に、例えば、
this.ActiveControl = this.textBox3、などと書いておけば、マウスでボタンを押しても、フォーカスはテキストボックスに飛びます。
面倒ですが、これをボタン全部に書きました。大変でした。
これで、キーコードが拾えない事はなくなりました。動作としては、こちらの意図通り動きます。

しかしながら、この状態で使っていく内に、再度の不備に気付きました。
そのフォーカスを集中させているテキストボックスの文字が反転してしまう場合があります。
反転したり、しなかったり、条件は分かりませんが、とても見苦しく、気になります。

解決策にたどり着きました。
フォーカスを集中させるためだけのテキストボックスを作りました。ダミーです。何も書込みません。
これを最小限の大きさにして、目につき難い所に置いておけばいいではないか、という事です。
これでもいいのですが、半信半疑で調べたら、テキストボックスは見えないように出来ます。
プロパティにvisibleというのがあって、falseにすると、実行時には見えません。
何のためにあるのでしょうかね。

そこで、全部のボタンの操作後に、ここにフォーカスを持っていくようにしました。
これで、めでたく、キーコードの取得がいつでも出来るようになりました。

まだ使い込んではいませんので、何か不備が出るかも知れません。

ただ、あと一つ、分からない事があります。
本当は、プログラム側でNumLockのON、OFFを操作する事が出来ると楽なのですが、その方法がよく分かりません。
ONの状態でもOFFの状態でも、それぞれコードは帰ってきます。
どちらのコードでも同じ動きをさせれば、実用上はなんとかなりそうに思います。



200913
C#、削除、ゴミ箱へ移動
ファイルの削除で悩みました。
単なる削除の方法はすぐ見つかります。
欲しいのは、即削除ではなく、ゴミ箱へ移動です。

苦労の末、これも何とか見つけ出しました。
using Microsoft.VisualBasic.FileIO
FileSystem.DeleteFile(@フルパス, UIOption.OnlyErrorDialogs, RecycleOption.SendToRecycleBin);
だそうです。

ただ、これを移しても赤線が消えません。
マウスカーソルを赤線に乗せると、参照がどうのこうのというダイアログが出ます。

この意味が、ようやく分かりました。
いえ、意味は相変わらず不明ながら、対策は分かりました。

メニューから、プロジェクト、参照の追加、でリストが出ます。
その中の、Microsoft.VisualBasicにチェックを入れて、OK、で赤線が消えました。
実際に試すと、確かにゴミ箱へ入ります。



200911
C#、ディスプレイのサイズなど

相変わらず、写真ビューアを作ろうとしています。
その中で、フォームの縦横のサイズとかディスプレイのサイズとか調べる必要がありました。
このサイズ関係は、比較的簡単なコードで取得できます。

で、フォームを全画面で起動して、その結果は、

タスクバーをロックしていたら、
フォームがある画面のサイズ横:1920
フォームがある画面のサイズ縦:1080
フォームがある画面の作業領域のサイズ横:1920
フォームがある画面の作業領域のサイズ縦:1040
フォームX座標:-8
フォームY座標:-8
フォーム全体サイズ横:1936
フォーム全体サイズ縦:1056

タスクバーを隠していたら、
フォームがある画面のサイズ横:1920
フォームがある画面のサイズ縦:1080
フォームがある画面の作業領域サイズ横:1920
フォームがある画面の作業領域サイズ縦:1080
フォームX座標:-8
フォームY座標:-8
フォーム全体サイズ横:1936
フォーム全体サイズ縦:1096
という結果でした。


コントロールパネルなどで見たディスプレイの解像度は、1920x1080です。
見よう見まねで作ったコードに間違いが無いとして、実際には公称のサイズより若干の余裕がある様です。
具体的には、上下左右に8ピクセルずつ余分に作ってあることになります。



200901
C#、写真表示、拡大縮小、劣化
写真を表示する方法で苦労しています。
ここに来て、ようやく目途が立ちました。

方法は探せば探すほど出て来ます。星の数ほどあるように感じます。
その中で、自分の目的にあったものを探すのは大変な苦労です。
元々、系統的な知識のないままに始めたC#ですので。

やりたいことは、写真の表示と、その拡大縮小表示です。
まず、 pictureBox1.ImageLocation、という、これでいのかというほど簡単な方法がありました。
事前に、ドッキングとかZoomとかpictureBoxの設定がいくつか必要ですが、この一行で写真の表示ができます。
ただ、拡大縮小が思い通りに出来ません。もちろん、私が知らないだけだろうと思います。

そこで、次に、
Image.FromStream()、というものを試しました。
これもうまく行きません。
いえ、表示は簡単に出来ますが、拡大とか縮小とかする段階で、問題が出ます。
拡大縮小していく内に、画像が劣化していくのです。
縮小は良いのですが、次にそれを拡大すると劣化していきます。
縮小したものをそのまま拡大しているのだろうと思います。

更にいくつか試した挙句、
Graphics.DrawImageに行き当たりました。
これだと、引数で写真の表示位置とサイズを指定できます。
未だ完全に理解は出来ていませんが、目的に合いそうです。
いえ、この方法でも、同じ写真の縮小と拡大を続けると、当初は画像が劣化していって、実用上は使い物になりませんでした。
縮小までは良いのですが、それを拡大していくと、g画像が荒くなっていきます。
つまり、縮小表示した画像を単純に拡大しているだけだろうと思います。
本来は、まず読み込んだ画像をどこかのバッファに置いておき、実際に画面に表示する場合は、そのバッファから必要な分をコピーして持ってくる、という形が普通だと思います。

具体的には、ネットの記事の見よう見まねですが、
Bitmap canvas = new Bitmap(pictureBox1.Width, pictureBox1.Height);
Graphics g = Graphics.FromImage(canvas);
Image img = Image.FromFile(@写真のフルパス);
g.DrawImage(img, 左肩の横座標, 左肩の縦座標, 横サイズ, 縦サイズ);
img.Dispose();
g.Dispose();
pictureBox1.Image = canvas;
これで、一回限りなら、どんな大きさにも対応できます。

2回目以降、つまり、先に表示した画像を拡大とか縮小する場合はどうしたらいいのか考えました。
極端な話、毎回ファイルから読み込んで表示する覚悟なら、上のサイズ類の数字を書き直して使えば済みます。
しかしながら、それでは抵抗があります。
そこで、上のどれかが、いわゆるバッファ操作だろうと見当をつけ、試行錯誤で確かめました。
Dispose()の説明にリソースの開放、とかあります。バッファを消しているのだろうという個人的な解釈です。

まず、どの関数でも共通して使える様に、勝手知ったるグローバル的領域に、
Bitmap canvas;
Graphics g;
Image img;
を持っていきました。
このうちのどれか、あるいは全部がバッファの設定になっているのだろうという期待です。
グローバル的領域とは、
public partial class Form1 : Formの下です。
ここで定義した変数類は、何故かどの関数でも使えます。理由は分かりません。

エラーを大量に発生させながら試行錯誤していくと、
最初の読み込みルーチンは、
if (img != null) img.Dispose();
if (g != null) g.Dispose();
canvas = new Bitmap(pictureBox1.Width, pictureBox1.Height);
g = Graphics.FromImage(canvas);
img = Image.FromFile(@写真のフルパス);
g.DrawImage(img, 左肩の横座標, 左肩の縦座標, 横サイズ, 縦サイズ);
pictureBox1.Image = canvas;
でうまく行きました。
ここで、1、2行目のif文は、多分、こうしておかないと、写真が変わった時に、バッファ、リソース、メモリ?の類を消しておかないといけないのだろうという想像です。効果や影響は分かりません。
実行しながら、タスクマネージャーなどで、メモリの使用率などを見ていくと、想像していたようには動いていませんが、少なくとも、メモリを使いっぱなしにはなっていないようなので、これで良しとします。

次に、拡大縮小ルーチンは、
canvas = new Bitmap(pictureBox1.Width, pictureBox1.Height);
g = Graphics.FromImage(canvas);
img = Image.FromFile(@写真のフルパス);
g.DrawImage(img, 左肩の横座標, 左肩の縦座標, 横サイズ, 縦サイズ);
pictureBox1.Image = canvas;
でした。
こちらの1、2行目の、canvas=云々と、g=云々はこれが無いと、前の画像が消えません。何故かはわかりません。試行錯誤の結果です。


200830
C#、SplitContainer、PictureBox

画面を二つに分割する事で苦労しました。
最初に試したのは、TableLayoutPanelです。

本題から外れますが、
大文字小文字の使い方が面倒です。
ツールボックスでは、TableLayoutPanel、SplitContainer、です。
コードの中では、この頭文字が小文字になって、tableLayoutPanel、splitContainerと表記されます。
こういうものなのでしょうが、面倒です。
それに、どこかの時点で変更されたのでしょうか、例文などで、PictureBoxなどと書いてるものがあります。

さて、
写真のビューアを作ろうとして、画面を縦に二つに分割する方法を調べました。
右に諸元、左に写真を表示するという計画です。
一応、HSPでも作って使用していて、使用中の1920x1080のディスプレイに最適なコマ割りが、左側の幅を389ピクセル取ると、右側の写真領域の比率が丁度よくなるという事は計算済みです。

今使っている写真の大きさが、6144x4080と5568x3712の2種類です。
単純な比例計算で左側の幅を389ピクセルにすると、右側の縦横の比率が写真の比率と一致します。
つまり、普通に写真を表示した時に、縦横に隙間ができないのです。

とにかく、起動時に、全画面で起動した時、左側の領域を389ピくセルにする方法です。
まず、TableLayoutPanelというのがあることを知りました。
これの横線を0にすると、縦に二つに分割した画面が作れます。
これには、欠点が(私が知らないという意味です)、二つあり、
全画面をやめて窓表示にしても、縦の分割線に位置を変更できない事と、
左側に置いたボタンなどのコントロールの位置を指定できない事です。

そこで、次にSplitContainerというものを調べてきました。
これで、意図通りの画面が作れました。
Form1のWindowStateをMaximizedに、
splitContainer1のSplitterDistanseを389に、(ややこしいですが、これは、splitContainer1.Panel1ではありません。)
とすることで、所期の目的が達成されます。
全画面で起動しますが、窓にしても、左側は一応固定されています。しして、位置をずらしたければ、マウスでドラッグすると移動出来ます。



200828
C#、ボタン名、関数名

前回のフォームアプリで、ボタン名とそのイベントハンドラというのでしょうか、ボタンをクリックした時のコードを記述する関数の関数名が一致せず、困りました。
確か、コードの中で、button1.Enabled云々とある所で、右クリックメニューから名前を変更すると全部変わると思って、実行しました。
コードの部分は一括で変更できました。しかし、関数名が変わりませんでした。
ややこしい話で、以降はどこにそのボタンの関数があるのか分かりにくい状態になりました。関数名とそのボタン名とが違うのですから。
動きに関しては、意図した通りに動くので、問題はなかったのですが。

ようやく、正解が分かりました。変更する順番が大事です。
ボタン名とその関数名(イベントハンドラー?)の名前を合わせるには、まず、最初に、ボタンのプロパティでnameプロパティを変更しないといけません。
その後で、ボタンをダブルクリックして、そのボタンの関数を生成します。
こうすると、その関数にも書き換えていた名前が使われます。
順番を逆に、関数を先に作っておいて、nameを変更しても、関数名は変わりません。


200827
C#、型変換?
何気なしに、下のようなコードを書いていました。
int a =0;
string b="";
b+=a;
これがエラーになりません。
何やらの型変換が起きています。調べても用語が分かりません。当たり前の事なのでしょうか。



200826
C#、SelectedIndex、SelectedItem

comboBoxのSelectedIndexとSelectedItem、見様見まねで使っています。ようやく、違いが分かりました。

私の理解では、
comboBox1に、always、hourly、daily・・・、とデータ(選択肢)がセットしてある状態で、
comboBox1.SelectedIndexには、数字(int)が入ります。選択肢の先頭から0,1,2です。
選択肢の2番目のhourlyが選択されたら、comboBox1.SelectedIndexは、intの1です。
こちらの方はそのまま代入も出来ます。comboBox1.SelectedIndex=0;とすると、一番目のalwaysが選択された状態になります。
ただ、数字ですので、選択状況をボックス以外に表示する時や、テキストファイルに保存する時にはcomboBox1.SelectedIndex.ToString();、とします。

comboBox1.SelectedItem、には、選択肢の文字列、alwaysとか、hourly、とかが入っています。
こちらの方は、選択肢の文字列が取り出せます。方法が少しややこしいですけど。
直接、string str = comboBox1.SelectedItem;とするとエラーになります。
object型とかキャストとかのエラーメッセージが出ます。
(string)comboBox1.SelectedIndex;か、comboBox1.SelectedIndex.ToString();とすると、選択された文字列が取り出せます。

ここまで、整理してきて、comboBox1.Text、というプロパティ?があることに気付きました。
先のcomboBox1で3番目のdailyが選択された状態だと、dailyが帰ってきます。
目的は、この文字列を取得する事でしたので、comboBox1.TextでOKです。
comboBox1.Textに関しては説明してあるページが少ないように思います。新しく追加されたものかも知れません。


200825
C#、this.Close()
プログラムを終了する時(フォームを閉じる時)は、this.Close()、とあり、各所に置いています。
とにかく、意図通り終了できていました。

今日、変な動作をするケースに気付きました。
終了すると同時に、例外が発生しているようです。
例外が発生せず、期待通りに終了する場合もあります。
終了、というボタンを作って、そのクリックイベントでthis.Close()すると正常に終了します。
フォームにあるXボタンでも正常に終了できます。

this.Close()をあちこちに置いて調べてみました。
原因が大体わかりました。いえ、原因というか、発生する構造というか。
this.Close()の次のコードが実行されています。
次の行に、フォームのボックスに表示するコマンドが置いてあった場合は、
破棄されたオブジェクトにアクセスできません、という例外が発生しています。

並行処理、みたいなもので、動作を止め切れていない様子です。

ただ、この現象は、デバッグモードの時だけで、デバッグ無しで実行、だと発生しません。
多分、Releaseモードでも大丈夫なのではないでしょうか。




200820
VS、ショートカットキー

C#をというか、VisualStudioを始めて二か月半ほどでしょうか。編集中、メニューを開くのが段々面倒になります。
そこで、使い勝手のいいショートカットキーを覚えていきます。

最近、ようやく覚えたものに、
F5キーがあります。デバッグの開始です。
これまでは、いちいちメニューを開いて、ビルドし、メニューのデバッグをクリックしていました。
これを、F5一発で済ませられます。ビルドエラーの時は止まりますので、問題は無いという事に気付きました。

関数間の移動に、F12や、Ctrl+マイナスキーなど、便利ですね。

ショートカットキーの怖い所もあります。
万国共通の、コピーペーストの関連で、Ctrl+A、Ctrl+C、Ctrl+V、Ctrl+X、などは便利な反面、よく間違います。
よくやるのが、Ctrl+V、とすべきところをCtrl+C、としてしまって、クリップボードを空にしてしまう事です。



200819
C#、ボタン名の変更
ボタン類を増やして行くと、コードが読み辛くなります。
button1は何のボタンだったかな、という感じです。

そこで、ボタンの用途に合わせて、ボタン名を変えることを考えました。
button1.Enabled = false、とするより、
Btn_end.Enabled = false、等とした方が、
終了ボタンを無効化したな、と分かります。

これはこれでいのですが、悪影響が出ます。
一つは、ボタンをクリックした時の関数名はそのままです。
そして、変更後に更にボタンを追加すると、button1がまた作られてしまいます。

で、関数はどうなるかというと、
最初のボタン名を変更したボタンの関数は、
private void button1_Click(object sender, EventArgs e)、で
後で作られた、button1の関数は、
private void button1_Click_1(object sender, EventArgs e)
となっています。

動きに矛盾はありませんが、ちょっと分かりにくいです。
私の知らない方法が有るのかもしれません。



200818
VS、二重起動

未だ、分からない事も多いながら、VisualStudio2019のエディタにも多少は慣れたと思います。
ただ、困った事に、油断すると重複して起動してしまいます。困った物です。

新しくプロジェクトを作る時以外は、sinファイルのアイコンを作っておいて、そのアイコンをダブルクリックして起動しています。
このアイコンをダブルクリックしさえすれば、同じものが何個でも起動します。
今、試してみたら、本体を起動して出てくる最近のリストを選択しても同じでした。やはり、重複して起動できます。

TeraPadで試すと、二つ起動は出来ますが、同じファイルを読み込もうとしても読み込みません。
右クリックメニューから、ファイルメニューから、どちらもダメです。

メモ帳は普通に読み込めました。

VisualStudioCodeも試してみました。
こちらは、よくわかりません。肝心な所で英語が出てきたりして、要領を得ません。
読み込めたり、読み込めなかったりします。



200815
C#、str.Contains(s)
strにsという文字列が含まれるか、という所で、str.Contains(s)を使いました。

いえ、特に問題はなかったのですが、ここでfalseを試してみようと考え、
string s="";
if (str.Contains(s) == false){}
としました。
バグ取り、と言いますか、動作試験などで、よくやることです。

しかしながら、これが期待通りに動きません。{}内は通らず、スキップしてしまいます。
冷静に考えると、当然でした。""は、どこにでも含まれています。trueです。


200814
C#、エラー処理

C#、VSの範疇かも知れません、C#でデバッグ中にエラーが発生すると、ブレークポイントみたいな感じで止まります。
発生した行と、原因の説明が表示されます。
心配なのは、これが実行ファイルで発生した時、どういう処理になるのか、という点です。

今回、簡単なエラーが出ましたので、思い切って試してみました。

VSのメニューにあるデバックなしで開始、bin/Debugフォルダに保存されている実行ファイル、bin/Releaceフォルダにある実行ファイル、のいずれの場合も、例外が発生した、という意味のダイアログが出ます。
続行と終了の選択が出来ますが、実質終了するだけです。
終了と言っても、実質は強制終了ですが、平和的な感じで終了できます。

この時のエラーは、ファイルが見つからない、というものでした。
念のためにもう一つ、0で除算しました、となるものを作ってみました。

対応は同じです。
デバッグモードでは、その行で止まり、原因が表示されます。
デバックなしで開始、では、先と同じダイアログが出て、終了させられます。

ありがたいのは、そのダイアログをよく見ると、詳細、というボタンがあり、そこにエラー発生の説明や発生した行番号まで表示される事です。
これはReleaseモードの実行ファイルでも同じです。行番号が表示されます。



200813
C#、forループ
forループをよく使います。
いえ、他にもループがある事だけは知っていますが、使ったことがありません。使い方が分かりません。

いつも気になっていた事です、最初からforの条件式に合わない場合はどうなるのか、という事でした。
c=-1;の状態で
for (int i=0; i<c; i++)、のループに入った場合です。

今まで、適当にやっていて問題は出ませんでした。
今日、しっかり調べてみました。

解説のあるページはネットにも多いのですが、このかゆい所に手の届く説明はなかなか見つけられません。
そこで、最後の手段、F1でMSのヘルプを見てみました。
いつも、このF1で出てくる説明は、訳の分からない事が書いてある場合がほとんどです。
しかしながら、今回は大当たりでした。しっかり書いてありました。
肝心の部分を書き出すと、

conditionセクションの式は、ループの反復の前に毎回評価されます。
式が true に評価される場合、次のループの反復が実行されます。
そうでない場合は、ループが終了します。
だそうです。
conditionセクションとは、上の例では、i<c、の部分です。

実際には、もっとねちねちと書いてあります。要約すると上の様になります。
つまり、最初から条件式に合わない場合はループは一回も実行されない、と解釈できます。

問題は、私の解釈で正しいかどうかなのですが。
振り返ると、HSPでも同じだったような記憶があるかないか、おぼろげですか、思い出しました。
どこでも共通なのでしょう。

実際に、動作がその通りなのか、調べるのは難しいです。
プログラム流れで、実際には、先のループの前の段階で、
if (c<0) return;
みたいなコードを入れるからです。

ここで気が付いて、試してみました。簡単なコードで試せばいいのです。
int c = -1;
for (int i = 0; i < c; i++)
{
MessageBox.Show("内");
}
MessageBox.Show("外");

実行すると、外、だけが表示されます。

200810
C#、エディタ、<>

VSのエディタは機能が多くて便利です。
まだ、記号の意味や操作方法の分からない事も多いです。

その中で、困ることがひとつ、<や>の扱いです。不等号ですね。

今、サイトマップファイルを扱うプログラムを作っています。
そこで、頻繁に出てくるのが、<url>とか</loc>とかいう文字列です。
この文字列をタイプする分には問題ありません。
が、なぜかコピー、ペーストで持ってくると、エディタ側で勝手にスペースを入れてくれます。
< url >というようになります。
//の後に貼り付けるとか、""の間に持ってくるとかだと大丈夫です。
計算式と勘違いするのでしょうね。

もし、文字列の先頭が<url>となっているなら、という様な構文はよく作ります。
タイプミスを減らす為、文字列を引用する時は、出来るだけコピーで持って来るようにしています。
そこで、油断すると、先ほどの変化が起きます。困ったものです。



200809
C#、File.Copy()、更新日時
ファイルのバックアップを作る必要に迫られ、調べました。
System.IO.File.Copy(@path1, @path2, true);という関数を見つけました。
コピー先に同名のファイルがあっても上書きする、というものです。
文字コードの指定とか、宣言とか、前置きも何もいらない(多分)様です。すぐ試してみました。

何かが違います。
ふと気が付きました。
ファイルの更新日時が変わりません。いえ、多分変わらないのだと思います。
普通の事ですが、不便な点があります。
上書きされたかどうか分かりにくいという事です。

実は、HSPでは通常、コマンドでコピーすると更新日時が変わります。これも多分です。
更新日時が変わらないと、実際に上書きされたかどうか分かりにくいのです。
上書きされた際、更新日時がその上書きされた時間になるなら、前回のコピーの後、1分待って試してみると結果が分かります。
コピー元のファイルの日時のままだと、こうはいきません。1分待ってコピーしても、あれ、上書きされなかったかな、と心配になります。
ファイルの中身を変えるなりして、その中身を見てみないと分かりません。

元々、エクスプローラなどでコピーする場合は、更新日時は変わりません。
当たり前で、まあ、慣れの問題かもしれません。



200808
C#、Win8.1、.NET

このPCと無関係の環境で、C#の実行ファイルを起動したいことがあり、マルチブートのWin8.1に切り替えてみました。
これが、立ち上がりません。
エラーメッセージのダイアログが英語ですので断定ではありませんが、意味は、.NETFramework、Ver4.7.2が必要だ、インストールするか、と書いてあるようです。
確かに、C#のプロジェクト云々の時、NET云々が沢山出ていました。必要な物なのでしょうし、私の8.1は飾りみたいなもので、必要最低限と言いますか、何も追加してありません。

Win10の方に、それがちゃんと入っているのか、入っていないはずはないのでしょうが、調べてみました。
これが結構面倒でした。

まず、コントロールパネルなどにあるプログラムと機能を見てみました。
ありません。
Windowsの機能の有効化の所に、.NETFramework、3.5の記述はあります。
これでは足りません。
もう一つ、.NETFramework4.8AdvancedServices、というものもあります。
4.8だからよさそうなものの、その後ろの英語の意味がよく分かりません。

そこで調べてみました。
MSのページにバージョンの確認方法が書いてありました。
regeditから調べられます。
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Fullのキーがあれば4.5以上が入っている、あと、その先の細かい数字を調べるとバージョンも分かる、という事です。

で、その通り調べていくと、どうやら4.8が入っています。
これも、4.8と書いてある訳ではなく、適当な5、6桁の数字を見比べて判別する、というものでした。
これで大丈夫だという事になりますが、面倒な話でした。
なぜ、もっとはっきりと出さないのでしょうかね。

それに、普通には.NETは入っているものなのでしょうか。
そこで、旧機を調べてみました。Win10です。
こちらには入っていました。と言いますか、先の実行ファイルがすんなり立ち上がりました。
必要な.NETはインストールされているという事になります。





200808
VS、バージョンアップ
VSのバージョンアップのダイアログが出ました。
バージョンアップは頻繁に出ます。5月に始めて、月に一回以上のぺーズだと思います。記録はしていませんが。
今回は16.7.0です。いつもの様に、すぐ実行しました。

今回は変化がありました。嬉しい事ではありませんが、起動時にダイアログが出るようになりました。
ソリューションを準備しています、とかいうメッセージです。
このダイアログが出ている時間は一秒そこそこです。
出ない時もあります。何度か試している内に、状況が分かりました。
PCを立ち上げ、最初にVSを使う時だけです。2度目からは出ません。
状況はVSを立ち上げ、リストにある目的のsinをクリックして起動する場合でも、直接sinのショートカットから立ち上げても同じです。最初にsinを起動する時、一回だけ出ます。
これが、PCの再起動でリセットされるみたいで、また最初の一回だけ出ます。

起動時のダイアログでは、バックグラウンドタスクがまだ実行中です。というものもあります。
これは、必ず出ますが、ひっそりと出ます。気にすることもないようなメッセージです。
今回のダイアログは、画面の真ん中に出ますので、とても気になります。
何も出さずに待たせる方が良いと思います。その方が、ほんの僅かでしょうが、早いはずです。

私の環境での、ショートカットからの起動に要する時間は、
一回目の起動、その面倒なダイアログが出る場合です、カーソル点滅まで15秒、バックグラウンド云々が消えるまでに更に10秒ぐらいでした。
2回目以降は、エディタのカーソルの点滅が始まるのに約10秒、バックグラウンド云々のダイアログが消えるまでに更に5秒ぐらいです。
あ、この差はダイアログのせいではなく、一回起動すると、何かメモリに残すのでしょうね。
また、この差があるせいで、一回目だけ、間つなぎのダイアログを出す様にしたのでしょう。
面倒な事です。

200812追記
再度、バージョンアップの通知がありました。16.7.1です。
すぐ、アップデートしました。
前回は、確かPC自体の再起動が要求されたと思いますが、今回はありませんでした。
今回の変化は、参りました、起動時の、ソリューションを準備しています、のダイアログが毎回出るようになりました。

起動に要する時間を再確認してみました。
PC起動後の一回目のVSの起動が、15秒+10秒、
2回目以降が、10秒、5秒、程度です。変わりません。
気持ち遅いようにも感じます。気のせいでしょう。


200807
C#、プリプロセッサ命令、#if DEBUG、注釈

デバッグモードの時だけ実行させたい命令があります。
動作確認用にダイアログするとか、テキストボックスに途中経過を表示するとかです。
HSPでは#defineで同じ様な事が出来ていました。
C#でも探していましたが、今日ようやく、このコマンドにたどり着きました。
#if DEBUG
#edif、です。

文字通り、VSのエディタでDebugにしている時だけ有効になるコマンドです。
Releaseにしていると、VSから起動した場合でも、Releaseフォルダにあるビルドした実行ファイルでも、このコマンドに挟まれた部分は実行されません。
逆に、Debugにしている場合は、メニューで、Debugなしで開始、でも実行されます。

この件、と言いますか、条件付きで実行したい場合、色々試しています。
//の注釈行は手軽なのですが、コードが長くなると手間です。
/*・・*/は復数行指定する時に便利なのですが、ネストが効かないというか、よくわからない状態になります。
コメントアウトしたい部分の一部に、既に/**/を使っている場合、よくわからない状態になります。

以前、調べた事で、#if trueがありました。
デバッグに関しては今日の分が便利です。書き直す必要がありません。


200804
C#、int、return
C#では、毎日の様に驚く事があります。

恥ずかしながら、
int aa(string bb)
{
  int cc;
  for (int ctr = 4; ctr < dd; ctr += 7)
  {
    bool tof = ee[ctr].Contains(bb);
    if (tof == true)
    {
      cc = ctr;
      break;
    }
  }
  return cc;
}
という感じのコードを書きました。

最後のreturn cc;に赤い波線、インテリセンスでしたか、が出て消えません。
マウスカーソルを当てると出てくる解説には、未割当云々と出ています。
解決後に考えると、その解説の通りなのですが、発生時には慌ててもいますし、理解不能でした。

原因は、最初の宣言で
int cc=-1、等、初期化?;が必要という事です。
納得は出来ますが、厳しすぎるようで、少し考えていただきたいような気もします。

先日、returnはループの中からでも問題ない、という事を知りました。
それに、trueは省略できますので、
少しスマートに(極めて個人的な感想です。)書き換えてみました。
int aa(string bb)
{
  for (int i = 4; i < dd; i += 7){if (ee[i].Contains(bb)) return i;} return -1;
}
と書けそうな気がします。
いま、試すと、エラーは出ていません。動作は未確認です。
動作も試しました。意図通り動いています。動いているように見えます。

こうなると、関数にする必要もありません。
ただ、分かりにくいし、本当に意図通りなのか、確信が持てませんので、私には使えません。
元に戻して、使っています。

200802
C#、str.TrimEnd()

末尾の空白行を削除するという事で、str.TrimEnd()を使ってみました。
全て手書きで作ってる場合は問題にもならない改行コード(0D0A、CRLF、\n、\n\a、以下改行)ですが、プログラムで行数をチェックしていると、これが問題になります。

そこで、簡単に末尾の改行を消せるみたいで、表題のメソッド?、関数?、を使ってみる事にしました。
どのような動作になるのか、コードの前後を調べました。
・・
・・
</urlset>改行
改行
改行

となっているファイルをstr.TrimEnd()を通すと

・・
・・
</urlset>

となります。
つまり、末尾にある改行は全部削除されます。
末尾の行は</urlset>だけになります。直後の改行も消えます。
これで問題はありません。
行数はちゃんとカウントされます。

なお、最後の行に改行のあるなしは、行数のカウントでは同じです。
つまり、末尾が
</urlset>改行、と
</urlset>、だけの行は、同じ一行です。



200802
C#、throw
try、cacth、throw、構文というのでしょうか、ネットから頂いたコードの中にありました。
指定のページが実際にサーバにあるか調べる為に使わせていただいています。
ページがある場合は、何も問題なく処理されます。
しかし、でたらめなURLを指定すると、throwの所でエラーで止まってしまいます。

on error gotoみたいなものだと思っていましたので、びっくりです。
デバッグモードでしたので、もしかと思ってリリースモードで試してみました。
こちらでは、ダイアログが出ます。続行するか終了するか選択するものです。
続行を選ぶと、すんなり回復します。
自前のダイアログを出す方法があればと探しましたが、見つけられません。


200720
C#、フォームに四角形の描画

フォームで画面を作っていく時、四角形を描画したい場合があります。
ボタンとかボックスとか幾つか配置してあり、このボックス類は一つのグループです、みたいな表示をしたい時です。

調べても、調べても、この方法が分かりません。
その中に、ラベルが利用できる、みたいな記事がありました。
正式に作る方法が分からないので、そのラベルを転用する方法に挑戦しました。

普通にラベルを配置します。
右クリックメニューに最背面へ移動、があります。こうしないと他のコントロールが隠れてしまいます。

そのままでは、文字数に合わせた小さなボックスで、どうしようもありません。
後、プロパティを変更していきます。
文字があるとまずいので、Textを削除します。
AutoSizeをFalseにすると、サイズを自由にできます。これで大きな四角形が描けます。
BorderStyleをFixedSigleにすると枠線が出てきます。
BackColorで色の指定が出来ます。

これで、必要なコントロールを囲うことが出来ました。


200729
C#、カレントフォルダ
レジストリが使えるなら、問題にはならない事でしょうが、そのような知識はありません。
あちこちに、素人は、レジストリをいじるなと書いてありますし。

プログラムでカレントフォルダを調べることは、簡単にできます。
System.Environment.CurrentDirectory、です。
ここにファイルを置きたいことはよくあります。
作業内容を次回の起動時に復元したい時に使う設定ファイルなどです。

さて、C#の場合、多分VS共通だと思いますが、このカレントフォルダが複雑です。
まず、コードが書かれているForm1.csがあるフォルダがあります。
ただ、これはカレントではありません。
ソリューションのフォルダ、あるいはプロジェクトのフォルダというべきものでしょう。
私は、今だに、ソリューションとプロジェクトの違いが分かりません。

さて、カレントは実行ファイルがあるところです。
この実行ファイルが二つあります。デバッグ用とリリース用です。別々です。
\bin\Debug
\bin\Release
となっています。

ですので、先の設定ファイルなどDebugフォルダに置いておかないといけません。
面倒な事です。こうしないと、動作試験ができません。



200726
C#、forループ、return、break、goto

これまで、forなどのループの中で、途中で抜け出すには、breakと覚えてきました。
ですので、ネストされたループから抜け出すのにフラグを使ったりして苦労したものです。

ここまで、C#でも同様に思っていましたが、詳しく調べてみたら、違うようです。
gotoでもreturnでも自由に抜け出せるようです。


200726
C#、false、!
if (!kkk.Contains(rrr) == false){}
このコードが意図通り動いてくれないので困りました。

原因は先頭についている小さな!でした。
ネットで、文字列が含まれているのか調べる構文をコピーしてきて使いました。

元々は、f (!kkk.Contains(rrr)){}、となっていたものです。
これで使わせていただいていたのですが、コードを見直す最中に、やはり、==が欲しくなります。
==が無いと直感で分かりにくい事と、
最近、trueとfalseのスペルを覚えましたので、==false、を付けて、見やすくしようとしました。

すると、突然、動きがおかしくなりました。
先頭の小さな一文字を消し忘れていたのです。



200725
C#、配列のコピー

文字列の配列のコピーに Array.Copy()を使いました。
この動作が、参照なのか値のコピーなのか分からず、困っています。
ネットでは、参照渡しになっていて、コピー先を変えると、コピー元も変わってしまう、と書いてあるようです。
逆にそんなことはない、と書いてあるように見えるものもあります。
一番の問題点は、私が専門用語を理解できない事なのですが。

そこで、実際に試してみました。
Array.Copy()で、配列kkから配列mmへコピーした直後です。

1行目を表示させると、
kk[0]は、<?xml version="1.0" encoding="UTF-8"?>
mm[0]は、<?xml version="1.0" encoding="UTF-8"?>

次に
mm[0] = "test"、としてみた結果です。
kk[0]は、<?xml version="1.0" encoding="UTF-8"?>
mm0]は、test
となっていました。

念のため、
kk[0] = "testtest"、としてみた結果は、
kk[0]は、testtest
mm[0]は、test
でした。

これで、はっきりしました。
参照ではない、という事です。

string型の配列の場合、参照ではない、と書いてある記事も見ました。
これだろうと思います。



200725
C#、バックアップ
プログラムを作りながら、ここでバックアップを作っておきたいと思う時があります。
やみくもに発展させてしまって、どうにもならなくなって、元のちゃんと動く状態まで戻そうとするときの為です。

HSPなら、単純にファイル名を変えるなり、フォルダを変えるなりして、毎日でもバックアップしておけました。
どうやら、VSでは単純ではないようです。
設定ファイルみたいなものがあって、バックアップから単純に戻しても動かない、みたいです。
でも、一応、節目節目で、フォルダごとバックアップしてあります。
しかしながら、これを戻してみた事はありません。
戻す場合は、フォルダごと戻さないといけないでしょうし、そうすると、現在のファイルをどこかに退避する必要がありそうです。
その退避した方が使えるか不明です。
バックアップも現在のファイルも同時に使えないと、怖くて使えません。

200829追記
フォルダごとのバックアップは有効でした。
プロジェックトを作って、被害が少ないように、比較的早めに試してみました。
フォルダごとバックアップしていたものを、元のフォルダに、そのまま何も変えずに戻すと、普通に動きます。
ついでに、フォルダを変えてしまううとどうなるかも試しました。
動きます。起動に少し時間がかかったような気がしましたが、何事もなく動きました。


200724
void、boid

boid サブフォルダ変更()
今日作った関数名です。これがエラーになって、原因が分からず、気が付くのに1時間以上かかりました。

赤い波線が出て、消えません。
関数内のreturn;の所にも波線が出ています。ヒントには型が違うみたいな表示だったと思います。

このヒントがよく出来ていると思います。赤い波線、インテリセンスの事です。
マウスカーソルを波線の上に持ってくると、エラーの原因やヒントが出てきます。
残念な事に、それを読んでも理解できる程の知識がありません。
ヒントの中に、解決策出ています。クリックしていくと、その案に沿ってコードを書き換えてくれます。
この方法で解決する場合もあります。

今回は、四苦八苦した挙句、スペルミスに自分で気付きはしました。
後で確認したことです。先のヒント、いくつかの解決案が箇条書きに出ているのですが、その最下段に、
boidをvoidに変更、という項目も出ていました。

あらためて感心すると同時に、最下段での案内です、そんな間違いはまずないだろうと思われているようです。

200723
VS、フォントサイズ
エディタのフォントサイズは、Ctrl+マウスのスクロールボタンで簡単に変更できる事に気付きました。ただ、多少の不便さがあります。
VSのメニューとCtrl+のショートカットが連動していません。
設定が維持されない時があります。

VSの使い始めの頃、フォントサイズの変更に苦労した覚えがあります。設定は、ツール、オプション、環境、フォント及び色、にあります。
どうやら、Ctrl+は規定外かもしれません。

メモ帳でも試しました。
メモ帳でも、Ctrl+マウスのスクロールボタンで変更できます。
つまり、Win共通のショートカットなのでしょう。

ただ、やはり、安定しません、と言いますか、設定が維持されません。。
メモ帳では、メニューの、書式、フォントで簡単に設定できますので、行き来して調べました。
ショートカットと連動していません。
ショートカットでの変更は、その場限りの変更の様です。
メモ帳を再起動すると、メニューで設定したサイズに戻ります。

VSでは、どうやら、すべて保存を実施した後では、設定が残るようです。
それでも、設定メニューの数字は、つまり、メニューに表示されるフォントサイズは実際と合いません。
ショートカットで変更して、そのサイズが維持される場合でも、ツールオプションの中のフォントサイズは変わりません。
多分、です。何しろ再確認が面倒なので、好みの大きさからもう変更したくありません。



200723
サイトマップファイル

このサイトは、一応、サイトマップファイルが作ってあります。HSPでの半自動化の一環です。
この作業がここまでの懸案で、半自動化のメモに書いていますが、何しろ30000行、600KB程のテキストファイルです。
ファイルを更新するのに50秒程かかっていました。
ページの更新はほぼ一日おきにしていますので、この作業も一日おきです。少し辛い物がありました。
この問題は、こちらのC#などを勉強する過程で原因に気付き、現在では3秒程度で終わる様に改良しました。

更に、このC#をかじっていく内に、C#がコンパイラと同じ程度に高速だという事を実感する様になりました。
そこで、このサイトマップファイルの更新作業をC#で組もうとしています。
現在、このページのメモは、大半、この作業に絡むものです。

そして、今、大まかなところで出来上がりました。後は、エラー処理と操作性の改良だけです。
そこで、実行時間を測定してみました。
やはりC#だと、ミリ秒の世界です。
実行時間は、ソートが入れてある関係で、ファイルの先頭近くに追加するか、末尾近くになるかで大きく違います。
一番手間を食うような状況、つまり、ファイルの末尾に追加するような作業で、500ミリ秒程度で終わります。


200722
C#、フォルダ選択ダイアログ、プロパティ
フォルダ選択をマウスで指定出来るように、と調べると、これが出てきます。
FolderBrowserDialog fds = new FolderBrowserDialog();

ただ、これは必要最低限と言いますか、まあ、意図通りには動きますが、操作性はよくありません。
本来は、普通のエクスプローラと同じ操作性で、左側にクイックアクセスやドライブなどが表示され、右側で目的のフォルダを選択するものです。

先のダイアログだと、その左側部分がありません。
それに、どうやらデスクトップが既定になっているみたいで、これが選択リストの最上段に出てきます。
必要なフォルダは、データドライブの中の、かなり深い位置にあり、スクロールしないと出てきません。

せめて、初期のフォルダだけでも見える状態で出てこないかと調べました。
fds.RootFolder = Environment.SpecialFolder.MyComputer;
とすると、何とか目的のフォルダが見える状態でダイアログが開きます。
これが確実ではなく、たまには別のフォルダが出てくるときもあります。
どうやら、前回の動作を覚えているようです。

200722
C#、テキストボックスの自動スクロール

複数行のテキストボックスの表示が、自動でスクロールする事に気付きました。
HSPではこれが無くて、苦労しました。システムコールか何かで実現させていました。
ボックスのプロパティに可否があるのかもしれません。
ま、うまくいっている所は探しません。

200720
#if、#endif、プリプロセッサ命令
#if true
#else
#endif
が使えます。

今まで、変数類を大幅に入れ替えて試したい時、
/*
*/、で囲んで、切り替えていました。
#ifの方が楽です。
trueをfalseに書き換えるだけで済んでしまいます。


200719
str.Remove(0, 1)

文字列の先頭ある「/」を削除したい時の処理、正しくは、
if (str.StartsWith("/") == true)
{
   str = str.Remove(0, 1);
}
なのですが、この=の前のstrを忘れて、
str.Remove(0, 1);だけにしてしいがちです。
困ったものです。
確かに、解説には、作業後の文字列を返す、と言うような事が書いてあります。

左側のstrに入る様だったら、右側にも入りそうなものですが、そうはなりません。

ただ、これとか、文字列の末尾の一文字を削る関数もあり、C#の便利な所です。


200717
C#、フォーム表示後にダイアログ表示、Form1_Shown()
フォームを表示させた直後の作業で、例えば、ファイルのあるなしを調べて、目的のファイルがない場合に、ダイアログでメッセージを出します。
この際、最初に配置されているpublic Form1()という関数がそれらしく、最初に実行されるのだろうと思い、ここにこの段取りを書き込んでいました。
ファイルの読み込みや、ボックスへの表示など、普通にはこれで予定通りです。
しかし、先の様にエラーのダイアログを出す様にしたら、肝心のフォームが出てきません。ダイアログだけが表示されます。

これでは、多少見苦しいので、調べました。
Form1_Shown()、という関数がそれで、ここに書き込むと、フォームの表示後にダイアログが出るようになりました。

正確には、private void Form1_Shown(object sender, EventArgs e)、です。
フォームのプロパティで、Shownという項目をダブルクリックすると出現します。



200717
C#、関数、引数、参照渡し、値

関数について、少し勉強してみました。
ここまで、使わない訳にもいきませんので、使ってはいますが、全部、引数無しの、Void関数名()、です。

必要な変数は、試行錯誤で全体にスコープされる場所を見つけました。
classの下です。
ここに置いておくと、これ以下のどこからでも参照?(言葉については不明)できています。

ネットの記事では、C#にはグローバル変数はない、と書いてあります。
多分、classとかnamespaceとかを超えられないという意味だと思います。
そのような大掛かりなものは、私には作ろうにも作れません。

そこで、折角なので勉強してみました。
引数について、参照渡し、値渡し、配列は参照渡しになる、という事は、昔読んだ記憶があるC言語と同じです。

ただ、そこまで厳密な区別は出来ず、肝心な変数はどこからでも参照できた方がしっくりきます。
これは、グローバルな変数しかない言語から入ったものの欠点だと、やはりどこかの記事にありました。


200712
C++、デスクトップアプリ
C++をまた少し触ってみました。
簡単にフォームが作れないかと思っての事です。過去何度も挑戦して、失敗しています。
なんのことはない、プロジェクトの所でデスクトップアプリを選択すると、簡単にできます。
出来ると言っても、初期画面のままです。どこにコードを書き込むのかさえ分かりません。
分かったとしても、これまでに知識はほとんど役に立たないと思います。そんなコードが並んでいます。

とにかく、フォームでしょうかデスクトップ画面というのでしょうか、窓は、初期状態でビルドしさえすれば表示されます。



200712
VS、プロジェクトのバックアップ、再利用

C#でプロジェクトかソリューションか、とにかく今作っているコードを利用して別のプロジェクトを作りたい場合があります。
普通には、ファイルをコピーして、それを使えばいいはずです。
バックアップでも同じです。ちょっと作業が一段落して、一応ちゃんと動いている。これから先の作業でどうなるか分からないので、バックアップしておく。最悪、これからの作業が行き詰ったら、そのバックアップに戻ってやり直せばいい、はずです。

調べたら、VSの場合、これが通用しない様です。
何やら設定ファイルみたいなものがあって、絶対パスになっているのでしょうか、フォルダを変えてしまうと、うまくないみたいなのです。
試してみて、元も子もなくなるのが心配なので、この件は試していませんが。

フォルダごとのコピーもバックアップも通用しない様なのです。困ったものです。
200829追記
フォルダごとのバックアップは有効でした。
プロジェックトを作って、被害が少ないように、比較的早めに試してみました。
フォルダごとバックアップしていたものを、元のフォルダに、そのまま何も変えずに戻すと、普通に動きます。
ついでに、フォルダを変えてしまううとどうなるかも試しました。
動きます。起動に少し時間がかかったような気がしましたが、何事もなく動きました。



今回も、そのようなケースで、新しくプロジェクトから始めます。
作るのは、C#、Windows、デスクトップ、Windowsフォームアプリケーション、.netFramework、です。
(次回の為に、プロジェクトの選択項目をメモしておきます。)
予めフォルダを作っておいて、そこを指定します。プロジェクト名はフォルダ名にします。根拠は、その方が面倒がなさそうなので。
フォルダは、新規の際のプロジェクトの場所を決めるボックスでも指定できます。
これが間違いやすいのです。
例えば、G:\data\cs\map、というフォルダで作業したいのに、出来上がって調べてみると、G:\data\cs\map\mapとなっていた、という事が起きがちです。
なので、あらかじめフォルダを作っておいて、プロジェクト名にそこを指定する、と失敗はありません。



200710
関数、メソッド、一覧、移動、日本語
関数への移動方法で悩んでいました。
関数を呼び出している所からなら、F12で移動できることは最近分かりました。
元の呼び出し場所へ戻るのは、Ctrl+-です。

いつもHSPを引き合いに出しますが、HSPでは編集メニューに関数一覧があります。ここから実際の関数の場所に移動できます。

今日ようやく、同じような方法を見つけました。
ソリューションエクスプローラーのform1という項目の横の小さな右三角をクリックです。
ここに関数一覧+αがズラーッと出てきます。
似たような名前がいくつも出てきて迷いますが、よく見ると自分が作ったものもあります。
で、目的の関数名をクリックで、コードの場所へ移動します。
200818追記
これに気付くのに一か月と8日かかりました。
関数等への移動の方法です。エディタの右上に小さなボックスがあり、そこの小さな三角をクリックすると、上と同じような関数類のリストが出てきます。
関数と変数定義と他にも何やらあるようですが、とにかくジャンプテーブルになっています。
上の方法だと、リストを表示させるまでに幾つかクリックが必要ですが、こちらならワンクリックです。
それに、懸案だった、今どこにいるか、カーソルの位置も分かります。
ただ、先の方法だと、常時リストが見えているので、連続して移動する時には、まだ使えそうです。
もう一つ、右上のリストは、ソートされています。これでは多少使い辛いです。
この点、どこかに設定があるといいのですが、あったとしても探すのが大変です。
200818追記ここまで。

更に調べたら、C#でも関数名や変数に日本語が使えます。今日初めて気づきました。
変数は何度も使うので日本語は面倒ですけど、関数には使った方が便利です。
HSPでは、よく使う、というか、重要な関数や区切りの場所に日本語のラベルを使う様にしています。
すると、関数の一覧を出した時、探しやすくなります。
C#でもラベルが自由に使えるといいのですが。
いえ、使えるみたいです。
ただ、使いたいのは、例えば、ボタンのクリックの所です。

ファイル読込ボタン:
private void button1_Click(object sender, EventArgs e){}
このように、関数の宣言の前後に日本語のラベルが使えると、関数を探すのがとても楽になるはずです。
残念な事に、関数の内側ならラベルは使えますが、ラベルは一覧には出てきません。

それに、今いちなのが、これで現在の位置が分からない事です。
HSPのラベル一覧では、現在のカーソルの位置のラベルが反転して、自分が今どこにいるのかが分かります。
これは重宝します。


200709
VSのヘルプ

常々、Visual Studioのヘルプは貧弱だなと思っていました。
まあ、フリーの物にはよくあることだからと観念して、ネット検索に励んでいました。
今日、気付いた事が1件、プラス2件あります。

まず、ファイルなどのフルパスからファイル名だけを取り出す(メソッドというのか関数というのか)方法について、
System.IO.Path.GetFileName()は、ファイル名だけではなく、最下層のフォルダ名も取り出せる、という事です。
つまり、文字列の一番右にある\から先の部分を切り取ってくれます。とても便利です。

これを利用する状況は、フォルダの一覧を作る時です。この時の試行錯誤で、便利なヘルプの機能について気付きました。
まず、単語の上にカーソルを置いてF1でヘルプが出てきます。
これは、HSPにも同じF1でヘルプが出てきますので同じでした。
ただ、VSのヘルプは、読んでみても私にはよくわかりません。専門家向きなのでしょうかね。

フォルダの一覧を作るので、下の様に書いてみました。
string[] dirs = System.IO.Directory.GetDirectories(backdir,"*ks", SearchOption.TopDirectoryOnly);
ところが、例の赤い波線がSearchOptionの所に出て消えません。
しかし、その赤い波線の所にマウスカーソルを持っていくと、ヘルプみたいなプルダウンが出ます。
考えられる修正内容を表示してくれるのです。
その内容の中にSystem.IO.とか、using System.IO、とかいう項目が出てきます。
ああ、これだと気づきます。で、クリックすると補完されます。
using System.IOの方がスマートなのでしょうか。何故か私はこれを使っていません。

で、こうなります。
string[] dirs = System.IO.Directory.GetDirectories(backdir,"*ks", System.IO.SearchOption.TopDirectoryOnly);
波線が消えます。実行すると意図通りに動いてくれます。

もう一回、System.IO.Path.GetFileName()について、
フルパスから一番右側のファイル名だけ取り出すものですが、とても便利です。
ファイルやフォルダのリストを取ると、全部フルパスで帰ってきます。
必要なのはファイル名だけです。この時に使います。
HSPでは、これが無いので、関数など作ったりしていました。
strrepとかsplitとかこれに近いものはあります。それでも面倒です。
一番ありがたいのは、文字数などのカウントが必要ないことです。
0から始まるのか、1からカウントするのか悩む必要がありません。



200708
true、false、if (!a)
未だにif文の書き方がおぼろげです。

まあ、間違っても、その場で赤い波線になるので、何とか処理出来ていますが。
よくやるのがこれ、if (a = fales)、です。
2か所も間違っています。
==とfalseのスペルです。

これに気が付かないので、どうしても赤い波線が消えません。
やむを得ず、例文などからそのまま、if (a)とかif (!a)とか書き直して凌いでいます。
もちろん、!を付けるのが正しいのか、付けないのか分かりませんので、試行錯誤します。
それぞれ実行して、どちらか予定通りの行動になる方を採用する、という段取りです。

これを回避する為に、a=bの形式にしたいのですが、一方がtrueかfalseの場合、先のスペルミスがあります。
何しろ、いくつもの選択肢があります。
まず、引用符""が必要なのか、大文字なのか小文字なのか頭文字だけ大文字なのか、等、無限に試行錯誤が続きます。

長年=一つで済ませてきましたので、==に気付かないのはやむを得なかったと思います。
false、trueは、最近、こう書けばいいと気づきました。
if (a == false)、です。
ネットでは、ほぼ全部、if (!a)、と書いてあります。
if (a == false)、と書いてもらうと分かり易いのに、なぜ省略するのでしょうかね。

今日、気付いた事が2点、
falseは、フェイルスではなく、フォールスと発音する事、
VSのエディタでは、正しくfalseとタイプすると、文字が青色に変わる、という事です。
これで、今後は大丈夫でしょう。多分。


200707
C#、テキストボックスへの表示にかかる時間

200705付けでメモした事で、全く同じ作業なのですが、2度目の方が作業時間がかかってしまう、という現象がありました。
かなり大きなテキストファイルの更新作業です。670KB程度、行数は30000行ほどのファイルです。
このファイルの適当な位置に、新しく10数行の文字列を挿入します。挿入位置は末尾や先頭ではありません。途中です。

フォームで画面を作ります。テキストボックスを数個、ボタンを数個です。
テキストボックスのmaxlengthは0にしています。
こうすると、表示サイズの制限がなくなるとの事です。

起動時に、目的のファイルを読み込んで、表示までしておきます。
ボタンにコードを埋め込んで、実際の作業、文字列の挿入です。
具体的には、以下の作業になります。
まず、念の為、ファイルはもう一回読み込み、表示します。
読み込んだテキストに、文字列を挿入して、再度表示、保存です。
念のため、上書きしないように、保存する時のファイル名は変えています。
ですので、何度でもボタンを押して、同じ作業が出来ます。

いつも作業時間を計っています。
HSPでは3秒かかる作業で、C#で代替えして、もう少し早く出来ないかという事が動機でした。
結果、320ミリ秒程度で終わります。

ただ、ここで問題があって、ボタンをもう一回押して、同じ事を再実行させると600ミリ秒かかってしまいます。
これは何だ、となって、時間の計測を細かく分割しました。
ファイル読込に何ミリ秒、表示に何ミリ秒、という感じです。

これで、簡単に原因が分かりました。
一回目の実行では、読み込みに要する時間は10ミリ秒程度でした。これが2回目以降は270ミリ秒程かかっています。

この結果は、こう考えるよりありません。
C#では、テキストボックスに再表示する際は、表示してある内容と同じテキストだったら、表示を省略する。
どうしているのでしょうかね。チェックサムみたいな物があるのでしょうか。
コードを読み切っているのでしょうか。このコードなら再表示の必要なし、という判断をしているとは思えませんが。
だとすると、向こうが偉いという事になります。
まさか、文字数とかファイル名だけで判定しているはずもないでしょうし。

更に、もう一つ、大事なことに気付きました。
C#で、ファイルが大きい時など、テキストボックスへの表示をさせなければ、圧倒的に速くなる。
今回のケースでは、表示を省略すると、50ミリ秒で終わることになります。
比較の為に挙げた、HSPでの3秒という時間には、表示時間が含まれていませんでした。
つまり、C#が圧倒的に速い、ということです。

さらに、ずーっと下のメモで、色々な比較をしています。
この時、表示に時間がかかるという事は考慮していたのか気になります。
やはり、正確な比較をするなら、C#は、C言語といい勝負をするのかもしれません。



200705
C#、文字列の分割と結合
テキストファイルの途中に文字列を挿入する作業に苦労しています。
文字列の末尾ではなく、途中に小さな文字列を追加しようとしているのですが、なかなかうまく行きません。
HSPだと、noteadd 追加するブロック,追加する行番号,0、という一行で済む作業ですけど。

C#で、文字列の途中に文字列を挿入する手段を探しましたが、簡単な方法が分かりません。
簡単ではないというような記事もあります。

分かったのは、
元の文字列を、行単位に分割する。
追加する位置を境にして、前後のブロックに分けた文字列を作る。
前のブロックの末尾に今回挿入するブロックを追加する。
その後ろに、先に分けておいた後半部分のブロックを追加する。
という手段です。これ以外にはなさそうです。

上の方法で試しますが、すんなりとは行きません。
分割する時、前半のブロックの末尾が改行だけの行になっていて、これを連結すると、その改行だけの行が消えてしまいます。
一行短く仕上がってしまいます。
やむを得ないので、連結する時、改行を一行追加して辻褄を合わせました。

この作業、現在、HSPでは3秒強かかります。
サイトマップファイルに新しいページを登録する作業です。
ファイルは30000行660KBあります。
一応、同じ種類のページはまとめておきたいものですから、末尾に追加とはいきません。
今のところ、出来上がったテキストを保存する作業を入れていませんが、C#だと、300ミリ秒ほどで終わります。
C#に変える効果がありそうです。

どうやら正解が分かりました。
途中で配列にしたものを文字列に戻して、その文字列同士を連結したのがまずい様です。

完成後の行数、文字列を挿入した作業後の行数は分かります。
最初に、その長さの配列を宣言しておきます。
元の文字列も挿入する文字列も配列に変換します。
完成後の長さ分確保していた配列に、前半部分の配列、挿入する部分の配列、後半部分の配列を、位置を指定してコピーします。
最後に配列を文字列に変換します。
これで、改行だけの行も残ります。

完成したとして、ファイルの読み込み、連結、ファイルの書き込み、までの時間は330ミリ秒ほどです。
HSPでは3秒かかっていました。

ただ、連続して実行すると、2度目には600ミリ秒かかります。原因不明です。
原因が分かりました。テキストボックスへの表示時間です。これについては、改めて、項を変えてメモします。




200702
tt.Replace("\\", "/");

とあるフォルダのファイルリストを取ると、次のような文字列が出てきます。
G:/main-data/code/VS2019/CSDATA/temp20\200625mg.htm
\を/に変えたいのですが、うまく行きません。
tt.Replace("\\", "/");
が言う事を聞きません。

200701
C#、降順のソート
listBoxを使ってみる事にしました。
フォルダにあるファイルの一覧を作って、リストボックスに表示させます。

まず、ListBoxではなく、listBoxですね。まずここでエラーと言いますか、例の赤い波線です。
どうやら規定では、昇順にソートされる様です。
私の希望では降順でソートして表示させたいのです。
基本的に、ファイル名に日付を付けていますので、一番新しいファイルを一番上に置きたいのです。

全くの付け焼刃です。例によって、ネットを探しました。
これが面倒でした。様々なソートの方法が有るようですが、どれも分かりません。
構文が長くて、意味不明です。2行に渡る物もあります。
C#のバージョンによっても違うのかも知れません。
やはり系統立てて勉強していない事へのしわ寄せでしょうね。
目的は、単純に文字列の配列を昇順に並び換えたいだけです。
HSPだと、簡単に、sortnote files,1、とするだけなのですが。

ようやく、見つけました。
Array.Reverse(files);、で目的達成でした。



200623
VSエディタの起動時間

VSのエディタの起動にかかる時間が気になってきました。
C#で、デスクトップにsinファイルのアイコンを作って、そのアイコンをダブルクリックしてVSのエディタを起動しています。
これが、開き終わるまでの時間です。

編集しているテキストは、Form1.csだけです。これが30KBで、あと、Program.csというファイルがあります。1KBです。
csファイルはこれだけです。
そこで、時計を横目で見ての計測ですので、正確さはありませんが、ダイアログで、準備が完了しました、と出るまでに8秒ほど、
そのダイアログで、バックグラウンドで云々とあって、ダイアログが消えるまでに更に8秒ほどかかります。

エディタに慣れてくると、この辺りも気になってきます。


200620
C#、byte[]

昨日発見したbyte型ですが、ある程度の文字列を扱うので、大きめに確保しておきました。
byte[] aa = new byte[1000000];
そして、文字のアスキーコードを順番に入れていき、終わった所で終端の0を入れます。
その後で、Shift_JISの文字列に変換します。
string tt = System.Text.Encoding.GetEncoding(932).GetString(aa);

当方の目論見通りです。ちゃんと表示され、保存も出来ます。
ですが、よくよく調べてみると、ファイルの大きさが、最初に確保した1000000バイトのままです。
それこそVSCodeで強引にhexダンプしてみると、文章が終わった所から以降には全部、0が並んでいます。
Shift_JISでは考えられない世界です。これがUnicodeなのでしょうか。私の無知なのでしょうか。

やむを得ず、完成後のバイト数をしっかり計算して、必要十分な領域を確保して、回避しました。
それにしても、byte型に関しては、もう少し勉強が必要かもしれません。
一番の原因は付け焼刃でやっている事なのですけど。


200619
C#、char、byte、Shift_JIS
C#のcharは16ビットです。8ビットはbyteという型があります。
これは許せません。これに気付くまでに3日かかりました。

普通は一文字ずつメモリというか配列に収めるならcharでしょう。
そのつもりでやっていったら、どうしても型変換のところで止まります。
char m[0] = 65;
char m[1] = 66;
char m[2] = 0;

これをstrngに変換しようとしても出来ません。
強引に変換しても、結果は文字化けしています。
VSのエディタの警告やブレークポイントでのデータを見ると、UTF-8になるよ、みたいな表示です。
理解はできません。

正解は、
byte m[0] = 65;
byte m[1] = 66;
byte m[2] = 0;
です。
これで期待通りのShift_JISの文字列”AB”を作れます。
(何故か、末尾の0?='\0'は必要なし。)

このところ、文字列の連結で試行錯誤です。
言語も、C、C#、HSPを右往左往しています。
C#の速度がどうにも遅いので、調べたら、StringBuilderクラス、というものがありました。
これを使うと、Cに近い速度が出ます。
よく見たら、Cではcharの配列を使っていました。
文字列を連結するのではなく、インデックスを指定して直接書き込んでいます。
そこで、HSPに戻って、pokeを使って書き込みするようにしたら、こちらもC#並みとはいきませんが、かなりな速度になりました。
そこで、戻ってC#です。
C#でも配列に書き込んだら、訳の分からないStringBuilderクラスなど使わなくてもいいのではないかと考えました。
そこで、当然、私の知識ではchar[]を使えばいい、はずです。
この間、3日悩みました。
正しくは、byte[]でした。

文例などに、byte型とかあるので、何だろうかとは思っていました。




200619
C#、型

C#の変数の型について、大して違わないだろうと、これまで何も調べずに使っていました。
と言いますか、どこに書いてあるか分かりませんでした。
最近、型変換がうまく行かないので、探していて、ようやく、分かり易いページを見つけました。

思っていたものと違いますね。
charは16ビットです。Unicodeのせいでしょうかね。
byteという型があって、これが8ビットです。1バイトですね。
intは32ビット、とあります。

Cでは、
charが8ビット
intが通常32ビット、
shortが16ビットとあります。ただ、Cはコンパイラ次第のようです。

念のため、VSのCではどうなのか、調べたのですが、見つけられません。
いえ、検索すると、intが4バイトというページがあります。32ビットですね。
ただ、残念なことに、これがどの言語の規定なのかが分かりません。
考えると、OSの32ビットと64ビット違いによる関連はないのでしょうかね。少し心配です。

HSPでは、
変数の宣言がありませんので調べるのに苦労します。
intは型変換です。小数点を切り捨てるのに使います。多分。
基本が整数なので、普通に割り算すると整数が帰ります。多分。
10進数の範囲は32ビットと書いてあります。これが制限なのでしょう。


200617
VS、上書き保存
Cの編集中、VSのエディタで上書き保存のアイコンをクリックするとダイアログが開いて、出力-デバッグ.txtというファイルを保存しようとする。
どうやら、コンソール出力の内容を保存するみたい、リダイレクトだったか、既定かな。便利と言えば便利。
コンソールを閉じていても出てくる時がある。
何か知らない構造があるのだろう。
200617
C、open
ファイル読込の際、rでもrbでも同じ結果になる。読込方次第か。
fp = fopen(fpath, "r");
200617
C#、byte[] bytes
byte[] bytes = SiftJISenc.GetBytes()について調べてみました。

76C2CC・・というテキストを読み込ませ、
変数に代入し、直下にブレークポイントを置くと、実際の数値をみられます。

データは以下の通りです。
bytes[0]=55= "7"
bytes[1]=54= "6"
bytes[2]=67= "C"
bytes[3]=50= "2"

つまり、アスキーコードが入るという事です。

ついでに、文字に戻すには、
char mo = (char)bytes[0];
char mo2 = (char)bytes[2];
UTF-16で戻ってしまう。困った。(これは間違い、勉強不足の頃の話)

200617
C#、ブレークポイント

Cではどこにでもブレークポイントが置けます。
C#ではコードのある行でないと置けません。
これが分からずに、再起動を繰り返しました。

200616
スクリプト、コード

エディタで作るプログラムのソースファイルの中身をなんというか、迷っていました。
今後は、HSPはスクリプト、その他の言語はコードと表現する事で統一します。
HSPのエディタは、HSPスクリプトエディタとなっています。
VSの方はMicrosoftVisualStudioCommunity2019となっていて、ここでは判断できませんが、ヘルプの中にはコードと書いてあります。

200615
C、strcat
strcat(aa,bb);
この前に、aa[0]='0';が無いとエラーになる。

200615
VSCode、HEX表示

VCCodeに16進表示の拡張機能をインストールしました。
下のプログラムの確認の為に使います。
この操作方法に毎回迷います。どうしたら16進表示になるのかです。

あちこちメニューをめぐって何とかなるのですが、今回間違いのない方法を見つけました。多分。
ファイルを読み込んで、ファイル名が表示されている所を右クリック、
そのプルダウンメニューの最下部にShow Hexdumpと出ています。

Shift_JISファイルが、いつも、文字化けしています。UTF-8で読み込まれています。
下のエンコーディングの所から、読み直すことが出来ますが面倒です。
ウーザー設定に初期設定がありました。

200611
C#、StringBuilderクラス、言語別実行速度比較、poke
C#で満足できるだけの速度を出せました。
ネットは、早い、という記事を見ます。ここまで信じられない話でした。
恥ずかしながら、ここまでのバタバタをまとめておきます。

作業は、テキストファイルの16進表示です。100KBのテキストファイルを変換してみました。
(実際には、その他、多少の副次的な作業もするのですが、中心の作業は16進変換です。)

という事で、forにしろrepeatにしろ、100000回のループが必要です。
最初にHSPで作ったものは、100KBのファイルを処理するのに11分かかりました。
いつものやり方で、冗長なスクリプトで作るとこうなります。
これは、スクリプトを見直して、39秒までには縮めました、(下の一覧表の*列の記号で、A、以下同じ)
しかし、この速度では役には立ちません。

そこで、コンパイラで、となります。
VisualStudioCommunity2019をインストールしました。
ついでに、VSCodeも落としました。
(後で気づいたのですが、このVSや、VSCodeには、16進表示の機能が付いていました。)

色々の言語を試しましたが、総合的な問題でC#に行き着きます。
当初、C#では期待通りの速度は出ませんでした。HSPより多少いいか、という程度でした。
そこで、調べていたら、文字列の連結には、StringBuilderクラスというものがあって、これが早いそうです。
以下、このStringBuilderクラスに到着するまでの経過です。

最初に、VBで試しました。
しかしながら、付け焼き刃の知識では何ともなりません。
VSの文字コードは、基本Unicodeだそうです。
ここまで扱ってきた文字コードはShift_JISだけでした。
Shift_JISのファイルを読み込んで、Unicodeで処理されるので、多分、変換してShift_JISのコードを出力する、となると思いますが、この変換がうまく行きません。
(この時点では、こんな風に考えていましたが、C#で何とか出来た現在、C#もVBもほとんど変わらないみたいですので、今なら何とかなるのかも知れません。Shift_JISで読み込んで、そのまま処理して、出力もShift_JISを指定して出力する。でしょう。)

対象のテキストファイルを、最初からメモ帳などでUnicodeに変換して処理するといいじゃないか、となります。
長年の事で、これが許せません。BOMとか4バイト一文字とかに抵抗があるのです。
やはり、文字は1バイトで処理できないといけません。(根拠なし。面倒だというだけです。)

そこで、先のVSでCに挑戦しました。
C言語については、昔、ほんの少しですが経験がありましたので。
便利な世の中です。ネットを探すと、例文が沢山出てきます。
それを継ぎはぎすると何とかなるものです。以下同じ。
それに、VBで悩んだUnicodeが出てきません。Shift_JISをShift_JISのまま読込め、そのまま処理出来ました。
VCでは、コードのファイルもShift_JISで保存されています。

Cで試すと、100KBの作業でも78ミリ秒で終わります(B)。
ただ、残念な事に、コンソールモードです。
Cではデスクトップの画面が作れません。どんなに探しても、フォームエディタを見つけられませんでした。

これには、便法ですが略式の解決方法があります。
画面処理はHSPで済ませて、実際の作業は、execでCの実行ファイルを起動します。H
この方法でやると、100KBの処理を700ミリ秒で終わります。(C)
待たされたと感じない時間です。
これで、実用上は問題ないのですが、ちょっと見苦しい気がします。

そこで、C++です。
確かに、ネットの情報を駆使してVSのメニューを掘り下げると、フォームエディタは出てきます。
ただ、ビルドしてもコンソール画面しか出てきません。
コードの書き方も全く分かりません。文法がCとはかけ離れています。
ネットにはCと大して変わらないとありますが、とてもそのようには思えません。

やむを得ず、C#を試しました。
C#だとフォームエディタは簡単に出現し、編集もできました。ボタンやテキストボックスなど簡単に取り付けられます。
マウスのドラッグでボタンなどの配置場所を指定できます。
HSPだと配置場所はスクリプトに座標の数字を書き込んで行きますので、C#の方が簡単です。
コードの配置場所もすぐ見つかりました。
private void button1_Click(object sender, EventArgs e)
の下に書けばいいのです。
ここに、ネットからの例文をコピーして多少変数をいじるだけで動きます。

で、試した結果、100KBの処理に16秒かかりました。ミリ秒ではありません。(D)(E)
こんなものかと思いました。コンパイラではありません。C#は中間言語なのです。
HSPよりはいいけど、秒の単位が必要なら、使うのに躊躇します。
そこで、順番としてはC++に向かったのですが、上のメモの通りです。
この間、他の言語も調べました。
GoとかFreeBASICとかです。
いずれも、デスクトップ画面を作れるかがよく分かりませんでした。

やむを得ず、C#に戻りました。
ここでようやく、StringBuilderクラスを知りました。
これを使うと、驚きです、同じ処理が151ミリ秒で終わります。(F)(G)
C並みとは言えないにしろ、これに近い、抵抗のない数字です。
それに、C#だけで画面から処理まで完結できます。

これで、ネットでの評価に近い数字になりました。
C++の迷路をさまよう必要はなく、HSPからCの実行ファイルを呼び出す必要もありません。
手探り状態ですけど、C#で何とかなりそうです。

一段落した所で、各言語のコードやスクリプトを比較していたら、幾つか気付いたことがあります。

HSPでは、文字列の足し算(連結)をしていました。
ここまでの経過で、文字列の連結には時間がかかる事を知りました。
HSPにも文字列を直接操作する手段があります。pokeです。
元々、変換元からの取り出しにはpeekを使っていました。
それでも、pokeを使わなかったのは、peekはメモリからの読み出しで、pokeはメモリへの書き込みです。
これに、多少の躊躇がありました。
それに、多少は早くなったとしても、そんなには違わないだろうと思っていました。
しかし、C#での事で、試してみる価値がありそうな気がしてきました。

HSPのスクリプトをpokeで作り直してみました。
爆速です。
39秒かけていた100KBのテキストの変換が0.516秒で終わりました。ミリ秒の単位で終わります。(H)
こうなると、HSPでの作業に抵抗はありません。
C、C#での騒ぎが何だったのかという事にもなります。

Cでは最初からポインタと配列で作業しています。つまり、メモリへ直接書き込んでいました。(B)
偶然、参考にした文例がよかったのでしょう。
あ、恥ずかしながら、配列とポインタが同じものだ、ぐらいは知っていました。

Cにも文字列の連結があります。一応。これも試しました。
連結だと、Cでも遅くなります。100KBの変換で2.8秒かかりました。(I)(J)


処理にかかる時間に関して一覧表を作りました。
言語 20KBのテキストでの作業   100KBのテキストでの作業
処理時間(秒) Cを1とした倍率   処理時間(秒) Cを1とした倍率
A HSP 1.703 106.4   39.860 511.0
B C(コンソール) 0.016 1.0   0.078 1.0
C HSP+C 0.653 40.8   0.703 9.0
D C#(debug) 0.393 24.6   15.683 201.1
E C#(releace) 0.319 19.9   8.092 103.7
F C#(sb:debug) 0.133 8.3   0.155 2.0
G C#(sb:releace) 0.135 8.4   0.151 1.9
H HSP(poke) 0.329 20.6   0.516 6.6
I C(strcat) 0.265 16.6   5.563 71.3
J C(sprintf) 0.140 8.8   2.813 36.1


以下は作業中のメモです。
System.Diagnostics.Stopwatch()を使って、時間を表示させました。
(HSPでは、GetTickCount、C#では、GetTickCount())

C#の作業時間、(F)
20KBで、(0, 2, 0, 123, 8, 合計133ミリ秒)
100KBで、(1, 12, 0, 132, 10, 合計155ミリ秒)
という結果です。いずれもデバッグモードです、驚きました。

releaceモードだと、(G)
20KBで、(0, 2, 0, 133、合計135ミリ秒)
100KBで、(1, 10, 0, 140、合計151ミリ秒)

合計以外のコンマ付きの数字は、各セクション毎の所要時間です。
テキストファイル読込、16進数変換、16進数整形、mesboxへの表示、16進数ファイルの保存、の順番で表示しています。
コンマ付き数字が4個の結果は、mesboxへの表示と16進数ファイルの保存の合計です。

こうしてみると、時間のかかっているのは、変換結果のボックス表示の時間です。
他の作業には時間がかかっていません。
コードの間違いか、何やら、タイムラグみたいなものがあるのかも知れません。
あるいは、並行処理みたいなもので、実際の処理は他所でやっているとか。
あるいは、グラボの性能が悪いだけ、かも知れません。


簡単にそれぞれのスクリプトとコードを書き出しました。
肝心の所だけです。本来は、多少の修飾があります。

HSP、単に文字列の結合、(A)
repeat len
  one=peek(sjistext,cnt)
  hextext=hextext+strf("%02x",one)
loop
実行結果は、20KBで、1.703秒、100KBで、39.860秒


C、コンソールモード、配列に直接書き込み、(B)
for (i = 0; i < size; i++) {
  one = buf0[i]
  mae = one / 16;
  sprintf(mozi, "%X", mae);
  buf[ctr] = *mozi;
  ctr = ctr + 1;
  usiro = one % 16;
  sprintf(mozi, "%X", usiro);
  buf[ctr] = *mozi;
  ctr = ctr + 1;
}
buf[ctr] = '\0';
結果、20KBで、16ミリ秒、100KBで、78ミリ秒、(デバッグモードのデバッグなし開始)


C#、単に文字列の追加、(D)、(E)
for (int ctr=0;ctr<len;ctr++)
{
  hextext += bytes[ctr].ToString("X2");
}


C# StringBuilderクラスを使って文字列を追加、(F)(G)
System.Text.StringBuilder hextext = new System.Text.StringBuilder();
for (int ctr = 0; ctr < len; ctr++)
{
  hextext.Append(bytes[ctr].ToString("X2"));
}
string hextext0 = hextext.ToString();
結果は、20KBで、135ミリ秒、100KBで、151ミリ秒



HSP、pokeで書き込み、(H)
repeat len
  one=peek(jistext,cnt)
  mae=one/16
  asc=strf("%X",mae)
  poke hextext,ctr,asc
  ctr=ctr+1
  usiro=one\16
  asc=strf("%X",usiro)
  poke hextext,ctr,asc
  ctr=ctr+1
loop
poke hextext,ctr,0
実行結果は、20KBで、329ミリ秒、100KBで、516ミリ秒


C、コンソールモード、連結方式でも試してみました。(I)
strcatで連結していきます。
for (i = 0; i < size; i++) {
  mae = buf0[i] / 16;
  sprintf(mozi, "%X", mae);
  strcat(buf, mozi);
  ctr++;
  usiro = hitomozi % 16;
  sprintf(mozi, "%X", usiro);
  strcat(buf, mozi);
  ctr++;
}
buf[ctr] = '\0';
結果(H)、20KBが、265ミリ秒、100KBで 5563ミリ秒。(デバッグモードのデバッグなし開始)


C、更に、sprintfを連結して二文字ずつ作業すると、(J)
for (i = 0; i < size; i++) {
  mae = buf0[i] / 16;
  ctr++;
  usiro = buf0[i] % 16;
  sprintf(mozi, "%X%X", mae, usiro);
  strcat(buf, mozi);
  ctr++;
}
buf[ctr] = '\0';
結果、20KBで、140ミリ秒、100KBで 2813ミリ秒(デバッグモードのデバッグなし開始)





200609
C++のプロジェクト、フォーム

上に新しいメモあり、

C#の速度が、HSPに比べたら早いけど、驚くほどの速さではない、Cに比べたらかなり遅い、という状況でした。
そこで、C++でフォームアプリに挑戦です。
何しろ、プロジェクトの作り方から分かりません。フォームのデザイナが出てこないのです。
ネット参照でようやくたどり着きましたのでメモしておきます。

新しいプロジェクトの作成
上の窓で、C++、Windows、コンソール、を選んでおく。
CLR空のプロジェクト(.NET Framework)を選ぶとビルドが通らない。。
CLRコンソールアプリ(.NET Framework)を選ぶとビルドできる。
次へ
プロジェクト名とフォルダを適当に指定する。
作成
エディタのプロジェクトメニューで、新しい項目の追加、
UI、Windowsフォーム、を選んで、(UIがないのは今までの選択が間違っている)
追加
データが失われる可能性云々のエラーが出る。この場合は、
ファイルメニューで、ソリューションを一旦閉じる
ソリューションの一覧が出るので、今作ったソリューションを開く

何とか、フォームを使う所まで到着して、ボタンをダブルクリックでコードを書き込む場所までは分かりました。
しかし、分かりません。構文が他の言語とはあまりに違いすぎます。
ここで中断(というより放棄)して、DLLを勉強してみます。

そのボタンのコードですが、
private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e)
というものがダブルクリックで生成されます。
ダブルクリック以外に冷静な方法がありそうなものですが、分かりません。

どこか間違っている様です。ビルドしてもフォームが出てきません。main()が?

C#では、同じ部分がこうなっています。
private void button1_Click(object sender, EventArgs e)
この程度だと、我慢して見られます。

どうにもこうにもC++が分かりません。
そこで、C#に戻って、調べました。
文字列の連結に使うStringBuilderクラスというものに気付きました。
これを使うと、C並みとはいきませんが、Cと同じ桁で実行できます。
C#に戻ります。

200609
C#、実行速度
この項、上に、新しいメモあり。

ネットではC#の実行速度は、コンパイラ並ではないにしろ、コンパイラと遜色ないような記事が多いです。
それならと、目下勉強中です。
ある程度、作り上げて、実際に試してみました。結果、HSPよりも少し早い程度です。
いえ、まだ途中経過で、改良の余地がある状況ですし、完全に同じ作業にはなっていないはずです。
とりあえずの結果です。

何しろ、ほとんど文法が分かっていないのに、ネットの文例をつなぎ合わせていくと、動いてしまいます。
そういう作りですので、まだまだ不十分だと思います。

その上で、
20KBのテキストファイルの処理がHSPでは1.7秒でした。

これをC#では、約400ミリ秒、です。
C#の計測結果、debugモードで、(10, 248, 248, 393ミリ秒)、12, 261, 0, 142(合計415ミリ秒)
releaceモードでビルドした実行ファイルで、(11, 183, 183, 319ミリ秒)

やはり、C#でもテキストボックス等へ大量のテキストを表示させると、時間がかかっています。
これはHSPでも同様で、どちらも表示は部分的に省略するようにしています。
どちらも、条件は変わらないと思います。

100KBのテキストで、HSPで40秒でした。
C#の計測結果は、debugモードで:(32, 15541, 15542, 15683ミリ秒)、36, 16006, 0, 155(合計16197ミリ秒)
同、releaceモードでビルドした実行ファイルで:(12, 7953, 7954, 8092ミリ秒)
C#では、8秒という事になります。

ここで、初めてreleace版で生成した実行ファイルで試してみました。
かなり早くなっています。こちらが本当の速さという事でしょう。
Cでも双方試しましたが、差は分かりませんでした。Cでは差が出るほどの作業ではなかったという事かも知れません。

やはり、テキスト表示は部分的に省略しています。
なお、C#で、テキストを省略せずに表示させると、29秒かかります。つまり、ボックスへの表示に13秒かかっています。
上二つ、Cも計測してあります。

まとめると、(前半の作業時間)
言語 20KBのテキストでの作業   100KBのテキストでの作業
処理時間(秒) HSPを1として   処理時間(秒) HSPを1として
HSP 1.703 1.0   39.860 1.0
C#(debug) 0.393 1/4.3   15.683 1/2.5
C#(releace) 0.319 1/5.3   8.092 1/4.9
Cのみ 0.016 1/106   0.078 1/511

HSPと比べればかなり成績が上がりましたが、8秒では心理的にも抵抗があります。
もう少し対策を考えます。

ネットで調べていたら、StringBuilderクラスというものがあって、文字列の連結に強い、そうです。
試しました。
20KBで140ミリ秒、(0, 3, 0, 137、合計140ミリ秒)
100KBで175ミリ秒、(12, 14, 0, 149、合計175ミリ秒)
という結果です。いずれもデバッグモードです、驚きです。
これで、ネットでの評価に近い数字になりました。C++のジャングルをさまよう必要はなく、C#に戻れそうです。


ループについて
この間の作業で、C#でも単純で数の多いループの最中に、帰ってこない状態になることがありました。
フォームの右肩のXのボタンが赤く表示されます。マウスカーソルが行っている状態です。
数秒ですので、何も試していませんが、ちょっとした暴走状態だと思います。
終了だけは出来ます、という意味かも知れません。
HSPではwaitを入れない単純なループでよく経験します。



漢字モード
VSのエディタで漢字がONにならない場合があります。
ビルドしてエラーも結構出ていますので、何やら暴走させているのかもしれません。
エラーが出ている間、デバッグ実行中にはONに出来ないようです。
コードを書き換えられない様にしてあるのかもしれません。



200607
VS、灰色の点々

自己書き換え、とでもいうのかな
VSのエディタに灰色の点々があります。よくできていると思います。
マウスを近づけるとメッセージが出てきます。
int宣言の所で、不必要な代入、とありました。
エラーにはならないけど無駄だという程度なのでしょう。

str.Replace("A", "B")

文字列の一部を入れ換えるのに
str.Replace("A", "B")
というものがあります。
これをそのまま信用して、
str.Replace("A", "B");
と書きます。
いくら待っても書き換わりません。

HSPに同様のコマンド、strrepがあります。
strrep strr,"A","B"、とすると、strrが書き換わります。

C#では、
strr=str.Replace("A", "B");
が正解の様です。

文字コード指定、文字コードの確認
System.Text.Encoding enc = System.Text.Encoding.GetEncoding("shift_jis");
System.IO.File.WriteAllText(filePath, htext, enc);

私が扱うテキストファイルの形式は全部Shift_JISなので、苦労しています。
VSではUnicodeが標準みたいですので。
上の構文でファイルのエンコードを指定できるみたいです。
最初に指定しておくと、いい様です。
と言いますのも、ファイル読込の時に指定して、再度書き込みの時に指定するとエラーになります。
例の赤線、インテリセンスが出て、既に定義されているとなります。
コンパイルは通るのかもしれませんが。

さて、問題は実際にShift_JISで保存されているのかが心配です。
構文の意味がよくわからずに使っていますので。
最近は、いい時代になりました。
ネットで探せば、大抵の例文が出ています。
例え初めてのC#でも、面倒な作業でなければ、なんとかなっています。
ですが、上のような心配もします。

そこで、解決策に気付きました。
半角だけのテキストの場合に、文字のエンコードを確認する方法です。
メモ帳ではUTF-8と表示されます。TeraPadでは、Shift_JISと表示されています。
プロパティなどで、バイト数を見ます。
同じもので、エンコードがはっきりしているファイルが必要です。
私の場合は、同じものを、HSPで作っていますので、Shift_JISとはっきりしているものがあります。
それと同じバイト数ならShift_JIS、少し大きいならUTF-8となります。

上のメモは、BOM無しUTF-8だとダメみたいです。
しかし、VSで出力されているものはBOM有りでした。

検索と置換、インテリセンス
System.Text.Encoding enc = System.Text.Encoding.GetEncoding("shift_jis");
System.IO.File.WriteAllText(filePath, htext, enc);

上のコードのencをShiftJISencに置換したいと考えました。
ネットを見ていたら、同じような文例を見つけ、こちらの方が分かり易いなと思った次第です。
それに、多分、この単語は適当に変えていい部分だと気が付きました。

で、エディタの編集メニューにある検索と置換から実行しようとしました。
すると、encの部分は良いのですが、どうやら.Encoding.GetEncodingにあるEncの部分も置換対象に含まれている様子です。

そこで、いちいちスキップする方法はありますが、手間は変わりません、手書きで変更していくことにしました。
手書きと言っても最初にShiftJISencをコピーしておいて、対象のencを探してペーストしていきます。

ここで、ありがたい機能に気付きました。
よく出てくるインテリセンスの赤い点線です。これがとても役に立ちます。
最初に、定義の?最初の行の、encを書き換えると、残りのencが全部赤い点線になっています。
先ほど度違って、今度は変更が必要な部分だけです。
これを順番にペーストしていくだけでした。



200605
C#、ツールボックス
フォームを作るのに、C#が簡単という記事を見て、ちょっと始めてみました。
VSにC#も全部入っています。多分。
見よう見まねで作っていきます。
ネットからの切り貼りで何とかなるというのが、便利というか恐ろしいというか。

確かにフォームデザインが簡単にできます。できました。
それでもやはり試行錯誤です。
失敗した時、意図通り出来上がらない時、フォルダーごと削処して、プロジェクトの作成からやり直しです。
いえ、どこが間違っているのか分かりませんし、修正なんかできるはずもありませんので。

何回かやり直しているうち、ツールボックスからボタンbuttonという項目がなくなりました。
新しいプロジェクトを作る際、.NETCoreと.NETFrameworkを行き来している時でした。
フォームにボタンが貼り付けられません。
困って、色々メニューを探したら、それらしきものがありました。ツールボックスのリセット、という項目です。
ツールボックスの上での右クリックメニューです。
これで復活しました。

長い文章を表示するボックスをつくるのに、TextBoxだと一行しか表示できそうにありません。
試してみると、よさそうな物に、RichTextBoxがありました。
これだと、簡単に、縦長のボックスが作れます。
しかし、よくよく調べると、TextBoxでもよかった様です。オプションでMultlineをセットすると縦に拡張できました。
今のところ、どちらが正解なのかは分かりません。

TextBoxにも最大文字数があるようです。32KBみたいです。
ただ、こちらはプロパティで簡単に変更できるとの事です。

さて、迷いごとを一つ、
System.IO.File.Exists();、
という構文と、

using System.IO;
.IO.File.Exists();
という、どうやら二つが分離されている構文があります。

どうやらusingがdefineみたいなものの様で、以下省略できるという意味の様です。
迷いますね、統一してもらいたい所です。


200529
文字列の比較

Cで文字列の比較で躓きました。
if (argv[1] == "ag")です。全く意図通り動いてくれません。

試しに、
printf("1番目の引数は:%s %d\n",argv[1],strlen(argv[1]));とすると、
ちゃんと
1番目の引数は:ag 2、とでます

正解は、Cでは文字列の比較は、==、では意味がなく、
if (strcmp(argv[1], "ag") == 0)
だそうです。

思い起こせば、HSPでも同じような事情があります。ただHSPでは=までは通じます。
大小の比較はできません。



200528
CTRL+A

各種編集作業の時便利なキーがあります。
Ctrl+C、Ctrl+V、Ctrl+X、Ctrl+A、です。
コピー関係のショートカットです。
特にCtrl+Aは重宝しています。全て選択、ですね。

私は、HSPの作業中に途中の経過をクリップボードに転送しておきます。
メモ帳などに貼り付けるのです。
作業後にそれを見て、意図通り動いているか調べます。

この時、前回の経過が貼り付けてあるメモ帳の表示を入れ換えるのに、Ctrl+A、Ctrl+Vで済みます。
ただ、最近、これらのショートカットを多用していると、効かなくなることがあります。
コピーもペーストも出来なくなります。

原因不明です。特に、HSPのエディタ上で顕著です。HSPを再起動すると回復します。
最近、Cを始めたので、何か悪影響が出ているのかもしれません。
そのものずばりで、clipsetを多用している事が原因かもしれません。


200524
VSのエディタ、赤い波線、インテリセンス
VSのエディタでCの作業中、全く関係ないファイルから数行のテキストををコピーして持って来ました。
すると、赤い波線が出て来ました。理由はよくわかりませんが、エラーの様です。
赤い波線は、例えば、行末にセミコロン;、を付け忘れた時に出てきます。心穏やかではありません。
どうやら、この波線をインテリセンス、というみたいです。やはりエラーです。

しかしながら、コピーしたものは日本語のテキストで、貼り付け(ぺースト)した場所は、/**/で囲んだ注釈行の中なのです。
構文の間違いではありません。
200526追記
この件、プログラムをVer16.6.0へアップデートする事で解決しました。した様に見えます。
以下、無意味なドタバタの記録です。200609再発しました。
まず、VSで悩まされている、日本語コードを疑いました。
調べてみると、ファイルの日本語コードは、コピー元もコピー先もShift_JISです。
コピー先の、VSのC言語のソースも、何故かShift_JISなのです。
VSのエディタで、どのように扱っているかは調べようがありませんが、保存してあるソースファイルはShift_JISです。

試しに、保存してあるソースファイルをメモ帳で開いて、同じ内容を貼り付けて、VSを立ち上げてみました。
結果、同様に赤い波線が出てきます。

特殊な漢字を使っていて、それに反応しているのかもと調べてみました。
昔、機種依存文字とか、コントロールコードとかの絡みで、こういう事がありました。
一行ずつ、一文字ずつ削除して調べました。それでもはっきりしません。
消える場合もあります。消えない場合もあるのです。どの漢字か特定できません。
しかも、全部削除しても波線が残る時もあります。

ただ、コンパイル、ビルドは通ります。
この用語がよく分かりません。
昔は、実行ファイルを作る作業をコンパイルとかリンク、メイクmakeとか読んでいたと思いますが、VSには、今の所、どちらも出てきません。
後日、調べて、実行ファイルを作るのはビルドだそうです。いつもビルドした後デバッグしていたので、デバッグで実行ファイルが作られるのかと勘違いしていました。
更に、releaseモードでビルドしたものが正式の実行ファイルの様です。
debugモードでもビルとすると実行ファイルができます。
同じものかと思っていましたが、ファイルを比較しててみたら。サイズが違います。
releaseモードの方が小さくなっています。
どこにも書いてありませんが(どこにも見つけられませんが)、多分、デバッグモードの方は、デバッグの為のコードが含まれているのでしょうね。暴走しない様に。
実行速度にも違いがあります。releaceの方が早いです。

そのビルドやデバッグですが、波線があってもできます。実行できています。
これはやはり、波線の方が間違いだろうと考えるようにもなりました。

ある時、偶然気付きました。
窓で作業している時に発生します。
全画面で作業している時はこの現象は出てきません。
ただ、窓で発生している状態で、全画面にしても消えません。
逆に、全画面でコピーして、窓に変えた場合は、発生する場合も発生しない場合もあります。
困ったものです。
貼り付けたものを、元に戻すコマンドで戻しても消えない事が多いです。しかし、そのまま全画面にして、赤線の出た状態で終了して、再度起動すると消えていたりします。
色々試すと、もう滅茶苦茶です。

プロジェクトをもう一つ作ってあって、そちらではこの現象は発生しません。
そこで、考えました。
最初からやり直す事にしました。
下のメモにある方法で、既存のCファイルからプロジェクトを作り直してみました。
何しろ、ソースファイル一つのプロジェクトです。
そのファイルを一つだけコピーして作り直すだけです。
これで見事解消しました。

思うに、原因は、
この作業中にソースファイルを入れ換えたことです。
なんの為だったかおぼろげですが、どこかのコメント行を追加したか、コードの一部を他所から持って来たかで、ソースファイルを同じ名前で入れ換えたことがあります。
多分、このせいだと思います。
試してみると簡単に分かることですが、面倒なのでやりません。
VSのプロジェクトは、多数のファイルが出来ています。
その中に、何かエディタ上の変更に付随して書き換わるファイルがあるのではないだろうか、という事です。
VS以外のエディタで、途中で編集をすると、何か辻褄の合わない事が起きるのではないのか、というのが、現在の推定です。

200526追記
再発しました。また赤い波線です。
思い当たる直前の作業は、
まず、ちょっと暴走気味で、メニューの変な所をクリックして、帰ってきませんでした。
どうするかのダイアログが出て、終了を選びました。
メモ帳からの文章をコピーで持って来ました。
#define文で、一行に//を2か所使いました。
この辺りで波線に気付きました。
やはり、窓での作業中でした。全画面にすると、消える時も消えない時もあります。
今回は、二つのプロジェクトで同時に発生しました。

行き詰って、最後に、プログラムのバージョンアップが無いか調べたら、新しいものがありました。
更新しました。
今の所、発生していません。波線は出ていません。まだアップして一日目ですが、平穏です。

200609
再発しました。
コメントの、/*、*/、の部分が赤い波線になっています。
今回は、変な作業はしていません。いえ、他のテキストからコピペぐらいはしたかもしれません。
200610
また、更新がありましたので、実行しました。Ver16.6.2になっています。
再起動したら、消えています。
200616
しばらく出ていませんでしたが、今日出ました。赤い波線です。
何故か、ほぼ全体的に発生しました。
終了、起動を何度か繰り返すと消えました。
発生は、エラーと言いますか、例外が発生した直後に出るようです。
一旦VSを終了し、再開すると大体は消えます。
更新は関係ないかも。更新したら、再起動しますからね。
こんなものなのかも知れません。



200522
既存のCのファイルからVSのプロジェクトを作る

既存のC言語のコードからVisualStudioのプロジェクトを作る段取り。
これまで、何度か試していて、ここまで、うまく行ったり行かなかったりでした。
今日、改めて試して、すんなり成功しましたので、メモしておきます。

別のプロジェクトで使ったフォルダ全体をコピーして、フォルダとソースファイル名だけ変えて、新しいプロジェクトを立ち上げても、うまく行きませんでした。対策を知らないだけかもしれませんが。
ソースファイルだけを、名前を変えて新しいフォルダにコピーして、この方法でプロジェクトを作るとうまく行きます。
(単独のソースの場合です。)

まず、
VSの起動画面の、プロジェクトの選択画面で、コード無しで実行、を選択します。

何も無い状態でVSが開くので、
メニューの、ファイル、新規作成、既存のコードからプロジェクトを作成、を選択していきます。

作成ウイザードが開くので、
作成するプロジェクトの種類はVisualC++、を選択し、次へのボタン、

プロジェクトのファイルの場所は、あらかじめ準備していたフォルダを、
プロジェクト名は、準備してある既存のCのコードのファイル名を入れます。
ここ、あらかじめ、既存のファイル名、フォルダ名、プロジェクト名の3つを同じ名前に合わせています。ただ、これが必須かどうかは不明です。
この窓には、都合3個のチェックボックスがあります。
一つは、次のフィルダー云々「フィルダー」となっています。
既定で全部チェックされていますので、そのままです。意味は分かりません。
次へのボタン、です。

つぎの画面で、プロジェクトの種類に、コンソールアプリケーションプロジェクト、を選択します。
ここの選択肢で、Windowsアプリケーションが既定の様ですが、多分、これを選ぶとまずいのだと思います。
後、次へのボタンで数画面ありますが、意味不明で、いずれも既定のままです。
ですので、完了ボタンで終わっています。

この設定で始めると、先のSDL関連はチェックされていません。
ですので、最初から、ビルドエラーは出ません。


200522
VSでコードのファイルがリソースファイルのフォルダに属している

何やら、試行錯誤でプロジェクトを作った際、よく見ると、Cのソースファイルが、ソリューションエクスプローラーでリソースファイルのフォルダに属している問題。

ファイル一つのプロジェクトで、ソースファイルのフォルダには何もありません。
これで、期待通りに実行は出来ているので、実用上の問題はないのですが、少し不安です。

そこで、思い切って入れ換えてみました。
方法は、
ソリューションエクスプローラーのファイル名の右クリックメニューに削除という項目があります。
これを選ぶと、除外か削除か選択するように促されます。
そこで、除外を選びます。削除を選ぶと、実際にファイルが削除されそうでした。
次に、ソースファイルの右クリックメニューで、追加、既存の項目、と進んで、該当ファイルを選択すると、無事入れ換えが出来ました。
ビルドもデバッグも同じようにできます。変わりません。


200521
VS2019、ビルドエラー、C4996

これまで、ほどほどうまくいって、期待通りの結果を出しているCのプロジェクトがあったので、このコードを使って別のファイルを作ろうと、新しいプロジェクトを立ち上げました。

新しいプロジェクトを作り時、試行錯誤で色々試したので、どの方法だったか思い出せません。
何やら、ソースファイルに、元のファイルからコードを全コピーして持ってきたと思います。
ところが、全く同じコードなのですが、ビルドエラーです。
fopenなどがエラーになっています。
元のコードでは警告で済んでいる所です。

何か対策があるはずと調べてみたら、
ソースファイルを反転させて、(右クリックメニューにあるプロジェクトから進んでも同じです。)、
メニューの、プロジェクト、プロパティ、C/C++、全般、と進んで、SDLチェック、という項目を、いいえ、にすると解決しました。
プロジェクトの作り方、初期設定が間違っていたのだと思います。
多分、コンソールではなくWindowアプリを選んでいたのだと思います。

なお、この問題、上の200522の記事で、根本的な(多分)解決方法を見つけてあります。

200519
malloc

Cでテキストファイルを読み込もうとしました。
250KBほどある巨大なファイルです。
大きいファイルだと、読み込んだり、作業するのが面倒なので、最初は小さなファイルから始めました。

まあ一応、予定通りの動きをします。
そこで、目的のファイルを読み込ませてみます。
エラーです。

試行錯誤と合わせて、ネットで調べた結果、分かったことです。
文字型配列の要素数に限度があり、大きな配列を宣言する時は、mallocを使って領域を確保する必要があるとの事です。
スタック領域、ヒープ領域という言葉で説明されています。
普通の宣言では、スタック領域に確保され、こちらだと、通常、あまり大きな領域は確保できない。
思い起こすと、アセンブラで言う、push、popの領域でしょうかね。
ヒープ領域は、この制限がなく、こちらを使う時には、mallocを使って確保する、のだそうです。

200512
文字コード、改行
Cでのテキストファイルの保存に関して
改行が余分に入って保存された事があります。
メモ帳で見たら、Macintosh(CR)となっていました。
TeraPadでは、SJIS CRと表示され、やはり改行が余分に入っていました。
ワードパッドでも試しました。改行されていませんでした。こちらでは何と判断されているか分かりませんでした。

余分な改行の原因はすぐ分かりました。と言っても試行錯誤の結果です。
fopenを "w"で開くと別にCRが付加されます。CRLFの他にCRが付きます。
"wb"で開くと、そのままです。
そうです。テキストをバイト単位で扱っているプログラムです。
ですので、16進のダンプも打ち出せます。
先の改行を挟む所は、通常は0d,0a、(CR,LF)となるべきところで、
余分な改行が入っている分は、0d,0d,0a、(CR,CR,LF)となっていました。
読込の時は、普通に"r"でfopenしても問題は出ていません。

なんとなく、世間では常識的な話なのかもしれません。

200512
プログラム言語、VisualStudio2019、文字コード

ほかの言語についても、多少の知識はあります。あるつもりでした。
現に、PCには古いコードを残しています。
1998年にCを、2003年にC++をやっていた形跡があります。LccとかBccとかのフォルダがあります。
コードもexeファイルも残っているので、試しに実行してみましたが、現在の環境では動きませんでした。
タイムスタンプから見て、Win98とかXPの頃でしょうかね。XPの環境はありますので、実行してみましたが、動きませんでした。

PCを作り変える際、データディスクだけは、そのまま付け換えるなり、コピーするなりして移動させていましたので、当時のOSが何だったかは、はっきりとは思い出せません。

他に、COBOLを勉強していた時期があります。
かすかな記憶では、COBOLは計算が苦手で、平方根の計算が出来ませんでした。
そこで、ニュートン法を使って試行錯誤で平方根を探すルーチンを作った覚えがあります。

具体的には、平方根は、元の数字以下になる事は分かっていますので、まず、元の数の半分の値を2乗します。
さすがに2乗は掛け算です。どの言語でもできます。
この結果が、元の数より大きければ、更に下半分に答えがあることが分かります。
小さければ、上半分です。
ですので、どちらかをさらに半分にした数字で試していきます。
これを必要な桁数まで探していくだけです。
これをある程度進めていくと、小数点以下で変化しない桁が増えていきます。
その変化しない桁は有効な数字と考えていいはずです。多分。

このルーチンは、当時は貴重だったのかもしれません。
オフィスコンピュータのメーカーのSEの方から、コピーさせてくれと頼まれて、コードの入っているFDを渡した記憶があります。
何しろ、当時、COBOLはオフコンでのみ動いていましたので、コンパイルさせてもらう為に、時々、メーカーの事務所に遊びに行っていました。会社にオフコンを導入した際の取引先でした。

BASICに関しては、使っていたPCの数だけありますね。
当時は、各メーカーが独自のパソコンを作っていて、OSもメーカーの数だけありました。それぞれ、ほとんど互換性はありませんでした。
その後、MS-DOSというOSが主流になって、全てMSのWindowsに流れていく訳です。

思い出すのは、沖BasicとN88Basicとの共通のFDを作った事です。
当時は5インチFDでした。2DDとか1MとかのFDの頃です。
双方のBasicで、FATでしたか、データを管理する領域の配置が違っていました。
幸い、当時は、セクター単位で読み書きするコマンドがBASICにもあって、自由に中身を調べ、変更できました。
そこで、互いの管理領域に仮のデータがあるように処理して、アクセスしないようにしていました。

アセンブラも少し勉強しました。MASMとかありました。
当時、Z80でした。haltだけ覚えています。
こちらは、8086に変わった時点で諦めました。
逆だったかもしれません。
ニーモニックでしたか、命令語が一段と増えていました。まあ、様子見、冷やかしでしたので。

さて、本題は、
とにかく、処理の早い言語の導入を考えました。
どうやら、コンパイラならどれでもいいようです。
各言語での速度比較のページによると、BASIC関係以外は大差ありません。いえ、BASICやHSPに比べたら格段に速いです。

真っ先にC言語です。
以前、Cで簡単な計算をする物を作っています。
最初、LotusかExselのシートで作った物を、Basicに移し、C言語に移しました。
更に主流は当時でもC++に移行中で、C++でも作りました。
ところが、C++に至って、クラスだったか構造体だったかが理解できず、挫折しました。
おぼろげな記憶ですが、とにかく、選択肢が多くて、複雑で面倒だなと思ったものです。
その後、現在のHSPを見つけて、ほとんどこれ一本で遊んでいます。
数KBのファイルを扱うものなら、インタプリタでも速度が遅くても問題ないのです。

ここに至って、なにがしかのコンパイラで作ればなんとかかるだろうと、準備を始めました。
VisualStudio2019をインストールしました。
これだと、CでもC++でもVisualBasicでも使えるという事です。しかも無料です。
先の速度比較では、VisualBasicでもHSPより格段に速いとありました。

まず、VB、C++,、Cと試しました。
先に、昔、自分で作った物をVS2019に移そうとしましたが、まずこれが出来ません。
ようやく移行できて、コンパイルすると、ビルドでしょうか、エラーです。
残念なことに、Cでさえ、その原因が分かりません。
どうやら、当時のコンパイラ独特のヘッダファイルとかがあるようです。

それなら、VBなら何とかなるかと、試してみました。
さすがに、VBだと、ある程度工夫すると動きます。
ところが、結果が文字化けします。
理由は、どうやら昔のShift_JISが通用しない事にあるようです。
いまのVisualStudioはUnicode(UTF-8、16)が標準みたいです。
コンバートする方法もあるみたいですが、理解できません。うまくいきません。

最終的にCで組めました。コンソールタイプですが。
ありがたいのは、どうやらC言語だとVSでもShift_JISで扱える事です。
標準なのかどうかは不明ですが、そのままで通用しています。
ソースファイルもShift_JISで保存されています。
ことによると、最初の既存のコードファイルがShift_JISだったので、そのまま引き継がれているのかもしれません。
作業対象のShift_JISのテキストファイルを普通にfopen、fread、fwriteすると、Shift_JISのままで操作できています。



200512
実行速度
現在、このサイトのページを作る事以外にも、色々な作業をHSPで試しています。
その中で、テキストファイルの変換をするものを作りました。
テキストを読み込んで、変換作業をして、再度ファイルに保存するものです。
単純な作業なのですが、バイト単位の作業で、意外と時間がかかります。
100KB程度のファイルで、11分ほどかかっていました。(この点、下に訂正あり。)
これでは、少し、時間がかかり過ぎです。

そこで、他の言語の実行速度を調べてみました。
まず最初に、自分のスクリプトを見直してみる、という事には思い当たりませんでした。
ネットで、他の言語を調べてみると、さすがにコンパイラでは速度は桁違いです。しかも何桁も違います。
そこで、コンパイラを試す事にしました。

200526追記
C言語での作業が一段落したので、結果です。
対象は100KB程度のテキストの変換作業です。作業内容は先のHSPと同じです。
HSPのみでは、11分かかる作業が、Cで作ると、125ミリ秒弱で終わります。0.125秒です。
HSPに比べてCでは、1/5500の時間で済んでしまうという事になります。(この点、以下に訂正あり。)

200530追記
Cでコードを作る際、HSPで組んでいたスクリプトを参考にしました。
ここで、HSPのアルゴリズムを見直しましたので、実行速度に関して、ものすごく冗長に作っていた事に気付きました。
プログラムは、速度より見やすさ優先が昔からの癖で、一回のループで済むところを何回かに分けたりして処理しています。

極端な話、数回のループなら、スクリプトをその数分コピーして済ますようなこともあります。
この方が、安全確実ですので。

やむを得ず、ループ内で複数の作業をする場合、作業の経過が分かるように、中間の処理状況を入れる変数をたくさん作ります。
途中、debugやassertを使って状況を調べられ、作業状況が分かり易くなるのは間違いありません。
ただ、大量のデータを扱う場合、そうも言っておられません。上の通り、たいした事をしていないのに11分かかる様になってしまいます。

Cの方は、アルゴリズムが分かっていたので、一回のループで処理できています。
それに、経過記録など悠長なコードの書き方を知りません、コンソールなので元々表示が単純でした、等が原因でしょう。
時間計測の際は、更に、#defineでprintf類をスキップします。

これを見習って、翻って、今度はHSPのスクリプトも修正しました。
作業時間の比較をするのなら、無駄な作業を省かないといけません。
無駄な変数を使わない。
無駄な表示もしない。
今回、mesboxも大量のテキストだと、表示時間が結構かかる事に気付きました。
しかも、末尾の記述が見やすいように、逐一スクロールさせていましたので大変です。
また、mesboxを使って、バイト単位の作業状況を表示させていました。
つまり、バイトごとに表示、ここでは数字ですが、を書き換えていました。
ループも出来るだけ少なく、中でawait類を使わない。(これで大量のデータ処理をすると、帰ってこない状態になりますが。)
等、作り直しました。

結果、先の100KBのテキストの処理が、49秒で終わるようになりました。HSPだけでの作業です。
上で、冗長なスクリプトで、11分かかったとメモしたものです。正確には689秒でした。
HSPでの改良だけで、前に比べて、1/14の時間に短縮されています。
いえ、それだけ冗長なスクリプトを書いていた、という事で、11分に関しては、これ以上比較する意味がありません。

次に、肝心のテキストの変換作業だけをCで代行する事を考えました。
本来は、作業速度を考えるなら、デスクトップを含んで全部をCか他のコンパイラで作ってしまう所でしょう。
あるいは、Cでdllを作って、HSPで読み込んで実行させる、という事の様です。
これについても少し調べましたが、私にはどちらも理解が出来ませんでした。

そこで、Cとの連携をファイルを使ってする事にしました。幼稚なやり方です。ですが、今の知識で出来ました。
目的のファイル名など、HSPでデータ引き継ぎ用のテキストファイルを作って保存して、Cを呼び出します。
Cでは、そのファイルを読み込んで変換作業をし、作業結果を、やはりファイルに保存します。

まあ、Cでも、ファイルの読み書きと、足し算引き算ぐらいなら、私にも出来るという事です。
それに、今回分かった事で、ファイルの読み書きには、さして時間がかからないという事です。
Cと引継ぎをする為のファイルにしろ、作業対象のファイルにしろ、ミリ秒の単位で処理されています。

このCで作るファイルをHSPで見張っていて、ファイルが出現したら、作業完了となります。
今、HSP側で、ファイルの出現を見張る間隔を1秒にして試すと、変換作業が3秒で終わるようになりました。
HSPだけで作業すると、50秒でしたので、1/17に短縮したことになります。
何より、3秒程度の待ち時間なら、精神的に許される時間だと思います。
その意味で、Cとの原始的な連携は許されていいと思います。

更に、HSP側の見張る間隔を0.5秒にすると、作業は1.2秒で終わりました。
これなら、もう十分に許される範囲です。
改良しても、HSPだと目的の100KBを処理するのに50秒かかります・
これでは、やはりストレスです。Cと組み合わせた価値が出てきます。

この状態で、C単独での実行時間(0.094秒)と比べると、527倍の時間です。Cだと、1/527の時間で済む、という事です。

ここまでの数字を一覧表にまとめてみます。
言語 100KBのテキストでの作業   20KBのテキストでの作業   2KB のテキスト
処理時間(秒) HSPを1として   処理時間(秒) HSPを1として   処理時間(秒) HSPを1として
HSP改良前 689.000 13.9   134.000 60.2  
HSP改良後 49.548 1.0   2.226 1.0   0.156 1
HSP+C 1.234 1/40   1.023 1/2.2   1.094 7.0
Cのみ 0.094 1/527   0.031 1/72  

20KBのテキストでも試してみました。
HSP+Cでの作業時間は、どちらでも、ほとんど変わりません。
これは、HSPでCの作業終了を見張る間隔を0.5秒にしている事で、この時間内に収まる作業では差は出ないという事でしょう。
何しろ、C単独だと、0.1秒程度で終わっています。

HSP単独での作業で、作業時間がファイル容量の比率にならないのが不思議です。
指数関数的な作業になっている様ですが、よく分かりません。

HSPで、2KBも試して、HSPだけで時間の比較をしてみました。
100KBだと、1KB当たり、0.495秒、
20KBだと、1KB当たり、0.113秒、
2KBだと、1KB当たり、0.078秒、
やはり、何か指数関数的なものがあるようです。



200507
Visual Studio Code 日本語化

エディタが欲しくて、Visual Studio Codeをインストールしてみました。
HSP以外のプログラム言語に挑戦してみようという魂胆です。
どうやら、今持っているTeraPadやメモ帳では物足りないみたいですので。

まず最初に、
MSのページからインストーラをダウンロードするのですが、紹介されているページが沢山あり、どれが一番安全なのか、主流なのか迷います。
結局、Microsoft Storeにも置いてありましたので、これを使いました。
他にも、MSのページが検索の最初に出ました。そこからもダウンロードしてみましたが、全く同じ物でした。

インストールは簡単に終わり、簡単に起動できました。
途中、デスクトップにアイコンを作る、ファイルの右クリックメニューに追加する、という意味のチェックが出ましたので、追加しておきました。

問題は、最初の起動が英語で、これを日本語化する事でした。
ネットの記事通り実行したつもりですが、再起動しても相変わらず英語のままです。

何度か試した結果、原因は、
メニューのviewのプルダウンから幾つか進んで、
configure display languageをクリックした後、
select display languageというダイアログが出ますので、
そこで、jaを選択する、
という事でした。
この間、日本語のインストールが済んでいなければ、その作業も入ります。

肝心の場面は下のキャプチャー画像の通りです。
そのまま適当にクリックしたり、Enterなどで指定するとenの方が反転していて、enを指定したことになります。
ここでしっかり、jaの部分を指定し、反転させねばなりません。
install云々の所をクリックしても、jaを選択したことにはなりません。
enを選択した状態でも、再起動のメッセージが出ますので、ここがとても迷うところでした。


200506
HSP、C言語

普段、HSPでプログラムを作っています。趣味程度です。
このサイトの大半のページを、そのHSPで半自動化しています。
今回、サイト作成とは関係なく、テキストファイルを読み込んで、バイト単位で変換して、保存する、というプログラムを作りました。
ところが、これが手間取るのです。
100KB程度のテキストファイルだと11分かかってしまいました。

このサイトのページは、5KBから10KB程度です。この程度のものだと待ち時間は感じられません。
ただ、11分もかかるようだと問題です。
対策は、プログラムを改良するか、他の言語を試すかです。
他の言語を試すことにしました。



トップページへ