2015/02/25

[C#]パスワードのためのアルファベットと数字混在のランダムな文字列の生成する

このエントリーをはてなブックマークに追加
パスワード生成とかに使われそうな感じのやつです。
IWg7G9mN←こういうのが出力できるとOK。

最初はランダムに数字を取得して文字コードから文字列を取得したらいいかなと考えましたが、単に候補文字をざっと準備しておいてランダムに選ぶほうが明瞭ですね。
アルファベット、数字だけじゃなくて、ひらがなカタカナ、漢字混在で作るにしても候補文字を準備しとくほうが簡単そうです。

文字の配列要素を用意しとく

候補文字を並べて準備しておいて、単純にランダムに選ぶというコードです。
非効率ではあるけれど、あきらかにメンテナンスもしやすいし汎用性もありそう。

private static string STR_GROUP_NUMBER = "0123456789";
private static string STR_GROUP_ALPHABET_LARGE = "ABCDEFGHIJKLNMOPQRSTUVWXYZ";
private static string STR_GROUP_ALPHABET_SMALL = "abcdefghijklnmopqrstuvwxyz";

private static Random _r = null;

// 引数(count)は出力文字の桁数です
public static string RandomString(int count) {
    if (_r == null) {
        _r = new Random();
    }
    string group = STR_GROUP_NUMBER 
        + STR_GROUP_ALPHABET_LARGE 
        + STR_GROUP_ALPHABET_SMALL;
        
    char[] list = new char[count];
    for (int i = 0; i < count; i++) {
        int num = _r.Next(0, group.Length); // ランダムに0~nの数値を返す
        list[i] = group[num];
    }
    return new string(list);
}
数字を出さないようにするためにはSTR_GROUP_NUMBERを除外すればいいだけ。
あるいは記号を追加するのも、文字列を足せばいいだけですね。

Randomクラスはインスタンス生成時の時刻から任意の乱数が選ばれます。
インスタンスを毎時生成すると、間髪入れず連続で呼び出したときは乱数が被ってしまうので、それを回避するために一回生成したものを使いまわすようにしています。

出力結果

桁数8桁のランダム文字を出力してみます。

for (int i = 0; i < 10;i++) {
    Console.WriteLine(RandomString(8));
}

IWg7G9mN
WxHPMkPP
qTu9oblq
WDKokf1J
19mw9TSh
MQlw0cIZ
IjttEtHh
kpa2ozbq
wyMExSGN
1DlMppqu

ばっちりです。

2015/02/22

[C#]ダミーデータをDataTableにして使う

このエントリーをはてなブックマークに追加
デバックやるにしても、何か学習するにも、hogehogeとかaaaとかダミーとして使ってしまうことがあります。aaaとかbbbとか。面倒くさいものなので動けばいいからと思って進めてると、ログ系とか、DB系でけっこうはまるのです。
そこでダミーデータをさくっと展開するためのサンプルコードを置いておきます。(解説っていうよりサンプルコードです)
テストとか、とりあえずなんか動かしてみるのにそれっぽいデータを用意するときに使えると便利です。

ダミーデータを準備する

今回使用するダミーデータは、なんちゃって個人情報さんから引っ張ってきます。
なんちゃって個人情報は、テスト用の個人情報をダミーで生成してくれるというオンラインサービスです。(つい最近知りました)
なんちゃって個人情報
http://kazina.com/dummy/

XMLにして出力件数を指定。今回の出力件数は200くらいにしました。

なんちゃって生成をクリック。
はい、XMLができました。

ファイルの名前を付けて保存からXMLを保存します。

※ちなみに、GoogleChromeでやるとXML作成まではやってくれましたが、そのままファイル保存すると失敗してしまいました。HTMLのなれの果てのようなファイルしかできないときは、IEでやってみてください。
↑失敗です

ダミーデータを展開する

生成されるXMLはrecordの繰り返しで構成されています。
1つのrecordは下のようになっています。構成は生成時のオプションによって変わりますので注意。

<record>
    <name>矢田 桃子</name>
    <ruby>やだ ももこ</ruby>
    <mail>yada_momoko@example.com</mail>
    <sex>女</sex>
    <age>68</age>
    <birthday>1947/1/16</birthday>
    <married>既婚</married>
    <prefecture>大阪府</prefecture>
    <keitai>080-1669- 474</keitai>
    <carrier>ドコモ</carrier>
    <curry>左ルー・別口派</curry>
</record>

DataSetのReadXmlメソッドつかって一発で読み込んでもいいんですが、XMLを展開して読み込むことにします。
/*
using System.Xml.Linq;
using System.Xml.XPath;
using System.Data;
using System.IO;
*/
// なんちゃって個情報をDataTableに展開する
private DataTable LoadDummyData(string dummyXml) {
  DataTable table = new DataTable();
  string[] columns = new string[] { 
  "name", "ruby", "mail", "sex", "age", "birthday", 
  "married","prefecture","keitai", "carrier","curry" };

  // ①DataTableのカラムをつくる
  table.Columns.AddRange(columns.Select(n => new DataColumn(n)).ToArray());

  // ②Xml読み込み準備
  StreamReader reader = new StreamReader(dummyXml, System.Text.Encoding.GetEncoding("shift-jis"));
  XDocument xDoc = XDocument.Load(reader);

  // ③recordエレメントを抽出
  IEnumerable<XElement> records = xDoc.XPathSelectElements("//record");
    
  foreach (XElement record in records) {
    DataRow row = table.NewRow();
                
    // ④DataRowに値をセットしていく
    columns.ToList().ForEach(n => row[n] = record.XPathSelectElement("./" + n + "").Value);
    table.Rows.Add(row);
  }
        
  return table;
}

// DataSetから読み込む方法
private DataTable LoadDummy(string dummyXml) {
  StreamReader reader = new StreamReader(dummyXml, System.Text.Encoding.GetEncoding("shift-jis"));

  DataSet ds = new DataSet();
  ds.ReadXml(reader);

  return ds.Tables[0];
}


ダミーデータを使ってみる

使ってみましょう。
GridViewのDataSourceにセットして、DataBindすれば。
string dummyXml = Path.Combine(this.Server.MapPath("dummy_cgi.xml"));

GridView1.DataSource = this.LoadDummyData(dummyXml);
GridView1.DataBind();
はい、このとおり。

以上です。

2015/02/20

テンキーを回転させる計算式

このエントリーをはてなブックマークに追加
なんていうか練習問題です。頭の体操と思っていただければいいです。
テンキーというのは、1-9までの数字が、ちょうど5を中心に八方を示す配置ですね。下から123と三つずつ、三列並んでいるやつです。
これをぐるっと90度づつ回転させることを考えてみましょう。
if文を9つ(この場合はswitch文だけど)書いてもいいけど。任意のキーnを回転させたとして、計算式で求めてみよう。

右に90度回転させる

右に90度がっと回したとき。
こういうふうにしたい。

計算式
計算式は3掛けて、10でわったあまり。
n=(n * 3) % 10;

180度回転させる

180度回転。反転です。
という感じ。

計算式
計算式は、10引くだけ。
n=10-n;

左に90度回転させる

っていう。

計算式
右に90度回転させて、それを180度回転させると、左に90度回転させたことになる。
n=10-(n*3)%10;

左に90度回転させる(別解)

もしくは、右に回転するときは3掛けたので、その逆算、3でわってあげればいい。
ただし十のくらいが面倒で、3でわれない数字をわれるように十のくらいを補間する必要があります。2桁の数字は、桁のそれぞれの数字を足して3でわれるなら、元の数字も3でわれるという性質があります。

計算式
ごちゃごちゃしますが、下の計算でOKです。(上のほうが簡単ですね)
n = ((2 - (n - 1) % 3) * 10 + n) / 3;

まとめ

ずいぶん前にこういう感じのプログラムを書いたのを、昨日ふと思い出したので書きました。
ものすごく狭いノウハウなので実践で使うことはまずないだろうけれど、頭の体操としての練習課題としては楽しい問題です。
計算式が、こんなんでいいの?っていうくらい簡潔なのがいい。

2015/02/17

[C#]昇順の配列を作る

このエントリーをはてなブックマークに追加
単純に整数の{1,2,3,4,5,6,7...n}までの配列を作るやりかた。
Enumerable.Rangeが便利です。

自力で配列をつくるやりかた

配列の初期化のときに指定しちゃってもいいんだろうけれど。
int[] list = new int[]{1,2,3,4,5,6,7,8,9,10};

自力でやるときは下のようなコードですね。
int[] list = new int[10];
for(int i=0;i<10;i++){
     list[i] = i;
}
別にいいんだけど、なんかなー。ってことで。

Enumerable.Rangeが便利!

Enumerable.Rangeメソッドというのが使えます。
このメソッドはEnumerable.Range(1,10)で戻り値が1~10までを順番に返すIEnumerableができます。
単なるint配列じゃなくて、IEnumerableなので、何やら加工するのにも有用です。

・2倍すると偶数配列になります
Enumerable.Range(1,10).Select(n=> n*2);

2015/02/16

サーバーのプログラムを更新したら「構成にエラーがあります」と言われるとき

このエントリーをはてなブックマークに追加
サーバーを引越したり、運用環境を新しくしたときにありがちかなと。
開発環境ではデバックできるのに、運用環境でこういうエラーになる。

構成にエラーがあります。
認識されない属性"targetFramework"です。


当方の場合、開発環境とサーバープログラムを新しく.Net Framework v4.5に対応させたけれど、サーバー運用環境が.NET Framework v2.0のままになっていたというのが原因でした。
言われれば当たり前のことなのだけど、運用中のサーバーにはあまり気にかけないことと、表示メッセージが何のことを表しているのかわかりにくかったので、備忘録として書いておきます。
ありがちというのは、.Net Frameworkを新しいバージョンへの対応させたときに、プログラムのどっかを触ってしまったのが原因なのかと、そっち方向に懸念してしまうと深い迷宮に入ってしまうのでした。

IISのアプリケーションプールを確認する

IISの設定を確認してみましょう。
うちの環境は、アプリケーションプールが.NET v2.0のままになっていたことが原因でした。もともと2.0で動かしていたWebサービスをプログラムだけ4.5に対応させたわけです。
そりゃ動かないよなあ。
対応したバージョンのものに設定しなおしてやるとうまく動きました。
メッセージの意味は、targetFrameworkという指定が.NET v2.0では認識されないってことだったんですね。
そんだけ!

2015/02/06

[C#]try-catch-finallyの通る順番

このエントリーをはてなブックマークに追加

try-catch-finallyの通る順番

古典的ですが、try-catchの通る順番について検証をしてみました。
catch内でthrowしてもfinallyにいくのか?とか。知ってるけど、言われるとちょっと不安になってしまった。やってみりゃいいじゃん、ということで、やってみた。
もちろん結果は、想定どおり。不信がる必要はありませんでした。
try中にExceptionが発生すると、catch行って、finally実装されてたらそこにいくわけです。そりゃそれ以外の結果だと、納得いかないでしょうよ。
ソースコード
// 二重のtry-catchにて、奥のcatch内にてthrowしてもfinallyを通る順番に変化はないのかの検証
Console.WriteLine("0");
try {
    Console.WriteLine("1");

    try {
        Console.WriteLine("2");
        throw new Exception(""); // ここでthrow入ります
    } catch (Exception ex) {
        Console.WriteLine("3");
    throw ex;
    } finally {
        Console.WriteLine("4");
    }

} catch (Exception ex) {
    Console.WriteLine("5");
} finally {
    Console.WriteLine("6");
}
Console.WriteLine("7");
出力結果









はい、安心です。
出力結果は、予想通り。ちゃんと動いてくれてます。

yield returnと組み合わせたときのfinallyの呼び出し

おまけにyield returnと組み合わせたときのfinallyの呼び出しってどうなんだろうと。yield returnは呼び出し時に実行される遅延実行なので、打ち切られたときとかもちゃんと呼ばれるのかと。
これもめんどくさそうですが気にしたほうがよさそうです。

ソースコード
private void button1_Click(object sender, EventArgs e) {
    Console.WriteLine("0");

    IEnumerable<int> en = this.Hoge();
    Console.WriteLine("1");

    foreach (int i in en) {
        if (i == 0) {
            Console.WriteLine("3");
        } else if (i == 1) {
            Console.WriteLine("5");
        }
    }
    Console.WriteLine("7");
}

private IEnumerable<int> Hoge() {
    try {
        Console.WriteLine("2");
        yield return 0;

        Console.WriteLine("4");
        yield return 1;

    }finally{
        Console.WriteLine("6 呼ばれた!"); // これがいつ呼ばれるのか?
    }
}

実行結果






6 呼ばれた!


はい、こんな感じですね。3のところでreturnしちゃっても、そのあとちゃんと6が呼ばれます。