2023年09月16日
_できなかったことリスト
C++再学習でできないことがきになったこと
・Windowsコンソールアプリでユニコード文字を扱うことができないこと。一部の文字は、スーパープログラマでもマジでできないらしい。マイクロソフトの問題?
・メモリを消費させて、メモリ確保できないというエラーを意図的に起こさせて、メモリ確保エラーの動作テストができなかったこと。検証をする前にWindows自体が死にかけて、例外発生のまえにアプリが落とされる。
2023年09月14日
_阪神はアレを優勝へと変換を確定させたぞ
やったね。
https://www.yo-net.jp/blog/edit/mt-tb.cgi/617
2023年09月13日
_新版明解C++中級編/著:柴田望洋 正誤表
自分が気づいたところをアップ!優しさのカタマリ。初版の2004年3月31日を手元にして執筆したものです。
P248-P249
Shape3/Line.h
49行目
×std::cout << '-'
〇std::cout << '*'
75行目
×std::cout << "|\n"
〇std::cout << "*\n"
あるいはプログラム動作結果の方を合わせるかしないといけません。
P266
chap07/IOBuf.cpp
16行目
×class InBuf : virtual Buf {
〇class InBuf : virtual public Buf {
22行目
×class OutBuf : virtual Buf {
〇class OutBuf : virtual public Buf {
P318
Twin/Twin.h
6行目の後ろに以下include文を追加挿入
#include <iostream>
P332
Array/BoolArray.h
27行目と28行目の間,BitOfByteRef& operator=(bool b){ 省略 }の定義終了部分とクラス定義終了の};の間に
以下のプログラムを追加。
BitOfByteRef& operator=(BitOfByteRef BitOfByteRefb) {
if ((BitOfByteRefb.vec >> BitOfByteRefb.idx) & 1U) {
vec |= 1U << BitOfByteRefb.idx;
vec |= 1U << idx;
}
else {
vec &= ~(1U << BitOfByteRefb.idx);
vec &= ~(1U << idx);
}
return *this;
}
BitOfByteRefbという変数は、任意の名称を使ってよいです。この部分のプログラムがないとその後のメイン関数の使い方
y[3] = y[6] = true;
z[5] = z[7] = true;
でエラーになります。y[3] = y[6]のような代入演算子の引数の形について取り決めがないことになります。プログラムの中身は様々な考え方が適用できますが、自分が考えたのはy[3] = y[6] = true;のような場合、y[6]がtrueやfalseに変更されるので、y[6]の値をy[3]にも反映しつつ、y[6]のtrue or falseの値そのものをy[3]に反映させれば、y[3] = true を実行したのと同じことになるという考え方です。この誤植は、この本の最大規模の間違いのような気がします。
P351
Stack/ArrayStack.h
18行目
× throw Overflow();
〇 throw Stack<Type>::Overflow();
24行目
× throw Empty();
〇 throw Stack<Type>::Empty();
P353
Stack/ListStack.h
3行目の後ろあたりに追加
#include <exception>
39行目
× } catch (const bad_alloc&) {
〇 } catch (const std::bad_alloc&) {
40行目
× throw Overflow();
〇 throw Stack<Type>::Overflow();
46行目
× throw Empty();
〇 throw Stack<Type>::Empty();
P354
Stack/VectorStack.h
24行目
× throw Overflow();
〇 throw Stack<Type>::Overflow();
31行目
× throw Empty();
〇 throw Stack<Type>::Empty();
P371
chap10/vector_assing.cpp
16行目
△ for(vector
〇 for(vector
P374
chap10/vector_print
15行目
× for (vector<T, Allocator>::size_type i = 0; i != v.size(); i++)
? for (vector<int>::size_type i = 0; i != v.size(); i++)
size_typeの型にはテンプレートが使えないみたい。つまり、Column10-1全体の説明も怪しいことになります。C++の規格の進化で事情が変わったのか、著者の勘違いなのかは不明です。vector何型であっても、size_typeの型名も何型でも容量は正しく返せそうな気がしますけど、ここはまだまだ調査が必要です。あとでChatGPTにも聞いてみようと思います。
ChatGPTは以下のようにすればテンプレート引数を使ってsize_typeを切り替えることができるとの回答でした。試してみたところ確かにうまく行きました。typenameキーワードを省略してfor文の中に入れ込んでしまうとうまく i の初期化ができないみたいですね。
template <typename T,typename Allocator>
void print_vector(const std::vector<T,Allocator>& v) {
typename std::vector<T, Allocator>::size_type i = 0;
std::cout << "{ ";
for (i = 0; i < (v.size()); i++) {
std::cout << v[i] << " ";
}
std::cout << "}";
}
template <typename T,typename Allocator>
void print_vector(const std::vector<T,Allocator>& v) {
std::cout << "{ ";
for (typename std::vector<T, Allocator>::size_type i = 0; i < (v.size()); i++) {
std::cout << v[i] << " ";
}
std::cout << "}";
}
でもいいんだって、1行目はtypenameでなくてclassでもいいけど、for文のところのtypenameは変えられません。typenameというのを使うのが現代の主流だそうです。C++03では、本のとおりでも動いたのかもしれません。
P388
chap10/vector_print_it1.cpp
14行目一つ前の正誤関係項目と同じ理由で
× for (vector<T, Allocator>::const_iterator i = v.begin(); i != v.end(); i++)
〇 for (typename vector<T, Allocator>::const_iterator i = v.begin(); i != v.end(); i++)
P397
chap10/vector_print2.cpp
40行目またひとつ前の項目と同じ理由で
× for_each(first, last, put1<std::iterator_traits<InputIterator>::value_type>());
〇 for_each(first, last, put1<typename std::iterator_traits<InputIterator>::value_type>());
またファンクタを受け取るための継承は必要なくなっています。
struct put3 /* : public std::unary_function<const Type&, void> */ {
struct put3<char>/* : public std::unary_function<const char&, void> */ {
struct put3<std::string> /*: public std::unary_function<const std::string&, void> */ {
のように継承を省略してもC++11以降の規格にしたがってプリプロコンパイルリンクをした場合は問題が発生しません。このようなやり方が主流になっているそうです。古き良き歴史を知る上では大事なことかもしれません。
P399
ここでも上の項目のとおり継承が省略できます。どんな型でもどんとこい!って感じで省略できてしまいます。
struct is_even/* : public std::unary_function<const Type&, bool>*/ {
struct plus10/* : public std::unary_function<const Type&, const Type&>*/ {
struct diff/* : public std::binary_function<const Type&, const Type&, Type>*/ {
P426
chap11/string_array_convert.cpp
30行目
△char* p[] = {"PAUL", "X", "MAC"}
〇const char* p[] = {"PAUL", "X", "MAC"}
Microsoft独自の厳密なチェックによりVisualStudio2022では既定の設定ではエラーになります。型"const char*"の値を使用して型"char*"のエンティティを初期化することはできませんというエラーです。
この変更に伴って、
19行目の関数の引数もconstにする必要があります。
△ vector<string> strptary_to_vec(char** p, int n)
〇 vector<string> strptary_to_vec(const char** p, int n)
とする必要があります。関数の引数をそのままにするなら、constでないchar型の2次元ポインタ変数を構築してコピーしないと駄目です。
char** ppchp = new char* [3];
for (int i = 0; i < 3; i++) {
ppchp[i] = new char[strlen(p[i])];
strcpy_s(ppchp[i], strlen(p[i]), p[i]);
}
とかね。
P467
chap12/concat.cpp
8行目
× void copy(ifstream&src, ofstream& dst)
〇 void copy(istream& src, ostream& dst)
型"std::ofstream&"の参照(constで修飾されていない)は型"std::ostream"の値では初期化できません。
というエラーになります。std::ifstream は std::istream の派生クラスであり、std::istream への参照を受け取る copy_concat 関数の引数に対して適切に渡すことができます。
あるいは関数テンプレートを使って
template <typename StreamSrc, typename StreamDst>
void copy_concat(StreamSrc& src, StreamDst& dst){
中身のプログラムには変更ないので省略
}
という具合に変更できます。呼び出し側で
copy_concat2(dynamic_cast<std::ifstream&>(cin), dynamic_cast<std::ofstream&>(cout));
ってするとコンパイルはとおりますが実行時エラーで駄目です。現代においては関数の型を変えるしかないですね。
変更した方が良い箇所
P16
Date/Date.cpp
4行目
△ struct tm* local = localtime(¤t );
〇 struct tm ptmlocal;
errno_t error = localtime_s(&ptmlocal, ¤t);
localtime関数はアンセーフな関数として利用には厳しい警告が発生します。localtime_sを使って予め実体化しておいたstruct tm型の変数を参照型として、localtime_s引数の第一引数として設定すると、その変数に第二引数に設定した時間に関する情報が設定され、受け取ることができます。
P98
chap03/termination.cpp
これも上記と同じ変更がオススメです。
P449
chap12/lasttime.cpp
これも上記と同じ変更がオススメです。
2023年09月01日
_C/C++言語直感的難問
こんな関数があったとします。
void put_list2(const int pcia[], int in, bool pbfuncfit(int)) {
bool bflag = false;
for (int i = 0; i < in; i++) {
if (pbfuncfit(pcia[i])) {
cout << "★";
}
else {
cout << " ";
}
cout << "a[" << i << "] = " << pcia[i] << "\n";
}
}
問.pbfuncfitって変数名なのに、後ろに(int)って付いてます。どういうことでしょう?
はい!シンキングタイム!
終~了~っ、みじかっ!
答えは、関数ポインタの間接演算子省略をした表記です。外部から呼び出すときの引数には関数名を指定します。実際に呼び出すときは、サンプルのプログラム内のようにしてint型の引数が必要なものです。関数ポインタの引数であるint型の値も外部から受け取り必要なときは、もう一つ、int型の引数を追加するとかして、うけとらないと駄目ね。
pbfuncfit(int)って表記だけど、うけとるのは関数名だけなんだってさ。
わかった人は関数ポインタマスターだね。すごいぜ!忘れてた人は、修行が必要だね。
ちな、自分はわからなかった。修行が必要な人だぜ。
ぱっとみなんのこっちゃわからんパターンってこういうことの積み重ねで生まれるんだわ。気をつけないとな。
再学習し始めたら、わかっていないことだらけ。修行が必要。
9月はプログラミングの季節だね。9月1日だ。
2023年08月31日
_打ち込みオワタ
スキャナーによる文書作成という本に記載されていたN88Basicのプログラムだけど、打ち込み終わった。よく頑張った。キーボードの入力作業がまた一段と早くなったという点では、成果があったと思う。
動作確認をすこしづつやって、プログラムの全貌をつかむという作業はコレから。長いプログラムを実行すると、実行したときにエミュレータが管理するメモリ上に読み込まれたプログラムが書き換えられるというトラブルに見舞われている。XLBasicエミュレータのメモリの使い方についてもう少し勉強しないといけないのかもしれない。
もう使ってる人が少ないのか、ググっても検索結果が乏しいのが淋しい。N88も知ってるマニア減ってきてるな。絶滅危惧種だ。やりこんでる人もいるけど、エミュレータに詳しい人が少ない。実機もってそうな人の方がマニアで、いまだになんかやってるという印象。実機もってるとかムネアツ過ぎるだろ。
意外と難しいプログラムも組めるし、あなどるなかれだな。計算機として使いこなすには、ものすごい科学技術の知識がいるのは、今も昔も変わりない。N88でも、文字認識もできれば、科学技術計算もできる。そりゃそうだ。戦争やってる最前線でも動いていたPCだからな。N88といえど、軍事利用も可能なほど高性能なのだ。今のPCのほうがもっと高性能なのもあたりまえの事実ですが、N88をなめすぎると痛い目にあうという話さ。
いまだにN88使ってるマニアの人の知識はやばすぎるってことだな。知り尽くしてる。エミュレータ?何それ?って感じなんだろう。せいぜいゴッコ遊びでもしてろってことだろう。本物にはかなわない。N88一台くらいあってもいい。
2023年08月26日
_時間かかるな!
スキャナーによる文書作成という本に掲載されているプログラムを本からPCで入力してるんですけど、めちゃくちゃ時間かかる。6000行ちかくのプログラムと48kbyteにもなる機械語。しかも、全部打ち込んだところで、デバッグに力をいれたとしても、動く保証はゼロというか動かないの確定してる。
XLBasicエミュレータとの整合性をとる作業が山のようにありそう。
機械語と4000行近くまでプログラム入力した。意味のない作業。1ページあたり70行くらいで、1ページに30分40分くらいかかってそう。
入力速度が遅いのかもしれない。キー入力速度たいしたことないんだな自分。反省。もっと真剣に打ち込み速度を高める練習しておくべきだった。
こういう作業を自動化するためのプログラムを手作業でやっている自分。空しい。自分で文字認識プログラム作ってみたい。
何か得るものはあるのか?この先、みものだな。
打ち込み練習にはなっているが、もっと知識を得たい。
やってやるぜ!みてやがれというところだが、みてないでおけ!だな。
そう!見てないでおけ!
わけのわからないプログラムだよまったく。打ち込みながらも何がしたいのか全く理解できない変数名のつけかた。作成者の人、すごいぜ、古本も出回ってるので、興味のある人は買ってみるがいい。いかに無駄遣いしたかを後悔するような本だぜ。なのに買ったんだぜ俺は。エグイだろ。はははははは!はははははははは!
_C++の再学習ちう
C++の学びなおしを始めました。Basicのプログラムの打ち込み作業をしつつ、合間で
さすがに初歩からの学びなおしはだるいので、中級編から始めています。
クラスで使う仕組みからです。静的メンバ変数・関数・constね。ふんふんって感じ。
http://www.bohyoh.com/
ここの本だね。いい本に出合えた感じがする。エピステーメーさんの話がわかるくらいまでにはなりたいね。
2023年08月17日
_結局
人のふんどしで相撲はとれないとかって奴だな。
挫折を甘んじて受け入れよう。ははははははは。ぶわはははははは。
_N88BasicXL
なんだよ。
今更、N88Basicさわってみたけど
A$="ABC":A!=VARPTR(A$,1)でSyntaxエラーだとさ、お手上げです。あ、XL Basicでは2個目の引数は非対応なので、A$="ABC":A!=VARPTR(A$)としてはいる。似たような構文でいろいろ試しても見た。試行錯誤、構文の組み合わせを考え絞る。すべてダメ。
文字列変数A$が利用しているアドレスを16bit浮動小数点A!に格納する関数なのですが、動かず。悔しい。せっかく理解しようと思ったのに。
XL Basicえみゅの説明書によるとA!が差すアドレスに文字列長 A+1とA+2のアドレスにA$の先頭アドレスが格納されるって書いてあるのに。
それだけじゃない。文字化け。XLがsjis対応なのはわかった。
SCREEN 2,0,0,1を実行しちゃうとその後の日本語を含むPRINT文で文字化けする。XLは日本語表示しようと思ったら第一引数は3(640x200 カラー)か4(640x400 モノクロ)じゃないといけないらしい。何気にいい感じのトラップもある。手ごわい。説明書読めって奴だな。それくらいは対応できてのシンタックスエラー不可避。辛い。
グラフィックキャラクターの利用が出来る1,2と日本語表示の3,4はトレードオフの関係。
イメージスキャナによる文書作成のコードを現代の環境で最大限活用してやろうと思ったのに。
諦めるか…
代替案を模索するか…代替案は見つかるのか?考えたくないような考えたいような。
何をしようとしているのかわかんねぇくらいだからな。SEGPTR8に取得した値を格納して終わっているという不気味な処理。文字列の領域を確保しただけだな。マシン語処理でなんかつかうんだろうか?
マシン語の部分もほぼまだわけわからんし。THE Basicの90年1月号にマシン語解析プログラムが記載されたらしい。欲しい。国立国会図書館いかないと駄目だな。
いや、諦めるか。
違う文字認識プログラムを読んだ方が早いのかな、既存の文字認識プログラムを解説してくれるやさしい人はいないみたいだし。
いや、諦めるか。
ちょっと知りたいだけの気持ちも、おもいっきり挫折するだけの一方通行。
いや、諦めるか。
ここ数年、挫折しかしてない。FONT構造の理解→FONT内部専用のプログラムのようなものがあることを知り挫折。むずすぎ。なんか文字の表示が拡大されたり縮小されたりするときにフォントの頂点の再計算するみたいなものがあるらしい。エグスギル。そこまで理解してやっとで制御できるらしい。それでなくてもフォーマットの種類が多いし。グリフ番号とかの仕組みも大概、ややこしい。体系全体を理解するなんて素人には無理だと悟ったね。つまり挫折。
PDF構造解析も挫折。日本語フォントの埋め込み。すさまじすぎる。ポストスクリプト?理解できない。つまり挫折
VSTプラグインで波形描画?ビットマップの扱い方さえわからない。描画した内容をビットマップで保存したいのにやりかたがまったくわからず。つまり挫折。
Node.js、Vue.js、フレームワーク。jQuery。Django。理解するべきかさえもわからない。つまり挫折。
Vexflowややこしい。できそうでできない。つまり挫折。
確率統計の知識もうすれつつある、微分積分もあまりできない。線形代数も最後のところでわかっていない。つまり挫折。
全部。ぜ~んぶ挫折。挫折。挫折!骨折並みに挫折。
HTMLやCSSでさえもあやしい。SCSS?あやしい。JavaScript?あやしい。
理解が足りないね。疲れたよ。どうしたいんだオレ。なにもみについてないぞオレ。基本情報処理技術者の資格持ってるだけなんだよな。ソフトウェア開発とかとれない程度の人間なんだわ。まいったまいった。
弱音記念日だね。N88Basic触っただけでここまで落ち込むんだわ。
https://www.yo-net.jp/blog/edit/mt-tb.cgi/616