業務のためのC#・C言語・C++学習

主にC#の文法やWPF周りのアウトプットに利用してます。

初めて学ぶC/C++

C#を業務で回路の制御にC#を利用していました。これに加えC言語/C++を使う必要が出てきましので、基礎文法からアプリケーション開発までを学習することにしました。私と似たような立場の方の役に立てればと思います。

 

学習計画

・環境構築

・基礎文法

Atcoderで問題を解く

オブジェクト指向で開発

・何かアプリを作る

・他者のコードを読む

・その他ソフトウェア開発に必要な知識を学ぶ

 

 

環境構築

Windowsで動く2つの環境を用意しました。将来的にはLinuxでの開発をする予定なので、ターミナルでビルドコマンドを手打ちできるVSCode+MinGWをメインに扱っていきます。

Visual Studio(総合環境)

VSCode(コードエディタ)+MinGW(コンパイラ、リンカ)

MINGWの準備:

x86_64-12.2.0-release-posix-sjlj-rt_v10-rev0.7zを選択し解凍

Release Release 12.2.0-rt_v10-rev0 · niXman/mingw-builds-binaries · GitHub

C:\Program Files\mingw64にダウンロードフォルダで解凍されたmingwのフォルダを移行する。これは単純にダウンロードフォルダに解凍したフォルダを置きたくないから。

 

スタート画面にsysdm.cplコマンドをうち、System環境変数のPathを編集する。Pathの編集ではC:\Program Files\mingw64\bin\を追加

基礎文法

目的:

以下の項目を理解する

標準入出力

ビルド

変数と型

演算

条件分岐

繰り返し処理

配列・二次元配列

関数

C言語C++の違い

 

手段 : 

◇「スッキリわかるC言語入門 第2版」

C言語の基礎文法を理解するために利用

●第Ⅰ部 基本構文
第1章 プログラムの書き方
第2章 変数と型
第3章 式と演算子
第4章 条件分岐と繰り返し
第5章 制御構文のバリエーション

●第Ⅱ部 開発をより便利にする機能たち
第6章 構造体
第7章 配列
第8章 関数

 

◇「1週間でC++の基礎が学べる本 」

標準入出力、string、名前空間vectorクラスなどを学習するために利用

私の場合はC#の経験があったので比較的早く理解できました。ただし、問題を解いたりなどのアウトプットしないと定着しない。次節で述べる競技プログラミングAtcoderで問題を解く必要あり。

 

Atcoder

目的 : 

基礎文法のアウトプット

→変数の型、whileとfor文、配列とソート、文字列、2重for文と2次元配列

アルゴリズムの基礎を学ぶ

→全探索、累積和

 

目標 : 

・ABC問題のCまでは解けるようにする。

・レーティングは茶色

*茶色のレベル感は、典型的なアルゴリズムに関する知識を多く持ち、全探索や単純な動的計画法を実装できること。難関大学の理系学部に入学できる程度の数学力や論理的思考力があり、数学的な工夫が必要な問題を正解出来ること。

 

手段:

◇以下の資料を読む

Atcoderなどの競技プログラミングとは何ぞやかについてのまとめ

https://qiita.com/e869120/items/f1c6f98364d1443148b3

 

文法の解説と問題

https://atcoder.jp/contests/APG4b

 

AtCoder Beginner Selection

・ABC問題の内A・B問題をそれぞれ50問解く。余裕があればC問題も解く。~2ヶ月

https://atcoder.jp/contests/abs

B問題までなら高校数学の範囲で解ける。最初は標準入力さえあやしかったが、問題の形式に慣れ正答率はA問題100%, B問題80%ぐらいになった。基礎文法のアウトプットには適切であった。B問題の一部の数学的問題、もしくはC問題以降は動的計画法などのアルゴリズムの理論を学習する必要あり

 

アルゴリズム的思考力が身につく!プログラミングコンテストAtcoder

ただでたらめに問題を解くのではなく、体系的に学習する必要を感じたので採用。問題が分類されている。

 

第3章

整数型整数型、while for文、配列とソート、文字列、二重for文、二次元配列

第4章

計算量



オブジェクト指向で開発

目的:

以下の項目を理解する

クラスとインスタンス

カプセル化

継承

ポリモーフィズム

 

手段 :

・参考資料

1週間でC++の基礎が学べる本 

3日目 クラスとオブジェクト
4日目 コンストラクタとデストラクタ/静的メンバ

5日目 継承とポリモーフィズム

 

実施結果:

フレームワークとライブラリの違い

フレームワークはアプリケーション開発する上で基礎機能を提供する部分であり、開発の土台となります。フレームワークを使用しないアプリケーション開発もありますが、例えばWindowsのデスクトップアプリケーションであれば.NET Frameworkを選択するとそのルールに従って、外観パーツを使うことができアプリケーション開発が可能になります。

 

ライブラリは開発で利用可能な応用機能のことです。例えば数値計算などのデータ処理があります。なくてもアプリケーション開発には困りませんが、あると強力です。

Windowsアプリケーション開発に必要なVisual Studioとframeworkについて

私が思う「Visual Studioフレームワークを使ってWindowsアプリケーション開発するメリット」は簡単にアプリケーション開発が出来る事だと考えます。

 

初めてGUIアプリケーションを作った際に画面にボタンを配置してvisual studioのボタンを押せばビルドの理屈は分からないが、アプリケーションが動作したことを思い出します。この簡単さがとにかく何か作りたいプログラミング初心者にとっては、最大の魅力です。Visual studioを利用しない従来の開発では、コンパイルやリンカを意識する必要があります。。コンピュータの仕組みを理解する上では大切ですが、初学者には大変かもしれません。

 

従来の開発手法

プログラムにはビルドが必要です。ビルドは、C#C言語で記述したソースコードを実行形式のアプリケーションとして利用出来る形にすることです。

ビルドの流れ:

ソースコード→オブジェクトファイル→アプリケーション

exe形式のアプリケーションコンパイラリンカーコードエディターソースコードobjファイル

*1 C/C++言語のビルド

Visual studioを使った現在の開発手法

Visual studioにはビルド機能だけではなく、デバッグ機能もあります。ソースコードに記述ミスがないか確認するデバッガーがあると開発効率が高くなります。

 

exe形式のアプリケーションコンパイラリンカーコードエディターソースコードobjファイルデバッガーVisual Studio

visual studioがあれば、

①コードエディターでソースコードを記述

ソースコードデバッグ

ソースコードコンパイラでオブジェクトファイルを生成

④オブジェクトファイルをリンカで実行ファイルでたるアプリケーションを生成

以上の内、③+④=ビルドが自動実行されます。さらに①と②を人間が作業しやすいような環境を用意してくれてます。したがってvisual studioは総合開発環境と呼ばれています。もしvisual studioがなければ場合は、①~④の作業に苦労します。

 

フレームワーク

ソースコードをビルドすればアプリケーション開発が可能としましたが、実際の現場ではアプリケーションの開発効率を更に上げるためフレームワークを使用することがあります。フレームワークとはOSとやり取りする各種機能を簡素化するアプリケーション開発の土台となるものです。ここでは主にWindows環境でアプリ開発をするためのフレームワークについて解説します。

 

WindowsなどのOSはデスクトップ環境、ファイルシステム、プロセス管理、メモリ管理などの機能を提供してます。元来アプリケーションを開発するというのはOSと会話し、プロセス管理やメモリ管理をすることです。しかし、これらの管理は複雑で実装が難しくなり開発に時間がかかったりバグがでやすくなります。

コンピュータ
OS
例:WindowsLinuxmacOS
アプリケーション
例:メモ帳
アプリケーション
例:自作ゲーム

 

そこで、メモリ管理やプロセス管理を簡素化する便利なプレームワークが導入されようになりました。フレームワークを利用することで、開発者が本当に実装したい部分に集中できるようになりました。

コンピュータ
OS
例:WindowsLinuxmacOS

 

フレームワークの種類

作りたいアプリケーションによって選択するフレームワークは異なります。

以下フレームワークの代表例です。

 

.NET Framework

.NET Frameworkは、windowsデスクトップアプリケーションやwebアプリケーションなどさまざまなアプリケーションが効率よく開発できる仕組みとして用いられる。

 

.NET Frameworkの実行環境はCLRと呼ばれるCPUに依存しない仕組みが搭載されている。従来の開発と比べプロセスやメモリ管理がCLRが請け負うので、開発者の負担が減る。

 

言語はMicrosoftが開発したC#がメインである。

 

ライブラリ/フレームワーク

・基本ライブラリクラス

Windows Forms :Windowsデスクトップアプリケーション開発のためのフレームワーク

WPF:より高級なUIを持つデスクトップアプリケーションのためのフレームワークソースコードの雛形であるMVVMパターンの採用が可能で、更にデバッグがしやすくなる

ASP.NET: webアプリケーション開発用のフレームワーク




.NET Core
.NET Framework 4.6の後継が.NET Coreで呼ばれるフレームワークである。特徴としてLinuxWindowsなどの複数のOSをサポート。ただし、.NET Framewrokの機能を全て継承してるわけではないので注意。

 

 

ASP.NET Core
クロスプラットフォームのWebアプリケーション開発をサポートするASP.NETの最新版。


Xamarin
モバイルアプリケーション開発のためのクロスプラットフォームツール。2024/5にサポート終了。.NET6に統合された。

新型コロナウイルス接触確認アプリ(COCOA) でも利用されましたが、あまり評判は良くないような? 


.NET 5
.NET Coreの進化版で、クロスプラットフォーム開発をさらに強化。.NETの中には.NET Framework が含まれている。


.NET 6
.NET 5の後継で、「.NET Multi-platform App UI」(.NET MAUI)や「Blazor desktop apps」がサポートされ、さらなる強化が行われた。

 

 

まとめ

visual studioを利用する際のビルドやデバッグの概念とソースコードの土台となるOSやフレームワークについて説明しました。

 

【C#】GUIアプリケーションからの外部プログラム呼び出し

GUIアプリケーションから外部の実行可能ファイルを直接呼び出すことは一般的なアプローチです。これにより、ユーザーがアプリケーション内で特定の操作を実行できるようになります。以下は、C#のアプリケーションから外部プログラムを呼び出し、その外部アプリケーションの標準出力をreturnする例です。

        public string RunExternalProgram()
        {

            // 外部プログラムのパス
            string programPath = @"C:\path\External.exe";

            // コマンドライン引数(必要に応じて設定)
            string arguments = "--boot AAA..";

            // 外部プログラムの実行
            ProcessStartInfo startInfo = new ProcessStartInfo(programPath, arguments);
            startInfo.RedirectStandardOutput = true;
            startInfo.UseShellExecute = false;
            startInfo.CreateNoWindow = true;

            Process process = new Process();
            process.StartInfo = startInfo;

            string output = "";
            process.OutputDataReceived += (s, args) => output += args.Data + Environment.NewLine;
            process.Start();
            process.BeginOutputReadLine();

            process.WaitForExit();

            return output;
        }

この例では、RunExternalProgram メソッドが外部プログラムを実行し、その結果を文字列として返す機能 を提供しています。外部プログラムの出力は、process.OutputDataReceived イベントハンドラを使用して受信し、結果を output 変数に追加しています。

GUIアプリケーションが実行されるディレクトリ(カレントディレクトリ)が、外部ファイルが存在するディレクトリと異なる場合

コマンドライン引数で何かしらのファイルを指定している場合、カレントディレクトリが正しくなくエラーが出る可能性があります。カレントディレクトリはGUIアプリケーションを実行している位置になります。したがって外部プログラムが異なるディレクトリの場合は引数で指定したファイルのディレクトリが想定と異なりエラーが起きます。

カレントディレクトリを一時的に変更するプログラムです。

        public string RunExternalProgramChengedDirectory()
        {
            // 現在のカレントディレクトリを保存
            string originalWorkingDirectory = Directory.GetCurrentDirectory();

            try
            {
                // 新しいカレントディレクトリを設定
                string workingDirectory = @"C:\path";
                //カレントディレクトリの変更
                Directory.SetCurrentDirectory(workingDirectory);

                // 外部プログラムのパス
                string programPath = @"C:\path\External.exe";

                // コマンドライン引数(必要に応じて設定)
                string arguments = "--boot AAA..";

                // 外部プログラムの実行
                ProcessStartInfo startInfo = new ProcessStartInfo(programPath, arguments);
                startInfo.RedirectStandardOutput = true;
                startInfo.UseShellExecute = false;
                startInfo.CreateNoWindow = true;

                Process process = new Process();
                process.StartInfo = startInfo;

                string output = "";
                process.OutputDataReceived += (s, args) => output += args.Data + Environment.NewLine;
                process.Start();
                process.BeginOutputReadLine();

                process.WaitForExit();

                return output;
            }
            finally
            {
                // 元のカレントディレクトリに戻す
                Directory.SetCurrentDirectory(originalWorkingDirectory);
            }
        }

上記のコードでは、RunExternalProgramChengedDirectoryメソッド内で一時的にカレントディレクトリを変更し、プログラムを実行しています。実行が終了した後、finally ブロック内で元のカレントディレクトリに戻しています。

この方法を使用すると、外部プログラムの実行時に一時的にカレントディレクトリを変更してファイルが存在するディレクトリに移動し、実行後に元のカレントディレクトリに戻すことができます。

【C#-WPF】MVVMパターンでDataGridを実装する方法

MVVM(Model-View-ViewModel)は、WPFWindows Presentation Foundation)などのXAMLベースのアプリケーション開発でよく使用されるデザインパターンです。MVVMはアプリケーションのロジックとUIを分離し、テスタビリティや保守性を向上させることを目的としています。DataGridの実装においてもMVVMパターンを適用することで、柔軟で拡張可能なコードを実現することができます。

実装するUI

Viewの準備

まずは、DataGridを表示するViewを作成します。これはXAMLファイルとして実装されます。

<!-- MainWindow.xaml -->
<Window x:Class="MVVMDataGridExample.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:MVVMDataGridExample"
        Title="MVVM DataGrid Example" Height="450" Width="800">
    <Grid>
        <DataGrid ItemsSource="{Binding DataItems}" AutoGenerateColumns="False" Margin="10"
                  SelectionMode="Single" CanUserAddRows="False">
            <DataGrid.Columns>
                <DataGridTextColumn Header="項目1" Binding="{Binding Item1}" />
                <DataGridTextColumn Header="項目2" Binding="{Binding Item2}" />
                <DataGridTextColumn Header="項目3" Binding="{Binding Item3}" />
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
</Window>

上記のXAMLコードでは、DataGridのItemsSourceに{Binding DataItems}を設定しています。これにより、ViewModelにあるDataItemsプロパティがDataGridにバインディングされます。

ViewModelクラスの実装

次に、ViewModelクラスを作成します。

using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;

public class Items : INotifyPropertyChanged
{
    // UIに自動更新を行うためのイベント
    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void RaisePropertyChanged([CallerMemberName]string propertyName = null)
    {
        var handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    private string item1;
    private string item2;
    private string item3;

    public string Item1
    {
        get { return item1; }
        set
        {
            if (item1 != value)
            {
                item1 = value;
                RaisePropertyChanged();
            }
        }
    }

    public string Item2
    {
        get { return item2; }
        set
        {
            if (item2 != value)
            {
                item2 = value;
                RaisePropertyChanged();
            }
        }
    }

    public string Item3
    {
        get { return item3; }
        set
        {
            if (item3 != value)
            {
                item3 = value;
                RaisePropertyChanged();
            }
        }
    }
}

public class MainViewModel
{
    public ObservableCollection<Items> DataItems { get; set; } // DataGridにバインディングするリスト

    public MainViewModel()
    {
        DataItems = new ObservableCollection<Items>(); // リストを初期化

        // データをロードしてDataItemsに追加
        DataItems.Add(new Items { Item1 = "000", Item2 = "111", Item3 = "222" });
        DataItems.Add(new Items { Item1 = "aaa", Item2 = "bbb", Item3 = "ccc" });
        DataItems.Add(new Items { Item1 = "AAA", Item2 = "BBB", Item3 = "CCC" });
    }
}

上記のコードでは、ViewModelクラスであるMainViewModelがDataGridのデータを保持するDataItemsプロパティを持っています。ItemsクラスはDataGridに表示する各行のデータを保持し、INotifyPropertyChangedを実装しています。これにより、プロパティが変更されたときにDataGridが自動的に更新されます。

DataGridのDataContextを設定

最後に、MainWindow.xaml.csでViewModelをインスタンス化して、DataGridのDataContextに設定します。

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            var context = new MainViewModel();
            this.DataContext = context;
        }
    }

これで、MVVMパターンでDataGridが実装されました。DataGridはViewModelにバインドされたデータを表示し、ViewModelはビューとデータの間でうまく調整します。これにより、アプリケーションの保守性と拡張性が向上し、より効率的なコードが実現できます。

.NET6で開発するアプリケーションの種類

日本マイクロソフトさんから.NET6によるWindowsデスクトップアプリケーションについてYoutube動画とスライドがあがっています。 Windowsユーザとしては非常に興味深い話です。

BS3 # Visual Studio 2022 と .NET 6 での Windows アプリ開発技術の紹介 | 日本マイクロソフト - YouTube

【BS3】Visual Studio 2022 と .NET 6 での Windows アプリ開発技術の紹介 | PPT

結論

今はWPF使え

要点

NET6では利用可能なUIは以下の3つ
・Win Forms
シンプルな画面を作るには便利だが、HighDPIや複雑なレイアウトを作るのは困難。
WPF
柔軟なレイアウトを作成しやすい(私も賛同)
MVVMの開発パターンが利用可能
・MAUI
AndroidiOSWindowsmacOS対応のクロスプラットフォーム

NET6に含まれていないもの
Windows App SDK
・Win UI
・その他API

Windows APP SDK

次世代のWindowsアプリ開発プラットフォーム
開発途中でまだまだ機能が不十分

【C#-文法】Dictionaryの入れ子

Dictionaryの入れ子を作りその出力を表示する。
入れ子は配列やListで実装することが多いが、あるキーで値を制御したい、あるキーワードだけ値を保存したい場合などにDictionaryの入れ子を利用する。

実装例

            Dictionary<string, Dictionary<string, string>> dicout = new Dictionary<string, Dictionary<string, string>>();

            var dicin = new Dictionary<string, string>();
            dicin.Add("Red", "赤");
            dicin.Add("Blue", "青");
            dicin.Add("Green", "緑");

            dicout.Add("色", dicin);

            //表示
            foreach (var key in dicout.Keys)
            {
                Console.WriteLine($"{key}");
                foreach (var n in dicout[key])
                {
                    Console.WriteLine($"{n.Key} : {n.Value}");
                }
            }
            //結果
            //色
            //Red : 赤
            //Blue : 青
            //Green : 緑