C++ Builder / String > 文字列の脱落をするクラス


動作環境
C++ Builder XE4

関連 http://qiita.com/7of9/items/8e433c6d0f7a9b2fe373

UDP通信でのパケットロスを再現してパケットロス対策を実装しようとしている。

パケットロスを発生させるクラスをStatic関数で実装してみた。

code

UtilStringDropout.h
//---------------------------------------------------------------------------

#ifndef UtilStringDropoutH
#define UtilStringDropoutH
//---------------------------------------------------------------------------

#include <System.hpp> // for String

/*
Stringを意図的に脱落させるためのクラス。
UDP通信時などでのパケットロスを再現するために使う。
*/

class CUtilStringDropout
{
private:
public:
    static String __fastcall GetStringAfterDrop(String srcStr, float dropout_rate, int dropout_chars);
    /**
     *  @param [dropout_rate] 関数コール時に何回に1回dropoutを発生させるか [0.0 - 1.0]
     *  @param [dropout_chars] dropout時の脱落文字数
     */
};

#endif
UtilStringDropout.cpp
//---------------------------------------------------------------------------

#pragma hdrstop

#include <vcl.h>
#include "UtilStringDropout.h"

//---------------------------------------------------------------------------
#pragma package(smart_init)

/*
v0.1 2017/02/08
    - GetStringAfterDrop()実装
*/

//---------------------------------------------------------------------------
// public関数
//
/*static*/String __fastcall CUtilStringDropout::GetStringAfterDrop(String srcStr, float dropout_rate, int dropout_chars)
{
    double rnd = Random(); // 0.0 to 1.0

    if (rnd >= dropout_rate) {
        return srcStr;
    }

    String wrk = srcStr;
    for(int loop=0; loop < dropout_chars; loop++) {
        int pos = Random(wrk.Length());
        wrk.Delete(pos, /* count=*/1);
    }

    return wrk;
}

利用例

TMemoとTTimerを持つフォーム。

Unit1.cpp
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
#include "UtilStringDropout.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
    Memo1->Clear();
    Timer1->Interval = 1000; /* msec */
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
    String rcvd = L"123456789ABCDEF";

    rcvd = CUtilStringDropout::GetStringAfterDrop(rcvd, /* dropout_rate=*/0.3, /*dropout_chars=*/5);

    Memo1->Lines->Add(DateTimeToStr(Now()) + L":" + rcvd);
}
//---------------------------------------------------------------------------

実行例

補足

@tenmyo さんのコメントなどから考えて、UDPの通信の脱落は上記の状況とは異なるかもしれない。

また、過去に自分が調べていた記事が見つかった。
http://qiita.com/7of9/items/7b980d262bf600d35cea

自分が遭遇している問題は、パケット単位の破棄が発生しているようだ。