C++ signal関数

#include <iostream>
#include <csignal> // signal関数を含むヘッダ
// シグナルハンドラ関数
void signalHandler(int signal) {
    std::cout << "Interrupt signal (" << signal << ") received." << std::endl;
    // プログラムの終了
    exit(signal);
}
int main() {
    // SIGINTシグナル(Ctrl+C)のハンドラを設定
    signal(SIGINT, signalHandler);
    std::cout << "Waiting for Ctrl+C..." << std::endl;
    // 無限ループ
    while (true) {
        // 何かの処理
    }
    return 0;
}

このプログラムでは、Ctrl+C(SIGINT)シグナルをキャッチし、カスタムのシグナルハンドラ関数 signalHandler() が呼び出されます。その後、プログラムはシグナルハンドラ内で exit() 関数を使用して終了します。

このように、signal() 関数を使用してシグナルを処理することで、プログラムが外部からのシグナルに対して適切に反応できるようになります。

***************************************************

#include <iostream>
#include <windows.h>
// Ctrl+C シグナル(SIGINT)のハンドラ関数
BOOL WINAPI consoleCtrlHandler(DWORD ctrlType) {
    switch (ctrlType) {
        case CTRL_C_EVENT:
            std::cout << "Ctrl+C signal received." << std::endl;
            // ここで処理を行う
            return TRUE;
        case CTRL_BREAK_EVENT:
            std::cout << "Ctrl+Break signal received." << std::endl;
            // ここで処理を行う
            return TRUE;
        default:
            return FALSE;
    }
}
int main() {
    // Ctrl+C シグナル(SIGINT)と Ctrl+Break シグナルのハンドラを設定
    if (!SetConsoleCtrlHandler(consoleCtrlHandler, TRUE)) {
        std::cerr << "Error setting console control handler." << std::endl;
        return 1;
    }
    std::cout << "Waiting for Ctrl+C or Ctrl+Break..." << std::endl;
    // 無限ループ
    while (true) {
        // 何かの処理
    }
    return 0;
}

このプログラムでは、Windows上でCtrl+CとCtrl+Breakのシグナルを処理する方法を示しています。SetConsoleCtrlHandler() 関数を使用して、コンソールのCtrl+CとCtrl+Breakのシグナルを処理するためのハンドラ関数を登録します。その後、シグナルが発生すると、登録されたハンドラ関数が呼び出されます。

C++ RS-232C通信制御プログラム

指定されたシリアルポート(COM1)を開き、指定されたボーレート(9600bps)で通信を行います。指定されたデータを送信し、受信したデータを取得して表示します。必要に応じてポート名やボーレートを変更してください。
#include <iostream>
#include <Windows.h>
// シリアルポートを開く関数
HANDLE openSerialPort(const char* portName, DWORD baudRate) {
    HANDLE hSerial = CreateFile(portName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
    if (hSerial == INVALID_HANDLE_VALUE) {
        std::cerr << "Failed to open serial port." << std::endl;
        return NULL;
    }
    DCB dcbSerialParams = { 0 };
    dcbSerialParams.DCBlength = sizeof(dcbSerialParams);
    if (!GetCommState(hSerial, &dcbSerialParams)) {
        std::cerr << "Failed to get serial port parameters." << std::endl;
        CloseHandle(hSerial);
        return NULL;
    }
    dcbSerialParams.BaudRate = baudRate;
    dcbSerialParams.ByteSize = 8;
    dcbSerialParams.StopBits = ONESTOPBIT;
    dcbSerialParams.Parity = NOPARITY;
    if (!SetCommState(hSerial, &dcbSerialParams)) {
        std::cerr << "Failed to set serial port parameters." << std::endl;
        CloseHandle(hSerial);
        return NULL;
    }
    COMMTIMEOUTS timeouts = { 0 };
    timeouts.ReadIntervalTimeout = 50;
    timeouts.ReadTotalTimeoutConstant = 50;
    timeouts.ReadTotalTimeoutMultiplier = 10;
    timeouts.WriteTotalTimeoutConstant = 50;
    timeouts.WriteTotalTimeoutMultiplier = 10;
    if (!SetCommTimeouts(hSerial, &timeouts)) {
        std::cerr << "Failed to set serial port timeouts." << std::endl;
        CloseHandle(hSerial);
        return NULL;
    }
    return hSerial;
}
// シリアルポートをクローズする関数
void closeSerialPort(HANDLE hSerial) {
    if (hSerial != INVALID_HANDLE_VALUE) {
        CloseHandle(hSerial);
    }
}
// データを送信する関数
bool sendData(HANDLE hSerial, const char* data, DWORD dataSize) {
    DWORD dwBytesWritten;
    if (!WriteFile(hSerial, data, dataSize, &dwBytesWritten, NULL)) {
        std::cerr << "Failed to write to serial port." << std::endl;
        return false;
    }
    return true;
}
// データを受信する関数
bool receiveData(HANDLE hSerial, char* buffer, DWORD bufferSize) {
    DWORD dwBytesRead;
    if (!ReadFile(hSerial, buffer, bufferSize, &dwBytesRead, NULL)) {
        std::cerr << "Failed to read from serial port." << std::endl;
        return false;
    }
    return true;
}
int main() {
    const char* portName = "COM1";
    const DWORD baudRate = CBR_9600;
    HANDLE hSerial = openSerialPort(portName, baudRate);
    if (hSerial == NULL) {
        std::cerr << "Failed to open serial port." << std::endl;
        return 1;
    }
    const char* sendDataStr = "Hello, RS-232C!";
    if (sendData(hSerial, sendDataStr, strlen(sendDataStr))) {
        std::cout << "Data sent: " << sendDataStr << std::endl;
    }
    char receiveBuffer[256];
    if (receiveData(hSerial, receiveBuffer, sizeof(receiveBuffer))) {
        std::cout << "Data received: " << receiveBuffer << std::endl;
    }
    closeSerialPort(hSerial);
    return 0;
}

日時、日時取得

Visual C++ (VC++) で日付と日時を取得するためには、Windows API の GetSystemTime() 関数を使用します。以下は、この関数を使用して現在の日付と日時を取得するプログラムの例です。

#include <iostream>
#include <Windows.h>

int main() {
    SYSTEMTIME systemTime;

    // 現在のシステム日時を取得
    GetSystemTime(&systemTime);

    // 取得した日時を表示
    std::cout << "Year: " << systemTime.wYear << std::endl;
    std::cout << "Month: " << systemTime.wMonth << std::endl;
    std::cout << "Day: " << systemTime.wDay << std::endl;
    std::cout << "Hour: " << systemTime.wHour << std::endl;
    std::cout << "Minute: " << systemTime.wMinute << std::endl;
    std::cout << "Second: " << systemTime.wSecond << std::endl;

    return 0;
}

#ifdefと#if #defineの違い

#include <stdio.h>
#define DEBUG
#ifdef DEBUG
    printf("DEBUGモードです。\n");
#endif
#define VERSION 2
#if VERSION >= 3
    printf("最新バージョンです。\n");
#else
    printf("古いバージョンです。\n");
#endif
***************************************
#include <stdio.h>
#define DEBUG
#define VERSION 2
#if defined(DEBUG) && VERSION >= 3
    printf("DEBUGモードかつ最新バージョンです。\n");
#elif defined(DEBUG) || VERSION >= 3
    printf("DEBUGモードまたは最新バージョンです。\n");
#else
    printf("通常モードかつ古いバージョンです。\n");
#endif

C++iniファイル読み書き

#include <iostream>
#include <Windows.h>
int main() {
    // INIファイルのパスとセクション、キーを指定
    LPCWSTR iniFilePath = L"C:\\Users\\sannp\\Desktop\\SAMC1\\INI\\COM.ini";
    LPCWSTR section = L"FTE";
    // キーを指定
    //LPCWSTR key1 = L"section1";
    //LPCWSTR key2 = L"section2";
    //LPCWSTR key3 = L"section3";
    LPCWSTR keys[3] = { L"section1", L"section2",  L"section3" };
    //// 書き込む文字列
    //LPCWSTR writeString = L"Hello, World!";
    //// 書き込む文字列のサイズ(バイト単位)
    //DWORD writeSize = static_cast<DWORD>*1;
    //// INIファイルへの書き込み
    //for (int i = 0; i < 3; ++i) {
    //    BOOL writeResult = WritePrivateProfileString(section, key[i], writeString, iniFilePath);
    //    if (writeResult == FALSE) {
    //        std::cerr << "Failed to write to INI file." << std::endl;
    //        return 1;
    //    }
    //}
    // 読み込み用のバッファ
    //wchar_t buf1[256];
    //wchar_t buf2[256];
    //wchar_t buf3[256];
    wchar_t buf[256];
    for (int i = 0; i < 3; ++i) {
        // INIファイルからデータを取得
        DWORD bytesRead = GetPrivateProfileString(section, keys[i], NULL, buf, sizeof(buf) / sizeof(wchar_t), iniFilePath);
        // 取得したデータを表示
        if (bytesRead > 0) {
            std::wcout << "Data read from " << keys[i] << ": " << buf << std::endl;
        }
    }
    //// INIファイルからデータを取得
    //DWORD bytesRead1 = GetPrivateProfileString(section, key1, NULL, buf1, sizeof(buf1) / sizeof(wchar_t), iniFilePath);
    //DWORD bytesRead2 = GetPrivateProfileString(section, key2, NULL, buf2, sizeof(buf2) / sizeof(wchar_t), iniFilePath);
    //DWORD bytesRead3 = GetPrivateProfileString(section, key3, NULL, buf3, sizeof(buf3) / sizeof(wchar_t), iniFilePath);
    //// 取得したデータを表示
    //if (bytesRead1 > 0) {
    //    std::wcout << "Data read from " << key1 << ": " << buf1 << std::endl;
    //}
    //if (bytesRead2 > 0) {
    //    std::wcout << "Data read from " << key2 << ": " << buf2 << std::endl;
    //}
    //if (bytesRead3 > 0) {
    //    std::wcout << "Data read from " << key3 << ": " << buf3 << std::endl;
    //}
    return 0;
}

*1:wcslen(writeString) + 1) * sizeof(wchar_t

C++ visa通信

#include <visa.h> // Keysight IOライブラリ・スイートのヘッダーファイル

#include <iostream>
#include <string>

int main() {
    ViSession defaultRM, instr;
    ViStatus status;
    ViChar buffer[256];

    // VISAデバイスの初期化
    status = viOpenDefaultRM(&defaultRM);
    if (status < VI_SUCCESS) {
        std::cerr << "Error opening VISA Resource Manager" << std::endl;
        return 1;
    }

    // VISAデバイスのオープン
    status = viOpen(defaultRM, "USB0::0x1234::0x5678::INSTR", VI_NULL, VI_NULL, &instr);
    if (status < VI_SUCCESS) {
        std::cerr << "Error opening device" << std::endl;
        return 1;
    }

    // VISAデバイスにクエリを送信して応答を取得
    status = viQueryf(instr, "*IDN?", "%t", buffer);
    if (status < VI_SUCCESS) {
        std::cerr << "Error querying device" << std::endl;
        return 1;
    }

    // 応答を表示
    std::cout << "Instrument ID: " << buffer << std::endl;

    // VISAデバイスのクローズ
    viClose(instr);
    viClose(defaultRM);

    return 0;
}

C++関連その3

コンソールサイズ設定

consol_size_set(800, 600);

int consol_size_set(short int x, short int y) {
// コンソールウィンドウのハンドルを取得
HWND console = GetConsoleWindow();
if (console == NULL) {
return 1; // エラー処理
}
 
// ウィンドウのサイズを設定
RECT rect;
GetWindowRect(console, &rect);
MoveWindow(console, rect.left, rect.top, x, y, TRUE);
 
// コンソールウィンドウをアクティブにする
SetForegroundWindow(console);
 
return 0;
}
------------------------------------------------------

C++標準ライブラリには、initgraph() という関数は含まれていません。initgraph() 関数は、古いBorland Graphics Interface (BGI) ライブラリで提供されていました。この関数は、グラフィカルな画面の初期化や描画環境の設定を行うために使用されました。

BGI ライブラリは、Turbo C++Borland C++ 等の古いC++コンパイラで使用されていましたが、現代のC++開発においては非推奨とされています。代わりに、より現代的なグラフィックスライブラリやフレームワークを使用することが一般的です。例えば、SFMLやOpenGLなどがあります。

------------------------------------------------------

textmode(C8025) のような形式の関数呼び出しは、古いMS-DOSBorland C++の環境で使用されていたものです。この関数は、グラフィックスモードに切り替えるために使用されました。C8025 は、特定のグラフィックスモードを指定していますが、異なる環境では異なる値になります。

具体的には、C8025 がどのようなグラフィックスモードを表しているかは、使用している環境やコンパイラによって異なります。そのため、このコードは環境依存であり、一般的なC++のコードではありません。

************************************************************

free() 関数は、動的に割り当てられたメモリ領域を解放するための関数です。PortInfo[PortNo].RecBuffer がポインタであり、その指すメモリ領域を解放します。

以下は、free() 関数の使用例です。

#include <cstdlib>

// メモリの割り当て
PortInfo[PortNo].RecBuffer = (char*)malloc(100); // 例として100バイトを割り当てたとします

// 割り当てたメモリ領域の使用

// メモリの解放
free(PortInfo[PortNo].RecBuffer);

この例では、malloc() 関数を使用して100バイトのメモリを動的に割り当てています。その後、そのメモリを使用した後に free() 関数を使用してメモリを解放しています。メモリを解放することで、その領域を他の目的に再利用できるようになります。

************************************************************

segread() は、古いMS-DOS環境で使用されていた関数の一つです。この関数は、セグメントレジスタの値を取得するために使用されました。

具体的には、segread() 関数は、セグメントレジスタの値を取得し、それを構造体に格納します。この構造体は SREGS と呼ばれ、以下のような定義があります。

struct SREGS {
    unsigned int es;
    unsigned int cs;
    unsigned int ss;
    unsigned int ds;
};

segread() 関数は、この構造体を引数として受け取り、セグメントレジスタ escsssds のそれぞれの値を設定します。

しかし、これらのセグメントレジスタの値を直接取得する必要がない場合は、現代のC++開発では通常使用されません。代わりに、OS固有のAPIやライブラリを使用して、必要な情報を取得することが一般的です。

以下は、Windows環境での例です。Windows APIGetThreadSelectorEntry() 関数を使用して、指定されたセグメントレジスタの情報を取得することができます。

#include <windows.h>

void getSegmentRegisters() {
    // セグメントレジスタの値を格納するための変数
    LDT_ENTRY entry;

    // DSレジスタの情報を取得
    GetThreadSelectorEntry(GetCurrentThread(), static_cast<DWORD>(__readfsbase()), &entry);

    // セグメントレジスタの情報を使用する
    unsigned int dsValue = entry.BaseLow | (entry.HighWord.Bytes.BaseMid << 16) | (entry.HighWord.Bytes.BaseHi << 24);
    // dsValue に DSレジスタの値が格納される
}

この例では、GetThreadSelectorEntry() 関数を使用して、現在のスレッドのセグメントレジスタの情報を取得しています。この方法で、セグメントレジスタの値を取得することができます。ただし、各セグメントレジスタに関する情報を取得するためには、適切な引数を指定する必要があります(例えば、GetCurrentThread()__readfsbase() を使用して、DSレジスタの情報を取得しています)。

************************************************************

registerbgidriver() 関数は、BGI (Borland Graphics Interface) ライブラリで使用される関数であり、特定のデバイスドライバを登録するために使用されました。しかし、BGI ライブラリは古いものであり、現代のC++開発にはあまり使用されません。

#include <graphics.h>

int registerbgidriver(void (*driver)(void));

registerbgidriver を使用すると、ユーザーはドライバー ファイルをロードし、ドライバーを「登録」できます。メモリの場所が registerbgidriver に渡されると、initgraph は登録されたドライバーを使用します。ユーザー登録ドライバーは、ディスクからヒープにロードすることも、.OBJ ファイルに変換して (BGIOBJ.EXE を使用)、.EXE にリンクすることもできます。

registerbgidriver を呼び出すと、driver が指すドライバーがリンク時に組み込まれたことがグラフィック システムに通知されます。このルーチンは、指定されたドライバーのリンクされたコードをチェックします。コードが有効な場合は、そのコードを内部テーブルに登録します。

registerbgidriver の呼び出しでリンクされたドライバーの名前を使用すると、そのパブリック名を使用してオブジェクト ファイルにリンクするようにコンパイラー (およびリンカー) に指示することもできます。

************************************************************

graphics.h は、古いBorland Graphics Interface (BGI) ライブラリで使用されるヘッダーファイルです。BGI ライブラリは、グラフィカルなアプリケーションを開発するためのツールとして提供されましたが、今日では非推奨となっています。

以下は、一般的に graphics.h ヘッダーファイルで提供される可能性のある機能や定義の例です(これはすべての実装で共通して提供されるわけではありません)。

  1. グラフィックス関連の定数:

    • DETECT: グラフィックスドライバを自動検出するための定数
    • VGA: VGAグラフィックスドライバを指定するための定数
    • EGA: EGAグラフィックスドライバを指定するための定数
    • その他、色や線種などの定数が含まれる場合があります
  2. グラフィックス関連の関数:

    • initgraph(): グラフィックスモードを初期化する関数
    • closegraph(): グラフィックスモードを終了する関数
    • getch(): キー入力を待ち受ける関数
    • putpixel(): ピクセルを描画する関数
    • line(): 直線を描画する関数
    • circle(): 円を描画する関数
    • rectangle(): 矩形を描画する関数
    • その他、描画や入力関連の機能が含まれる場合があります
  3. グラフィックス関連のデータ型:

    • struct xycoord: x座標とy座標を持つデータ型
    • struct linesettingstype: 描画する線のスタイルを保持するデータ型
    • その他、色やパターンなどを表すデータ型が含まれる場合があります

これらの機能や定義は、C++の標準ライブラリではなく、Borland Turbo C++などの古いC++コンパイラで提供されるものです。現代のC++開発では、よりモダンなグラフィックスライブラリやフレームワークを使用することが推奨されています。

Visual C++ (VC++) では、古いBorland Graphics Interface (BGI) ライブラリの代わりに、よりモダンで柔軟なグラフィックスライブラリやフレームワークを使用することが推奨されます。以下は、VC++で使える代替としてよく使用されるもののいくつかです。

  1. DirectX: DirectX は、Microsoftが提供するグラフィックスとマルチメディアのAPIです。DirectXを使用することで、ゲームやマルチメディアアプリケーションを開発することができます。特に、DirectX 9以降のバージョンでは、Direct2DやDirect3Dを使用して2Dおよび3Dの描画を行うことができます。

  2. OpenGL: OpenGLは、クロスプラットフォームの3DグラフィックスAPIであり、Windowsでも利用可能です。OpenGLを使用することで、ハードウェアアクセラレーションを利用した高性能な3D描画を行うことができます。さらに、OpenGLは2D描画にも使用することができます。

  3. SFML (Simple and Fast Multimedia Library): SFMLは、C++でゲームやマルチメディアアプリケーションを開発するためのモダンなライブラリです。SFMLは、ウィンドウの管理、グラフィックス描画、音声再生、入力処理など、さまざまな機能を提供します。また、クロスプラットフォームであり、WindowsLinuxmacOSなどで使用することができます。

  4. WinAPI: Windows APIを使用して、ウィンドウやデバイスコンテキストを直接操作することもできます。これにより、Windowsアプリケーションの開発やカスタマイズが可能になりますが、OpenGLやSFMLのようなライブラリを使用することで、より高レベルな抽象化を得ることができます。

  5. ****************************
  6.