2014年05月28日

C#で16進数から10進数の変換

   このエントリーをはてなブックマークに追加 Clip to Evernote
どう書く?orgに感謝を込めて」シリーズ その11

■問題 (出題者:shojiHIDAKA さん)

16進数を10進数に変換してください。
ただし、入出力は文字列とし、次の変換は最低必ずできなければいけないこととします。
0x12437308CCB6 →20080902065334
0x2C9C1227FC6520B →200904012311450123
あわせて、扱える最大の整数も明らかにしてください。

Convertクラスを使えば簡単ですね。
この問題については、クラスライブラリ使わずに書くのは時間の無駄だと判断。 10進から16進に変換するコードも書いています。

■C#で書いたコード
using System;

namespace Doukaku.Org {
    class Program {
        static void Main(string[] args) {

            // Convertクラスを利用
            long num = Convert.ToInt64("0x12437308CCB6", 16);
            Console.WriteLine(num);
            long num2 = Convert.ToInt64("0x2C9C1227FC6520B", 16);
            Console.WriteLine(num2);

            // 先頭の 0x は省略可能
            long num3 = Convert.ToInt64("8000000000000000", 16);
            Console.WriteLine(num3);
            long num4 = Convert.ToInt64("7fffffffffffffff", 16);
            Console.WriteLine(num4);

            // 10進数から16進数への変換も Convertクラスを使う。
            Console.WriteLine(Convert.ToString(20080902065334, 16));
            Console.WriteLine(Convert.ToString(200904012311450123, 16));
            Console.WriteLine(Convert.ToString(long.MinValue, 16));
            Console.WriteLine(Convert.ToString(long.MaxValue, 16));

            Console.ReadKey();
        }
    }
}
  

Posted by gushwell at 22:04Comments(0)TrackBack(0)

2014年05月25日

C#で外部の実行ファイルを呼び出し

   このエントリーをはてなブックマークに追加 Clip to Evernote
どう書く?orgに感謝を込めて」シリーズ その10

■問題 (出題者:ところてん さん)
外部の実行ファイルを呼び出して実行してください。 ただし、実行中にプログラムの実行をブロックする版と、しない版の二つを作ってください。

Processクラスを使えばできますね。それほど難しくありませんね。
RunAndWaitと Runメソッドを作成。Runでは、パラメータ付きで呼び出す例としてみました。

■C#で書いたコード
using System.Diagnostics;
using System;

namespace Doukaku.Org {
    class Program {
        static void Main(string[] args) {
            // mspaint.exeを起動し、終わるまで待つ
            int code = RunAndWait("mspaint.exe");

            // 上のmspaint.exeが終わらないと、次のNotepad.exeは起動しない
            Process p = Run("notepad.exe","a.txt");

            // 直ぐに、Runメソッドから制御が戻る。このプログラムが終了しても、
            // notepad.exeは終わらない。
        }

        // ブロックする版 (終了するまで待って、制御を当プログラムに戻さない)
        static int RunAndWait(string cmd) {
            ProcessStartInfo psi = new ProcessStartInfo(cmd);
            Process process = Process.Start(psi);
            process.WaitForExit();
            return process.ExitCode;
        }

        // ブロックしない版
        static Process Run(string cmd, string param) {
            Process process = new Process();
            process.StartInfo.FileName = cmd;
            process.StartInfo.Arguments = param;
            process.Start();
            return process;
        }
    }
}
  
Posted by gushwell at 22:00Comments(0)TrackBack(0)

2014年05月21日

C#で自分自身のファイル名を知る方法

   このエントリーをはてなブックマークに追加 Clip to Evernote
どう書く?orgに感謝を込めて」シリーズ その9

■問題 (出題者:ところてん さん)
 
自分自身のファイル名を知る方法を示してください。 ビルド後のファイルが、hogehoge.exeであれば、 ”hogehoge.exe”が表示されるようなプログラムを書いてください。 スクリプト言語でも同様です。 ファイル名が変更されたらそれに追従するようにしてください。

いくつかの方法を書いてみました。 「自分自身のファイル名」という意味合いでは、最後の例が一番合ってるかな。


■C#で書いたコード
using System;
using System.Reflection;
using System.Diagnostics;

namespace Doukaku.Org {
    class Program {
        static void Main(string[] args) {
            string path = "";

            // 方法その1
            path = Environment.GetCommandLineArgs()[0];
            Console.WriteLine(path);

            // 方法その2
            path = Process.GetCurrentProcess().MainModule.FileName;
            Console.WriteLine(path);

            // 方法その3 (若干意味合いが異なる)
            path = Assembly.GetEntryAssembly().Location;
            Console.WriteLine(path);

            // 実行中のメソッドがあるアセンブリファイル名を表示する例
            path = Assembly.GetExecutingAssembly().Location;
            Console.WriteLine(path);
         }
   }
}
  
Posted by gushwell at 22:30Comments(0)TrackBack(0)

2014年05月18日

C#でミリ秒まで含んだ時刻文字列を生成

   このエントリーをはてなブックマークに追加 Clip to Evernote
どう書く?orgに感謝を込めて」シリーズ その8

■問題 (出題者:znzさん)
YYYY年mm月dd日HH時MM分SS.xxx秒なら、「YYYYmmddHHMMSS.xxx」のようにミリ秒まで含んだ文字列を返すプログラムを書いてください。

書式設定って、時分秒までは覚えていても、ミリ秒(fff)までは覚えてないです (^^;

■C#で書いたコード
using System;

namespace Doukaku.Org {
    class Program {
        static void Main(string[] args) {
            Console.WriteLine(GetDateString(DateTime.Now));
        }

        static string GetDateString(DateTime date) {
            return date.ToString("yyyyMMddHHmmss.fff");
        }
    }
}
  
Posted by gushwell at 22:30Comments(0)TrackBack(0)

2014年05月15日

C#でXMLから情報を取り出す

   このエントリーをはてなブックマークに追加 Clip to Evernote
どう書く?orgに感謝を込めて」シリーズ その7


■問題 (出題者:にしお さん) 
指定されたURL「http://ja.doukaku.org/feeds/comments/」をGETするとXML文字列が手に入ります。このXML文字列がすでに入手できてdataという変数に代入されているとします。このdataから、以下のような表記で書き込まれている「更新日時」を取り出すコードを書いてください。 <lastBuildDate>Thu, 12 Jul 2007 09:42:50 -0000</lastBuildDate>

C#で書いたコード
using System.Linq;
using System.Xml.Linq;

namespace Doukaku.Org {
    class Program {
        static void Main(string[] args) {
            XDocument xdoc = XDocument.Load("http://ja.doukaku.org/feeds/comments/");
            xdoc.Save("test.xml");
            var q = xdoc.Root.Descendants()
                .Where(e => e.Name == "lastBuildDate")
                .Select(e => e.Value);
            q.ToList().ForEach(Console.WriteLine);
        }
    }
}
なお、このこのURLには今となってはアクセスできません。 そのため、別のXMLを使うコードも書いてみました。GreatPersons.xml内のName要素を抜き出す サンプルコードです。
using System.Linq;
using System.Xml.Linq;


namespace XMLから情報を取り出す {
    class Program {
        static void Main(string[] args) {
            // Descendants を使って、とりあえず、Nameはすべて取り出す。
            XDocument xdoc = XDocument.Load("GreatPersons.xml");
            var q = xdoc.Root.Descendants()
                .Where(e => e.Name == "Name")
                .Select(e => e.Value);
            q.ToList().ForEach(Console.WriteLine);
            Console.ReadLine();

            // Person要素のNameを取り出す。
            var q2 = xdoc.Root.Elements("Person")
                         .Select(e => e.Element("Name").Value);
            q2.ToList().ForEach(Console.WriteLine);
            Console.ReadLine();
        }
    }
}
<?xml version="1.0" encoding="utf-8" ?>
<GreatPersons>
  <Person>
    <Name>坂本竜馬</Name>
    <BirthYear>1835</BirthYear>
  </Person>
  <Person>
    <Name>勝海舟</Name>
    <BirthYear>1823</BirthYear>
  </Person>
</GreatPersons>
  
Posted by gushwell at 22:30Comments(0)TrackBack(0)

2014年05月14日

WindowsXPのシェアは?その後 (当Blogのアクセス解析から)

   このエントリーをはてなブックマークに追加 Clip to Evernote
今年のはじめに、「WindowsXPのシェアは?(当Blogのアクセス解析から)」という記事を投稿しましたが、WindowsXPのサポートが終了して1ヶ月が経過したので、再度このブログのログ解析から調べてみました。

以下、直近一ヶ月のアクセスログの結果です。


WindowsShare



伸びたのは、Windows8.1 と Windows 7 ですね。
Windows XPの利用は確実に減ってますが、でも、まだ 3% は、XP です。
このブログがプログラマ系のブログということを考えれば、一般にはもっとXPの割合は多そうな気がしますね。

   
Posted by gushwell at 21:29Comments(0)TrackBack(0)

2014年05月11日

設定ファイルから値を取得

   このエントリーをはてなブックマークに追加 Clip to Evernote
どう書く?orgに感謝を込めて」シリーズ その6

■問題 (出題者;syat さん) 
設定ファイルから項目名をキーとして値を取得するコードを書いてください。 設定ファイルのイメージも載せてください。 ここで設定ファイルとは、
・項目名と値のペアが書いてあるファイル
・フォーマットはその言語で扱いやすいものでよい
・コードと分離され、コードに影響を与えずに変更が可能
を条件とします。ファイルが難しければ同等のものでもかまいません(テーブル、環境変数など)。


.NETでの標準である configファイルを使ってみました。

■C#で書いたコード
using System;
using System.Configuration;
using System.Collections.Specialized;

namespace Doukaku.Org {
    class Program {

        static void Main(string[] args) {
            NameValueCollection settings = ConfigurationManager.AppSettings;

            // キーを指定して読み込む
            string price = settings["Orange"];
            Console.WriteLine("{0} = {1}", "Orange", price);


            // すべての設定値を読み込む
            foreach (var key in settings.AllKeys)
                Console.WriteLine("{0} = {1}",key , settings[key]);


            // こんな読み込み方法もある AppSettingsReaderクラスを使用
            AppSettingsReader reader = new AppSettingsReader();
            int val = (int)reader.GetValue("Peach", typeof(int));
            Console.WriteLine("{0} = {1}", "Peach", val);
        }
    }
}
  
Posted by gushwell at 22:30Comments(0)TrackBack(0)

2014年05月08日

データの圧縮と展開

   このエントリーをはてなブックマークに追加 Clip to Evernote
どう書く?orgに感謝を込めて」シリーズ その5

■問題 (出題者: 
mattsan さん)
データを圧縮するcompress、展開するdecompressという関数やメソッドなどを書いてください。データはバイト列でもストリームでもそれ以外の形式でもOKです。 圧縮形式は問いませんが、できるだけ一般的なフォーマット(zip,lzhなど)でお願いします。 また、標準以外のライブラリを使う場合には出典の記載をお願いします。 「○○でも実用的な圧縮/展開プログラムがかけるんだぞ!」というのを、ぜひ示してください。

文字列を圧縮、展開するメソッドを作成。 
お題では、一般的なフォーマットとありますが、このコードを書いた当時は、まだ、.NET Framework3.5 だったので、 .NET Framework4.5に追加されたZipArchiveは使ってない。 GZipStream を使ってバイト配列に圧縮。

ZIPファイルについては、メールマガジン「C#プログラミングレッスン」のバックナンバー No.379 を見てください。

■C#で書いたコード 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.IO.Compression;


namespace Doukaku.Org {
    class Program {
        static void Main(string[] args) {
            // 文字列をバイト配列に変換します
            string text = @"ある日の暮方の事である。一人の下人(げにん)が、羅生門(らしょうもん)の下で雨やみを待っていた。
広い門の下には、この男のほかに誰もいない。ただ、所々丹塗(にぬり)の剥(は)げた、大きな円柱(まるばしら)に、蟋蟀(きりぎりす)が一匹とまっている。羅生門が、朱雀大路(すざくおおじ)にある以上は、この男のほかにも、雨やみをする市女笠(いちめがさ)や揉烏帽子(もみえぼし)が、もう二三人はありそうなものである。それが、この男のほかには誰もいない。";

            byte[] destination = Compress(text);
            // 圧縮前と圧縮後の長さを比較します
            //Console.WriteLine(source.Length.ToString() + " vs " + ms.Length.ToString());

            // バイト配列を文字列に変換して表示します
            //Console.WriteLine(Encoding.Unicode.GetString(destination));

            string result = Decompress(destination);
            Console.WriteLine(result);
            Console.ReadLine();
        }

        private static string Decompress(byte[] destination) {
            using (MemoryStream ms = new MemoryStream(destination))
            using (GZipStream gzip = new GZipStream(ms, CompressionMode.Decompress)) {
                StringBuilder sb = new StringBuilder();
                byte[] buff = new byte[4096];
                int length = 0;
                while ((length = gzip.Read(buff, 0, buff.Length)) > 0) {
                    sb.Append(Encoding.Unicode.GetString(buff, 0, length));
                }
                return sb.ToString();
            };
        }

        private static byte[] Compress(string text) {
            byte[] source = Encoding.Unicode.GetBytes(text);

            // 入出力用のストリームを生成します
            using (MemoryStream ms = new MemoryStream())
            using (GZipStream gzip = new GZipStream(ms, CompressionMode.Compress)) {

                // ストリームに圧縮するデータを書き込みます
                gzip.Write(source, 0, source.Length);

                // 圧縮されたデータを バイト配列で取得します
                return ms.ToArray();
            }
        }
    }
}
  
Posted by gushwell at 23:00Comments(0)TrackBack(0)