全知全能を目指す人のありがたい雑記

何かしら意味のあるありがた~い話か、意味のない雑念だらけの日記を書く予定です。

【パワー系PG】データを整数型で表現しないで列挙型を使え

あなたのプログラム、「intを不必要に多用」してませんか?

どの言語にもenumみたいな列挙型ってあると思うんだ。
C言語における、intとenumによる実装の違いを紹介しよう。

intを使ったときの実装

#include <stdio.h>

int main(void){
    
    int warningRate; //2桁入力【例:36】
    scanf("%02d", &warningRate);
    
    int signal;
    
    if(warningRate < 50){
        signal= 0;
    }
    else if(warningRate < 75){
        signal= 1;
    }
    else{
        signal= 2;
    }
    
    switch(signal){
        case 0:
            printf("緑、今日も平和だ");
            break;
        case 1:
            printf("黄、危ない予感");
            break;
        case 2:
            printf("赤、逃げろー!");
            break;
    }
}

読ませる側や保守・運用を考えない
パワー系PGの臭いがする!!

enumを使ったときの実装

#include <stdio.h>

enum Signal{
    Green,
    Yellow,
    Red,
};

int main(void){
    
    int warningRate; //2桁入力【例:36】
    scanf("%02d", &warningRate);
    
    enum Signal s;
    
    if(warningRate < 50){
        s = Green;
    }
    else if(warningRate < 75){
        s = Yellow;
    }
    else{
        s = Red;
    }
    
    switch(s){
        case Green:
            printf("緑、今日も平和だ");
            break;
        case Yellow:
            printf("黄、危ない予感");
            break;
        case Red:
            printf("赤、逃げろー!");
            break;
    }
}

何が言いたいか

int signal;って変数に
0とか1とか2って入れてるけど、
signalが0だと何なの?signalが1って何?2って?

見ただけじゃあ判断ができない。
0や1や2である意味は、
後続の処理から推測するしか方法がない。

何でもかんでもintやstringで解決する輩が一定多数いるので
気になって仕方が無い。

あと、余談だがenum⇔intの相互変換もできる。

以上

enumっていう数値を名前付き定数として
表現できるものがあるんだから使おうぜ~。。

【パワー系PG】ハードコーディングはやめてDBMSを使いたい

あなたのプログラム、「ハードコーディング」してませんか?

ハードコーディングとは簡単に言うと以下のような感じ
内容としては業務データをプログラムで作っている処理。

int input;
scanf("%d", &employeeNo);

if(employeeNo< 1&& employeeNo> 100){
    //①の業務データ
}
else if(employeeNo< 101 && employeeNo> 200){
    //②の業務データ
}
else if(employeeNo< 201 && employeeNo> 300){
    //③の業務データ
}
else if(employeeNo< 301 && employeeNo> 400){
    //④の業務データ
}
else if(employeeNo< 401 && employeeNo> 500){
    //⑤の業務データ
}
else if(employeeNo< 501 && employeeNo> 600){
    //⑥の業務データ
}
else if(employeeNo< 601 && employeeNo> 700){
    //⑦の業務データ
}
else if(employeeNo< 701 && employeeNo> 800){
    //⑧の業務データ
}

あっ、パワー系PGが書いたコードか!!!

さて、上のコードで気になるのが何点か。

  • 1とか100とか101とか200って何ぞ??
  • コード量にパワーを感じる

コードを書いていない側からすると
色々気になってくるコードだね。

卒業する方法

  • 1とか100とか101とか200って何ぞ??
  • コード量にパワーを感じる

仰る通りです。
パワー感じますよね。
1とか100とか101とか、パッと見、数値の意味がわからんちんですな。

そもそも、
業務データを取り扱うときは
プログラムにガリガリ書くべきではない
です。
まあ、当たり前の話です。

業務データを取り扱うときは
プログラムに直接持たせるのではなく、
DBMS(データベース管理システム)を使いましょう。

言語とDBMSを連携するには相応のライブラリや
フレームワークを流用するのが筋
です。
DBMSも、色々種類があるので何か自分に合うものを探すと良いです。

例えば「C言語MySqlの連携」を例に挙げるなら、
以下の記事辺りを参考にしてください。
d.hatena.ne.jp

ぐぐればいくらでも出ます。

あと、データベースにアクセスするためには
SQLというのを覚えないといけません。

まあ単純な文なら一瞬で覚えられます。
cfm-art.sakura.ne.jp

書き方のイメージとして以下のような形式。

SELECT [営業所種別] FROM [従業員テーブル] WHERE [従業員番号]

SQL文はライブラリやフレームワークによって
プログラム内に記載できます。

例えば、WHEREの後には条件を記載するのですが、
条件に先ほど定義したemployeeNoを渡すこともできます。
※その場合はemployeeNoに対するレコードをDBからもらえます。

ですので、
データベースから引っこ抜いた営業所種別のレコードをそのまま流用すれば
プログラムとしては数行で済むわけです。

業務データはDBMSを使おう。

「パワー系PG」は卒業したい

こんにちは。

突然ですが、あなたのプログラムからパワーは感じませんか?

  • 1ファイルに数千行も記載してる?
  • 機能分割がきちんとできていない?
  • 同じコードをコピペしている?
  • 変数を連番に命名している?
  • 変数名が適当?
  • 1行に無理やりロジックを詰め込む?
  • 似たようなリテラルを直書きしてる?

さて、本来はプログラムにパワー(気合)を込めるべきなのでしょうか?

自分はそうは思いません。

成果物に対して、
可能な限り少ないコード量で人が読めるコーディングをすべきです。

気合で書いたコードは以下の問題があります。

  • バグが発生したとき、何千行もあるコードを人が気合で見ることになる
  • バグを修正するとき該当箇所が複数箇所にコピペされており、修正箇所の網羅と修正漏れが怖い
  • 適当な変数名を定義したりリテラルを直書きしたりで、該当行で何の処理をしているのかまったくわからない
  • 1行にやりたいことを詰めすぎて処理が追えない

適当に箇条書きしましたが、とにかく恐ろしいです。

このように、頭を使わないで
とにかく「コピペ」や「一時的な解決にしかならないコーディング」等、
コーディングをパワープレイで済ませようとする人のことを
パワー系PG」と呼んでます。

「パワー系PG」はまともなPGではありません。

自分のプログラムにパワーを感じてきたら
要注意です。

パワー系PGは卒業して、
効率を重視する面倒くさがり屋で優秀なPGになろう。

C言語でうるう年計算・月の末日計算・曜日計算を一通り書いた

学生の課題あるあるのプログラム。

各関数は全部落ちてるソースをパクっただけ。

fudebaco.com
edu.clipper.co.jp
C言語入門:うるう年判定プログラム:Geekなぺーじ

#include <stdio.h>

int main(void){
    int year; //yyyyで入力する!例「1970」
    scanf("%d", &year);
    
    int month; //mmで入力する!例「01」
    scanf("%02d", &month);
    
    char weekdays[7][4] = {"日","月","火","水","木","金","土"};
    
    int lastday = GetLastDay(year, month);
    
    for(int today = 1; today < lastday + 1; ++today){
        printf("%02d%02d%02d日 ",year,month,today);
        int weekday = GetWeekday(year, month, today);
        printf("%s曜日\n",weekdays[weekday]);
    }
    return 0;
}

int IsLeapYear(int year){
    if (year % 400 == 0 || (year % 4 == 0 && year % 100 != 0)) {
      printf("%02d年はうるう年\n", year);
      return 1;
    } else {
      printf("%02d年はうるう年ではない\n", year);
      return 0;
    }
}

int GetWeekday( int y, int m, int d ){
    if( m < 3 ) {
        y--; m += 12;
    }
    return ( y + y/4 - y/100 + y/400 + ( 13*m + 8 )/5 + d )%7;
}

int GetLastDay(int year, int month){
    int l;
    int lmdays[] = {31,29,31,30,31,30,31,31,30,31,30,31};
    int mdays[]  = {31,28,31,30,31,30,31,31,30,31,30,31};
    int lastday;
    
    l = IsLeapYear(year);
    if (l == 1) {
        lastday = lmdays[month - 1];
    } else {
        lastday = mdays[month - 1];
    }
    
    printf("%02d%02d月の末日は%d\n",year,month,lastday);
    return lastday;
}

入力

1992 02

出力

1992年はうるう年
1992年02月の末日は29日
1992年02月01日 土曜日
1992年02月02日 日曜日
1992年02月03日 月曜日
1992年02月04日 火曜日
1992年02月05日 水曜日
1992年02月06日 木曜日
1992年02月07日 金曜日
1992年02月08日 土曜日
1992年02月09日 日曜日
1992年02月10日 月曜日
1992年02月11日 火曜日
1992年02月12日 水曜日
1992年02月13日 木曜日
1992年02月14日 金曜日
1992年02月15日 土曜日
1992年02月16日 日曜日
1992年02月17日 月曜日
1992年02月18日 火曜日
1992年02月19日 水曜日
1992年02月20日 木曜日
1992年02月21日 金曜日
1992年02月22日 土曜日
1992年02月23日 日曜日
1992年02月24日 月曜日
1992年02月25日 火曜日
1992年02月26日 水曜日
1992年02月27日 木曜日
1992年02月28日 金曜日
1992年02月29日 土曜日

テーマをカスタマイズした

背景色が地味だったのと、透明感を持たせたいなーと言うことで
コンテンツのアルファ値を変更しやした!!

デザインCSSに以下の記述を追加。

#container-inner{
  background-color: rgba(46, 46, 46, 0.93);
}

.entry-inner blockquote{
  background-color: rgba(46, 46, 46, 0);
}

引用が追随して透過されなかったので、
entry-innerクラスの引用文に対して直接透過を指定しやした。

透明感がでてすっきりしたぜ。

C#で文字列を弄るなら正規表現を使いたい

ファイル名に拡張子をつけていないので、
ファイルを保存する際に、
拡張子を追記して保存するようにしたい

と仰る方を見かけたので一つサンプルコードを。

文字列操作なんて不要!
なら、正規表現で置き換えてみよう。

↓無理やり文字列の後尾に「.png」を追加するプログラム

using System;
using System.Text.RegularExpressions;

public class Program{
    public static void Main(){

        string fileName = Console.ReadLine();

        if(fileName == null){
            Console.WriteLine("入力に文字を入れてください。");
            return;
        }
        
        if(fileName.Contains(".")){
            Console.WriteLine("拡張子を.pngに置き換えます");
            fileName = Regex.Replace(fileName,@"(?<=\.)(.*)","png");
        }
        else{
            fileName = string.Concat(fileName , ".png");
        }
        
        Console.WriteLine(fileName);
    }
}

追記

↑のやつ
「aaaa.hoge.fuga」ってやると
「aaaa.png」になる。駄目コード。

ってか、少し調べてたらこんなクラスがあったで。。。
Path.ChangeExtension メソッド (String, String) (System.IO)

正規表現なんて不要!
なら、ChangeExtensionで置き換えてみよう。

↓無理やり文字列の後尾に「.png」を追加するプログラム(Ver2)

using System;

public class Program{
    public static void Main(){
        
        string fileName = Console.ReadLine();
        
        if(fileName == null){
            Console.WriteLine("入力に文字を入れてください。");
            return;
        }
        
        fileName = System.IO.Path.ChangeExtension(fileName, "png");
        
        Console.WriteLine(fileName);
    }
}

え?
1行で済むやないかーーーーーい

.NET様様だね。

Photon Unity Networkingを使ってみよう「かなぁ」

3Dでかつ、マルチプレイがしたい!ってことで

UnityにPUNを導入することにした。

とりあえず、公式?の解説(古い記事)と

更新日時が比較的新しい(今年の)記事の2つを参考にしている。

 

support.photonengine.jp

nopitech.com

 

導入手順

  1. Photonのサイトでアカ登録

    新規登録 | Photon Engine

  2. 「アプリケーションリスト」に移動してアプリを作成する(種別はPUN)

    https://dashboard.photonengine.com/ja-JP/App/Create

  3. Unityのプロジェクトを立ち上げる
  4. AssetストアからPUNを落とす。Free(無償版)で

    Photon Unity Networking Classic - FREE - Asset Store

  5. PUNウィザードが出るので2で作成したアプリのIDを入れる

 

あとはPUNに接続するためのスクリプトを書けば良いっぽいが、

まだ使ってみよう「かなぁ」なのでやってない!!

 

でもwktkしてる。