fc2ブログ

C#ライブラリリファレンス - コンソール で一文字ずつ読み取る

概要
 コンソールの入力方式には、クックドモードとローモードが存在します。厳密な意味でのローモードはWin32APIを使用する必要がありますが、1文字ずつ読み取る程度の処理ならばC#でも、Console静的クラスにより簡単に実装できます。

日常でたとえると
 厳しく文章を校正する。

使用に適した状況
 ローモードほど自由度はなくてもいいから、1文字単位で処理を行いたい場合。本格的なローモードで、特別なアプリケーションを作るとき以外は、この機能で十分な機能を持つアプリケーションを作れます。

サンプル

/*----------------------------------------------------
 * 
 *  1文字ずつ読み取る。
 *  
 ----------------------------------------------------*/
using System;
using System.Text;

class Sample
{
    static void Main( )
    {
        //@キーが押されるまで文字を入力。
        Console.WriteLine(
            "何か文字列を入力して下さい。" +
            Environment.NewLine +
            "終了するときは半角の@を押して下さい。" );
        char input = ' ';
        var output = new StringBuilder();
        do {
            //※Enterキーを必要としない
            var info = Console.ReadKey();
            input = info.KeyChar;
            output.Append( input );
            Console.Write( input );
        }
        while ( input != '@' );

        //終了の合図を消す。
        output.Remove(
            output.Length - 1,
            1 );

        //入力された文字列を表示。
        Console.WriteLine();
        Console.WriteLine(
            "貴方が入力した文字列は「{0}」ですね。",
            output.ToString() );

        //終了。
        Console.WriteLine( "終了です。Enterキーを押して下さい。" );
        Console.ReadLine();
    }
}


名前空間
 Console静的クラスは、System名前空間に属します。

解説
 以前ローモードの一例として、文字を1文字ずつ読み取り、細かく制御する方法があることを解説しました。非常に細かい単位で制御したい場合、以前解説したようにWin32APIの助けが必要ですが、多くの場面でそこまで細かく制御する必要はありません。
 ちょっとわかりにくいですが、ReadメソッドはEnterキーが必要ですが、ReadKeyメソッドを使用すると、まるでWin32APIで実現するローモードのように、1文字単位で処理ができるようになります。
 1文字単位でキーを読み取れると、高機能なコンソールアプリケーションを作成することが可能になると思います。現在はGUIやWebが当たり前になっていますが、過度な装飾がないコンソールの方が役に立つ場面もあります。それに加え、MVCパターンで実装し、コンソール(CUI)とGUIを2つ用意する手もあります。この方法はテストでも役立つでしょう。

裏話
 以前の記事で、ローモードとしてこの機能を解説しようか迷いましたが、厳密な意味でローモードとは呼べないので、別に解説することにしました。それで、違う記事でC#はモードの違いを意識することなくプログラミングができると表現しました。
スポンサーサイト



テーマ : プログラミング
ジャンル : コンピュータ

C#ライブラリリファレンス番外編 - コンソールで特定のキーが押されたことを知る

概要
 コンソールは、Ctrl+CキーもしくはCtrl+Breakキーで終了することができます。それをイベントして捕捉出来れば終了時の処理を行えます。

日常でたとえると
 特定の社内放送があったら呼んでくれと頼む。きっとおひるごはんの時間を気にしているの。

使用に適した状況
 Ctrl+CキーもしくはCtrl+Breakキーでの終了前に行いたい処理がある場合。

サンプル

/*----------------------------------------------------
 * 
 *  コンソールの終了キーイベントを捕捉する。
 *  
 ----------------------------------------------------*/
using System;
using System.IO;
//コンソールが終了した理由を記録する。
class Sample
{
    static void Main( )
    {
        //終了イベントを捕捉する
        Console.CancelKeyPress += Console_CancelKeyPress;

        //終了
        Console.WriteLine( 
            "コンソールの終了イベントを記録します・・・" );
        Console.ReadLine();
    }

    ////イベントを記録する。
    static void Console_CancelKeyPress( object sender, 
        ConsoleCancelEventArgs e )
    {
        var file = new FileInfo( "log.txt" );
        StreamWriter writer = file.AppendText();
        writer.WriteLine( DateTime.Now.ToString() );
        writer.WriteLine( "終了理由" );
        writer.WriteLine( "{0}が押されました。", 
            e.SpecialKey.ToString() );
        writer.WriteLine();
        writer.Close();
    }
}


名前空間
 System名前空間を参照します。

解説
 Win32APIを使用せずにイベントを捕捉したい場合、コンソール静的クラスのイベントを活用すれば、数あるイベントの一部だけ補足することができます。おそらく、C++での開発経験が人は、物足りなく感じると思いますが、コンソールをメインで使用する事はないので、これで十分なのかもしれません。

テーマ : プログラミング
ジャンル : コンピュータ

C#ライブラリリファレンス番外編 - コンソールの終了理由を知る

概要
 SetConsoleCtrlHandler関数を使用すれば、コンソールが終了するときに発生するイベントを捕捉することができます。

日常でたとえると
 帰るときに知らせてと部下に言う。

使用に適した状況
 終了前にやりたい処理がある場合。例えば、「本当に終了しますか?」とユーザーに尋ねたり、「データを記録しますか?」と尋ねたりします。これは、よくある処理だと思います。

サンプル

/*----------------------------------------------------
 * 
 *  コンソールの各種終了イベントを捕捉する。
 *  
 ----------------------------------------------------*/
using System;
using System.IO;
using System.Runtime.InteropServices;

//どの方法で終了したか。
enum ConsoleEventType
{
    CTRL_C_EVENT = 0,
    CTRL_BREAK_EVENT = 1,
    CTRL_CLOSE_EVENT = 2,
    CTRL_LOGOFF_EVENT = 5,
    CTRL_SHUTDOWN_EVENT = 6
}

//コンソールが終了した理由を記録する。
class Sample
{
    //コントロールイベントのハンドラ関数リストに
    //指定した関数を追加する。
    delegate bool Callback( int ctrlChar );
    [DllImport( "kernel32.dll" )]
    static extern bool SetConsoleCtrlHandler(
        Callback handlerRoutine,
        bool add );

    //イベントを記録する。
    static bool HandlerFunc( int dwCtrlType )
    {
        var file = new FileInfo( "log.txt" );
        StreamWriter writer = file.AppendText();
        writer.WriteLine( DateTime.Now.ToString() );
        writer.WriteLine( "終了理由" );
        switch ( ( ConsoleEventType ) dwCtrlType ) {
            case ConsoleEventType.CTRL_C_EVENT:
                writer.WriteLine( "Ctrl + C キーが押されました。" );
                break;
            case ConsoleEventType.CTRL_BREAK_EVENT:
                writer.WriteLine( "Ctrl + Break キーが押されました。" );
                break;
            case ConsoleEventType.CTRL_CLOSE_EVENT:
                writer.WriteLine( "コンソールが閉じられました。" );
                break;
            case ConsoleEventType.CTRL_LOGOFF_EVENT:
                writer.WriteLine( "ユーザーがログオフしました。" );
                return false;
            case ConsoleEventType.CTRL_SHUTDOWN_EVENT:
                writer.WriteLine( "コンピュータをシャットダウンしました。" );
                return false;
        }
        writer.WriteLine();
        writer.Close();
        return false;
    }

    static void Main( )
    {
        //終了イベントを捕捉する
        SetConsoleCtrlHandler( HandlerFunc, true );

        //終了
        Console.WriteLine( "コンソールの終了イベントを記録します・・・" );
        Console.ReadLine();
    }
}


名前空間
 System.Runtime.InteropServices名前空間を参照します。

解説
 アプリケーションでよくある処理のうちの一つが、終了前に何らかの処理を行う事です。例えば、編集中のデータを保存したり、誤ってコンソールを閉じるのを防いだりします。そたためには、終了直前のタイミングで、関数を実行する仕組みが必要です。
 C#ではデリゲートを使用し、イベントが起こった際に実行するメソッドを指定することが可能です。通常簡単な文法でできるのですが、低レベルの処理を行いたい場合Win32APIを使用する必要があります。その時は、簡潔な文法を使用できません。
 この記事を読んで、「そんなよくある処理に一々Win32APIを使用せねばならないのか」と疑問に感じた人もいるでしょう。その点は心配無用です。Win32APIほど細かい情報ではありませんが、簡潔に知るすべはあります。そのことに関しては別の記事で解説します。

テーマ : プログラミング
ジャンル : コンピュータ

ニュースを分析17回 - 日本のマスメディアの狂気

 私は日本のマスメディアに狂気を感じるときがあります。その狂気がある限り、信頼性が低く、世の中に対して害になると思えてなりません。そこで、今回はマスメディアの狂気について書くことにしました。
 報道の原則は事実を報道する事です。しかしながら、それは建前であり、本音は儲かれば何をしてもいいと考えているように見えて仕方がありません。というのも、事実をないがしろにし、よく集団ヒステリーを起こし、事実よりもワイドショー化して儲ける事だけを考えていると思えることが何度もありました。
 枚挙にいとまがありませんが、最近では大阪市出直し選挙とSTAP細胞と靖国参拝問題でマスメディアの狂気を感じました。
 大阪市出直し選挙においてマスメディアは、「橋下氏が勝つことが決まっているからつまらない」だとか「つまらないから選挙するだけ無駄だ」と報道し続けました。これは事実ではなく、ワイドショー化して儲けにくいといっているにすぎません。しかしながら、事実の報道であるのならば、橋下氏はもちろんの事、マック赤坂氏といった他の候補者の主張を報道し、真面目に報道するべきです。選挙を面白いとか、面白くないとかで語ること自体がふざけています。選挙をワイドショー化し、日本の政治を低俗化したその罪は大きいです。
 STAP細胞に関する報道に関しても、研究者のプロフィールを明かすというワイドショー化するのに必死でした。そして、問題が発覚すると喜々として叩き出しました。論文に不備があったのは事実でしょうが、STAP細胞の内容も碌に報道せず、ヒステリー化して感情的にたたくだけに徹したのは非常に幼稚です。ワイドショー化したいだけだとこの報道が示していると思えてなりません。
 加えて日本のマスメディアは、誰かを貶めることに躍起になっています。例えば、橋下市長や小泉元総理は「マスメディアを利用した」と書き続けています。しかしながら、思うように人気が下がらないからといって、捨て台詞を吐くなんてことは狂気以外の何物でもありません。事実の報道はどこに行ったのでしょうか?ワイドショー化して事実を捻じ曲げるのはもちろんの事、嘘を報道する会社もあるぐらいですから、日本のマスメディアの低俗ぶりには酷いものです。
 事実を報道するという建前を、本音にするには、冷静に取材し、妄想や邪推ではなく、事実を書き続けるしかないのではないでしょうか?そこ都から考えるに、ワイドショー化は拝金主義がなせる業であり、事実と一番遠いと思うのは私だけでしょうか?
 ただし、日本のマスメディアの全体的な傾向に狂気を感じるといっても、個々の記者や一部の会社は質が高い報道をしています。それら本当の報道精神持つ人たちが大多数になることを私は願っています。その為にするべきことは、待つことではなく、消費者である私たちが、質の良い情報を見極め、質が悪い情報を淘汰していくしかないと思います。
 日本人はよく、自自浄作用などといって、待つことばかりしていますが、本当にするべきなのは待つことではなく、消費者の権利を正しく行使することです。念のために言っておきますが、権利を行使するのとモンスター化するのは別物です。自分の理性と道徳心を磨かねばなりません。狂気を孕んだマスメディア界にした私たち消費者の責任でもあるのです。私たち消費者は、情報の質を見極める目を持たねばなりません。

テーマ : 政治・時事問題
ジャンル : 政治・経済

C#ライブラリリファレンス番外編 - ローモードのコンソール で細かいイベントを監視(C++/CX編)

 C#のライブラリリファレンス(C#ライブラリリファレンス - ローモードのコンソール で細かいイベントを監視 概要)で説明したように、コンソールのローモードを使用し、細かいイベントを得る場合、C#の相互運用機能を使うよりも、C++/CXでライブラリを作成したほうがいいです。C++/CXで作成すると、こんな具合になります・・・

//ヘッダーファイル1
#pragma once
using namespace System;
using namespace System::Runtime::InteropServices;

namespace ConsoleUtility 
{
	enum class EventType;
	ref class ConsoleEvent;

	public ref class ConsoleEventArgs : EventArgs
	{
	public:
		initonly EventType Type;
		initonly ConsoleEvent^ EventData;
		ConsoleEventArgs( ConsoleEvent^ data );
	};

	public ref class ConsoleEventWrap
	{
	public:
		//コンストラクタでモードを記録
		static ConsoleEventWrap( );

		//イベントを読み取る
		static void ReadEvent( );

		//何かのイベント発生を通知するためのイベントハンドラ。
		static event EventHandler< ConsoleEventArgs^ >^ SomeEvent;

	private:
		//標準入力
		static HANDLE stdin;

		//コンソールモード。
		static DWORD inOldMode;

		//現在のコンソールモードを保存する。
		static void SaveMode( );

		//監視用のモードを設定する。
		static void SetNewMode( );

		//レコードの内容をもとにイベントを取得する。
		static ConsoleEvent^ GetEvent( INPUT_RECORD record );

		//モードをもとに戻す。
		static void ResetMode( );

		//イベント発生を通知。
		static void OnSomeEvent( ConsoleEvent^ data );
	};
}

//ヘッダーファイル2
#pragma once
using namespace System;
using namespace System::Runtime::InteropServices;

namespace ConsoleUtility
{
	//コンソールイベントの型
	public enum class EventType
	{
		Key = 1,
		Mouse = 2,
		WindowsBufferSize = 4,
		Menu = 8,
		Focus = 10
	};

	//コンソールのイベント
	public ref class ConsoleEvent abstract
	{
	private:
		EventType _type;
	public:
		ConsoleEvent( EventType type );
		property EventType Type {
			EventType get( );
		}
	};

	//キーボードイベントに使用する共用体。
	[StructLayout( LayoutKind::Explicit )]
	public value struct nChar
	{
	public:
		[FieldOffset( 0 )]
		System::Char UnicodeChar;
		[FieldOffset( 0 )]
		System::Char AsciiChar;
	};

	//キーイベント
	public ref class ConsoleKeyEvent : ConsoleEvent
	{
	private:
		bool _keyDown;
		INT16 _repeatCount;
		INT16 _virtualKeyCode;
		INT16 _virtualScanCode;
		nChar _nChar;
		INT32 _controlKeyState;
	internal:
		ConsoleKeyEvent( KEY_EVENT_RECORD data );
	public:
		property bool KeyDown { 
			bool get( );
		};
		property INT16 RepeatCount {
			INT16 get( );
		};
		property INT16 VirtualKeyCode {
			INT16 get( );
		}
		property INT16 VirtualScanCode
		{
			INT16 get( );
		}
		property nChar Value {
			nChar get( );
		}
		property INT32 ControlKeyState {
			INT32 get( );
		}
	};

	//マウスイベント
	public ref class ConsoleMouseEvent : ConsoleEvent
	{
	private:
		INT16 _x;
		Int16 _y;
		INT32 _buttonState;
		INT32 _controlKeyState;
		INT32 _eventFlags;
	internal:
		ConsoleMouseEvent( MOUSE_EVENT_RECORD data );
	public:
		property INT16 X { 
			INT16 get( );
		}
		property INT16 Y {
			INT16 get( );
		}
		property INT32 ButtonState {
			INT32 get( );
		}
		property INT32 ControlKeyState {
			INT32 get( );
		}
		property INT32 EventFlags {
			INT32 get( );
		}
	};

	//ウィンドウバッファサイズ変更イベント
	public ref class WindowBufferSizeEvent : ConsoleEvent
	{
	private:
		INT16 _x;
		Int16 _y;
	internal:
		WindowBufferSizeEvent( WINDOW_BUFFER_SIZE_RECORD data );
	public:
		property INT16 X {
			INT16 get( );
		}
		property INT16 Y {
			INT16 get( );
		}
	};

	//メニューイベント
	public ref class ConsoleMenuEvent : ConsoleEvent
	{
	private:
		UINT32 _commandId;
	internal:
		ConsoleMenuEvent( MENU_EVENT_RECORD data );
	public:
		property UINT32 CommandId {
			UINT32 get( );
		}
	};

	//フォーカスイベント
	public ref class ConsoleFocusEvent : ConsoleEvent
	{
	private:
		bool _setFocus;
	internal:
		ConsoleFocusEvent( FOCUS_EVENT_RECORD data );
	public:
		property bool SetFocus {
			bool get( );
		}
	};
}

//注目するべき実装
//コンストラクタでモードを記録
static ConsoleEventWrap::ConsoleEventWrap( )
{
	stdin = GetStdHandle( STD_INPUT_HANDLE );
	SaveMode( );
}

//イベントを読み取る
void ConsoleEventWrap::ReadEvent( )
{
	INPUT_RECORD record;
	DWORD bufferSize = 1;
	DWORD count;
	ReadConsoleInput(
		stdin,
		&record,
		bufferSize,
		&count );
	ConsoleEvent^ data = GetEvent( record );
	OnSomeEvent( data );
	ResetMode( );
}

//現在のコンソールモードを保存する。
void ConsoleEventWrap::SaveMode( )
{
	DWORD mode;
	GetConsoleMode( stdin, &mode );
	inOldMode = mode;
}

//監視用のモードを設定する。
void ConsoleEventWrap::SetNewMode( )
{
	DWORD mode = inOldMode |
		ENABLE_WINDOW_INPUT |
		ENABLE_MOUSE_INPUT;
	DWORD inNewMode = mode;
	SetConsoleMode( stdin, inNewMode );
}

//レコードの内容をもとにイベントを取得する。
ConsoleEvent^ ConsoleEventWrap::GetEvent( INPUT_RECORD record )
{
	switch ( record.EventType )
	{
	case KEY_EVENT:
		return gcnew ConsoleKeyEvent( record.Event.KeyEvent );
	case MOUSE_EVENT:
		return gcnew ConsoleMouseEvent( record.Event.MouseEvent );
	case WINDOW_BUFFER_SIZE_EVENT:
		return gcnew WindowBufferSizeEvent(
			record.Event.WindowBufferSizeEvent );
	case MENU_EVENT:
		return gcnew ConsoleMenuEvent(
			record.Event.MenuEvent );
	case FOCUS_EVENT:
		return gcnew ConsoleFocusEvent(
			record.Event.FocusEvent );
	}
	return nullptr;
}

//モードをもとに戻す。
void ConsoleEventWrap::ResetMode( )
{
	SetConsoleMode( stdin, inOldMode );
}

//イベント発生を通知。
void ConsoleEventWrap::OnSomeEvent( ConsoleEvent^ data )
{
	ConsoleEventArgs^ e = gcnew ConsoleEventArgs( data );
	SomeEvent( nullptr, e );
}
※念のために書いておきますが、プログラムが冗長になるのでエラー処理はしていません。

 このプログラムのポイントは、ReadConsoleInput関数と、SetConsoleModeで指定するパラメーターです。この2つの関数を使用する事により、細かなイベントを取得できます。この手の相互運用のプログラムは、難しいというよりも面倒ですが、C#でやることの手間を考えると、C++/CXを使用する方がよいと思います。

テーマ : プログラミング
ジャンル : コンピュータ

C#ライブラリリファレンス - ローモードのコンソール で細かいイベントを監視

概要
 コンソールのローモードを使用すれば、通常では得られないイベントを得ることができます。しかしながら、C#ではC++/CXの力を借りるのが賢明です。

日常でたとえると
 外国に住む専門家の意見を聞きたいから通訳を雇うよ。

使用に適した状況
 コンソールをより細かく制御したい場合に使用します。本格的なアプリケーションの作成に使用します。

サンプル

/*----------------------------------------------------
 * 
 *  コンソールのイベントを確認する。
 *  
 ----------------------------------------------------*/
using System;
using System.Runtime.InteropServices;
using ConsoleUtility;

class Sample
{
    static void Main( )
    {
        //コンソールイベントを確認。
        ConsoleEventWrap.SomeEvent += ConsoleEventWrap_SomeEvent;
        MonitorEvent();
        ConsoleEventWrap.SomeEvent -= ConsoleEventWrap_SomeEvent;

        //終了。
        Console.WriteLine( "終了です。Enterキーを押して下さい。" );
        Console.ReadLine();
    }

    //イベントを監視する。
    private static void MonitorEvent( )
    {
        //@キーが押されるまで文字を入力。
        Console.WriteLine(
            "色々試してください。" +
            Environment.NewLine +
            "終了するときはコンソールを閉じてください。" );
        do {
            ConsoleEventWrap.ReadEvent();
        }
        while ( true );
    }

    //発生したイベントの内容を表示。
    static void ConsoleEventWrap_SomeEvent( 
        object sender, ConsoleEventArgs e )
    {
        switch ( e.EventData.Type ) {
            case EventType.Key:
                ShowEvent( ( ConsoleKeyEvent ) e.EventData );
                break;
            case EventType.Mouse:
                ShowEvent( ( ConsoleMouseEvent ) e.EventData );
                break;
            case EventType.WindowsBufferSize:
                ShowEvent( ( WindowBufferSizeEvent ) e.EventData );
                break;
            case EventType.Menu:
                ShowEvent( ( ConsoleMenuEvent ) e.EventData );
                break;
            case EventType.Focus:
                ShowEvent( ( ConsoleFocusEvent ) e.EventData );
                break;
        }
    }

    static void ShowEvent( ConsoleKeyEvent e )
    {
        Console.WriteLine( "キーボードイベント発生。" );
    }

    static void ShowEvent( ConsoleMouseEvent e )
    {
        Console.WriteLine( "マウスイベント発生。" );
    }

    static void ShowEvent( WindowBufferSizeEvent e )
    {
        Console.WriteLine( "ウィンドウバッファイベント発生。" );
    }

    static void ShowEvent( ConsoleMenuEvent e )
    {
        Console.WriteLine( "メニューイベント発生。" );
    }

    static void ShowEvent( ConsoleFocusEvent e )
    {
        Console.WriteLine( "フォーカスイベント発生。" );
    }
}

このサンプルはC++/CXで作成したライブラリを使用します。そのライブラリについては、長くなるので違う記事で解説します。

名前空間
 C++/CXで作成したライブラリの名前空間を参照します。

解説
 コンソールのローモードを使用すれば、1文字ごとに判別できるといったことにとどまりません。文字通り「生」でコンソールを制御することが可能となります。しかしながら、そこまでする人は想定されていないのか、.NETのライブラリでは用意されていませんので、ネイティブコードも使用できるC++/CXの助けを借りましょう。
 この記事がC#の記事なのか疑問ですが、木になる人がいると思い、C#用の記事を書くことにしました。こうした場面で、Win32APIの力が必要となり、そのネイティブコードの量が多ければ、素直にC++/CXを使用するのが賢明だと思います。

テーマ : プログラミング
ジャンル : コンピュータ

C#ライブラリリファレンス - ローモードのコンソール

概要
 コンソールの入出力モードは大別すると、クックド(cooked)とロー(raw)の2つがあります。C#でローモードを行うにはConsole静的クラスを使用するだけではなく、Win32APIの力を借ります。

日常でたとえると
 今から先生が黒板に書くから板書して。

使用に適した状況
 簡単なアプリケーションを作りたい場合に使用します。GUIが一般的ですが、ちょっとしたアプリケーションならば、コンソールを使用したほうがCUIアプリケーションの方が使い勝手がいいです。
 しかし、CUIだからといって簡単なアプリケーションだけしか作れないわけではありません。ローモードを使用すれば、もっと複雑なアプリケーションを作ることも可能となります。
 クックドモードとは違い、ローモードでデバッグ目的に使用する事はあまりないと思います。

サンプル

/*----------------------------------------------------
 * 
 *  ロー( raw )モードのコンソール
 *  
 ----------------------------------------------------*/
using System;
using System.Text;
using System.Runtime.InteropServices;

class Sample
{
    //標準入力。
    const int STD_INPUT_HANDLE = -10;

    //1文字ごとに出力する。
    const int ENABLE_ECHO_INPUT = 0x0004;

    //ハンドルを取得する。
    [DllImport( "kernel32.dll" )]
    static extern IntPtr GetStdHandle( int inputHandle );

    //現在のコンソールモードを取得する。
    [DllImport( "kernel32.dll" )]
    static extern bool GetConsoleMode(
        IntPtr consoleHandle,
        ref int mode );

    //コンソールモードを設定する。
    [DllImport( "kernel32.dll" )]
    static extern bool SetConsoleMode(
        IntPtr consoleHandle,
        int mode );

    static void Main( )
    {
        //Enterキーが必要にならないように設定する。
        IntPtr consoleHandle = GetStdHandle( STD_INPUT_HANDLE );
        int oldMode = 0;
        GetConsoleMode( consoleHandle, ref oldMode );
        int newMode = ENABLE_ECHO_INPUT;
        SetConsoleMode( consoleHandle, newMode );
        InputOutPut();
        SetConsoleMode( consoleHandle, oldMode );

        //終了。
        Console.WriteLine( "終了です。Enterキーを押して下さい。" );
        Console.ReadLine();
    }

    //Enterキーが必要なのでそのままではローモードにならない。
    private static void InputOutPut( )
    {
        //@キーが押されるまで文字を入力。
        Console.WriteLine(
            "何か文字列を入力して下さい。" +
            Environment.NewLine +
            "終了するときは半角の@を押して下さい。" );
        char input = ' ';
        var output = new StringBuilder();
        do {
            input = Convert.ToChar( Console.Read() );
            output.Append( input );
            Console.Write( input );
        }
        while ( input != '@' );

        //終了の合図を消す。
        output.Remove(
            output.Length - 1,
            1 );

        //入力された文字列を表示。
        Console.WriteLine();
        Console.WriteLine(
            "貴方が入力した文字列は「{0}」ですね。",
            output.ToString() );
    }
}


名前空間
 Console静的クラスが所属している名前空間はSystemです。ローモードの場合、Win32APIの力を借りるためにSystem.Runtime.InteropServices名前空間に属する、DllImport属性も必要となります。

解説
 Unixシステムでは文字入力の2つの方式を、クックド(cooked)ロー(row)と呼んでいました。Windowsでもその習慣を引き継ぎ、コンソールはこの2つの方式に対応しています。Win32APIで細かく指定することができますが、C#(.NET)では2つのモードを意識することがなく使用することができます。しかしながら、その事はプログラマーが覚えておくべきことなので解説します。
 今回解説しているローモードは、1文字ごとに細かく制御します。ロー(raw)とは、生を意味する言葉で、調理せずに生で文字を扱う事を表しています。ローモードではプログラマーがすべてを管理します。今回は紹介していませんが、マウスイベントも補足できるようになります。
 ローモードを使用するうえで重要なAPIは、SetConsoleModeGetConsoleModeGetStdHandleの3つです。これら3つのWin32APIは、.NETで対応していないのでインポートします。もし、他にも細かく制御したいことがあるのであれば、Win32APIのお世話になるでしょう。.NETのライブラリは優れていますが、たまにそういう事もあるので、Win32APIの使用経験が必要となります。
 .NETでは普段は気にすることなく、ConsoleオブジェクトのReadLineもしくはWriteLineを使って、文字列を気軽に読み書きします。ですが、プログラマーが意識して使用するローモードは使用できません。ローモードの性質から言って、それは当然のことだといえるでしょう。

テーマ : プログラミング
ジャンル : コンピュータ

C#ライブラリリファレンス - クックドモードのコンソール

概要
 コンソールの入出力モードは大別すると、クックド(cooked)とロー(raw)の2つがあります。C#でクックドモードを行うにはConsole静的クラスを使用します。

日常でたとえると
 今から先生が黒板に書くから、合図をした後で板書して。

使用に適した状況
 簡単なアプリケーションを作りたい場合に使用します。GUIが一般的ですが、ちょっとしたアプリケーションならば、コンソールを使用したほうがCUIアプリケーションの方が使い勝手がいいです。また、デバッグ目的で使用する事もよくあります。

サンプル

/*----------------------------------------------------
 * 
 *  クックド( cooked )モードのコンソール
 *  
 ----------------------------------------------------*/
using System;

class Sample
{
    static void Main()
    {
        //入力された文字列を取得
        Console.WriteLine( 
            "何か文字列を入力し" +
            "最後にEnterキーを押して下さい。" );
        string inputValue = Console.ReadLine();

        //入力された文字列を表示
        Console.WriteLine( 
            "貴方が入力した文字列は「{0}」ですね。",
            inputValue );

        //終了
        Console.ReadLine();
    }
}


名前空間
 Console静的クラスが所属している名前空間はSystemです。

解説
 Unixシステムでは文字入力の2つの方式を、クックド(cooked)ロー(row)と呼んでいました。Windowsでもその習慣を引き継ぎ、コンソールはこの2つの方式に対応しています。Win32APIで細かく指定することができますが、C#(.NET)では2つのモードを意識することがなく使用することができます。しかしながら、その事はプログラマーが覚えておくべきことなので解説します。
 今回解説しているクックドモードは、調理済みの文字列を扱えます。調理済みとは、一文字ごとに細かく制御する必要がなく、ユーザーが文字列を編集した後Enterキーを押せば返ってくる事を指しています。正しく文字列が「調理済み」なのです。
 先ほど言ったように、.NETでは別段気にすることなく、ConsoleオブジェクトのReadLineもしくはWriteLineを使って、文字列を気軽に読み書きできます。入力方式を意識する事なく使用できるのは便利ですが、知っておくと一味違うアプリケーションが作れるようになります。

テーマ : プログラミング
ジャンル : コンピュータ

中の人の徒然草489 ブログに関する事

 理由はわかりませんが、今年の2月と3月は非常に忙しかったです。それでブログが滞っていました。だけど今は落ち着いてきたので、以前のように毎日ブログを書きます。いや、もしかしたら、溜まっている分、以前よりも多く書くかもしれません。

テーマ : 日記
ジャンル : 日記

ネタつつき209 - コピペ問題から見える知的財産の問題

 こ最近STAP細胞の論文についての報道が過熱していました。それで今回は、コピペ問題について取り上げます。この話題を取り上げた理由は、知的財産をどう扱うべきかについて、深いテーマがそこに潜んでいるからです。これから、コピペと知的財産についての私個人の意見を述べます。
 先ず言いたいのは、毎度のマスメディアがヒステリー状態になってバッシングをしているのは問題外だという事です。あの態度は、日本のマスメディアが、ただ悪口を言いたいだけだと証明している稚拙な行為です。本来大人がするべきことは、その事件を時系列に記述し、知的財産の専門家(弁護士や学者など)がどう考えるのかについてありのままに報道することです。
 私は特許庁から「個人が情報技術に関する発明を出願すること自体愚かなことだ」といわれ、政党から「個人の知的財産を会社が取って何が悪い」と明言されたことがあります。その経験と、システム屋と知的財産は切っても切れない関係なので、よく知的財産について考えていました。
 客観的に考えるために、科学者はどう考えているのか気になったので調べたところ、著名な科学者である武田教授の意見が興味深かったです。彼によると「学問の成果は人類共通の財産」であり、法律に明記されていないリンチはあってはならないとのことでした。なるほど、そういう考えもあるのかと私は思いました。何度も知的財産を略奪された私にはない考えで非常に勉強になりました。
 確かに、人類共通の成果について共有するのは理想的だといえます。その意見そのものは正しいでしょう。しかしながら、商売をしている私としては、完全に納得できない部分もありました。その理由は2つあります。
 一、発明をするのにあたり、時間・お金・労力が必要となります。そのリソースを取り戻すことも許されず、全て無料で他人に搾取され放題になるのは納得がいきません。搾取した人は何のリソースも消費せず、窃盗行為で儲けられるというのは道徳的に考えても納得がいきません。また、技術者/発明者本人の生存ができなくなります。発明者/技術者はただ搾取される存在ではなく、生存権があるはずです。
 二、発明したものはわが子と同じであり、誘拐されるのは納得がいきません。しかも、盗んだ企業は発明の本質を理解していないので、非常に出来が悪くされてしまいます。わが子が誘拐され、悪い別人として育てられるのを許す親がいるでしょうか?
 武田教授が誤解されるのは不本意なので明記しますが、武田教授が発言したきっかけは、あくまでも創意工夫の必要がない冒頭の部分だという点も付け加えておきます。あくまでも法治国家と、学問の共用性について述べたといえるでしょう。
 知的財産問題が複雑なのは、人類発展のための共用性と、商売としての側面が重なっている点にあります。人類発展のためには、個人の権利を放棄してもよい場面があります。しかしながら、発明者の生存権すら脅かすのは問題であり、発明したものを悪用する組織が野放しになるのもまた問題です。その二つの天秤をどのように折衷させるのか非常に難しい問題です。
 私自身、完璧な答えに至っていませんが、現時点の考えを述べます。知的財産は目に見えないからといって盗んでいいものではなく、発明者の権利を守らないとなりません。現状は盗みたい放題であり、法律の不備を正し、窃盗を防ぐ社会的仕組みが必要です。しかしながら、発明者本人も、人類の発展のために利益に関して妥協する高い道徳心が必要です。
 以上で終わりです。日本は技術大国を名乗っておきながら、知的財産について無関心で無法状態なので、真面目に知的財産のあり方について考えていただきたいです。そうすれば、本当の意味で日本は世界一の技術大国になれるでしょう。

テーマ : 政治・時事問題
ジャンル : 政治・経済

プロフィール

インドリ

Author:インドリ
みなさん、はじめまして、
コンニチハ。

ボクは、無限の夢(infinity dream)を持つネタ好きな虹色の鳥インドリ(in dre)です。
色々な情報処理技術を啄ばむから楽しみにしてね。

http://twitter.com/indori
は別人による嫌がらせ行為です。
私とは関係ないので注意して下さい。
次はなりすましブログなどをするかもしれませんが、ここ以外でブログをするつもりがないので、ここ以外にインドリのブログがあったとしても無視してください。


何度言っても分からない人がいるので、ここにコメント欄へ書き込むときの注意事項を書きます。


一、社会人としてのマナーをわきまえましょう。
一、妄想に基づく書き込みを止めてください。
一、暴言の類は書かないで下さい。
一、某誹謗中傷サイトの書き込みは彼らの妄想に基づく書き込みですから無視して、ここへ書き込まないで下さい。
一、コメント書く前に他のコメントよく読んでから行って下さい。
一、言いがかかり等の行為を禁止します。
一、その他常識的に考えて迷惑なコメントはしないで下さい。


以上のルールを守れない人のコメントは削除します。



利用上の注意
ここに紹介してある文章およびプログラムコードは正確であるように心がけておりますが、内容を保証するものではありません。当サイトの内容によって生じた損害については、一切の責任を負いませんので御了承ください。


執筆したCodeZineの記事


【VB.NETで仮想CPUを作ろう】

  1. VB.NETで仮想CPUを作ろう
  2. レジスタの実装
  3. 仮想CPUのGUI化
  4. テストドライバの改良
  5. CPUの基礎動作の実装
  6. MOV命令の実装
  7. ADD命令実装
  8. SUB命令実装
  9. INC命令&DEC命令の実装と命令長
  10. MLU命令の実装とModR/Mについて
  11. DIV命令の実装とイベント設計について
  12. 機械語駆動式 関数電卓を作ろう!
  13. 機械語駆動式 関数電卓を作ろう! 解答編(前半)
  14. 機械語駆動式 関数電卓を作ろう! 解答編(後半)


【仮想ネットワーク実装でTCP/IPを学ぼう】
  1. TCP/IPの基礎と勘所
  2. ネットワークアクセス層の勘所
  3. インターネット層の勘所
  4. トランスポート層の勘所
  5. アプリケーション層の勘所
  6. セキュリティの基礎と仮想ネットワークの仕様
  7. GDI+と独自プロトコルの定義



【並列化】
インテル Parallel Studioを使って並列化プログラミングを試してみた
並列プログラミングの効率的なデバッグを実現する「Parallel Inspector」


【TBBシリーズ】
  1. インテル スレッディング・ビルディング・ブロックの概要
  2. インテルTBBから学ぶループの並列化
  3. スレッドセーフとインテルTBBのコンテナ
  4. インテルTBBのスレッドクラス


【OpenMPシリーズ】
  1. OpenMPの基礎構文
  2. OpenMPの実行時ライブラリと並列ループ
  3. OpenMPのメモリモデルとfork- joinモデル

最近の記事
最近のコメント
月別アーカイブ
カテゴリ
Ada (9)
COBOL (5)
C (9)
C++ (11)
C# (370)
D (25)
Java (8)
Perl (1)
Ruby (14)
PHP (2)
Boo (2)
Cobra (2)
LISP (6)
F# (33)
HTML (0)
XHTML (0)
CSS (0)
XML (0)
XSLT (0)
Scala (4)
WPF (0)
WF (2)
WCF (0)
LINQ (4)
MONO (5)
Linux (0)
MySQL (0)
ブログ内検索
リンク
最近のトラックバック
RSSフィード
ブロとも申請フォーム

この人とブロともになる

QRコード
FC2カウンター