見出し画像

M5Stack プログラミングメモ 集

わからなくて、調べたことを、随時、追記していきます。


1.std::vectorクラス

C++の標準テンプレートライブラリ (STL) に含まれる動的配列を実現するためのクラス。

template<typename _Tp, typename _Alloc = std::allocator<_Tp> >
    class vector : protected _Vector_base<_Tp, _Alloc>
    {
#ifdef _GLIBCXX_CONCEPT_CHECKS
      // Concept requirements.
      typedef typename _Alloc::value_type		_Alloc_value_type;
# if __cplusplus < 201103L

テンプレートパラメータ

@tparam _Tp  Type of element.(std::vector が格納する要素の型)
@tparam _Alloc  Allocator type, defaults to allocator<_Tp>.(アロケータの型)アロケータはメモリの確保と解放を行う役割。

規定クラス:_Vector_base

 実際の要素を保持し、メモリの確保と解放を担当するクラス

std::vectorクラスで動的配列
#include <M5Core2.h>

void writeVectorData();
//vectorクラス
std::vector<String> texts;

void setup() 
{
  int i;
  M5.begin();

  //vectorクラスに要素を追加
  texts.push_back("YOKOHAMA");
  texts.push_back("HAMAMATSU");
  texts.push_back("SENDAI");
  texts.push_back("NAGOYA");
  texts.push_back("HAKATA");
  texts.push_back("SAPPORO");

  // サイズの取得
  size_t vsize = texts.size();
  M5.Lcd.setTextColor(TFT_CYAN);
  M5.Lcd.setTextSize(2);
  M5.Lcd.println("std::vector Class Test");
  M5.Lcd.setTextColor(TFT_BLUE);
  M5.Lcd.printf("Vector Size:%d\r\n",vsize);
  M5.Lcd.setTextColor(TFT_GREENYELLOW);
  M5.Lcd.println("------------------");
  //要素の表示
  for(i=0; i<vsize; i++)
  {
    String str = texts[i];
    M5.Lcd.printf("%s\n\r",str);
  }
}

//グローバル変数にstaticを付けるとファイル内のみで参照。
static bool repaint;
void loop() 
{
  
  if(repaint)
    writeVectorData();
    
  M5.update();

  if(M5.BtnA.isPressed())
  {
    texts.clear();
    M5.Lcd.clear();
    delay(200);
    repaint=true;
  }

  if(M5.BtnB.isPressed())
  {
    //vectorクラスに要素を追加
    texts.push_back("YOKOHAMA");
    texts.push_back("HAMAMATSU");
    texts.push_back("SENDAI");
    texts.push_back("NAGOYA");
    texts.push_back("HAKATA");
    texts.push_back("SAPPORO");
    M5.Lcd.clear();
    delay(200);
    repaint=true;
  }

  delay(10);
}

void writeVectorData()
{
  repaint=false;
  // サイズの取得
  size_t vsize = texts.size();
  M5.Lcd.setCursor(0,0);
  M5.Lcd.setTextColor(TFT_CYAN);
  M5.Lcd.setTextSize(2);
  M5.Lcd.println("std::vector Class Test");
  M5.Lcd.setTextColor(TFT_BLUE);
  M5.Lcd.printf("Vector Size:%d\r\n",vsize);
  M5.Lcd.setTextColor(TFT_GREENYELLOW);
  M5.Lcd.println("------------------");
  //要素の表示
  for(int i=0; i<vsize; i++)
  {
    String str = texts[i];
    M5.Lcd.printf("%s\n\r",str);
  }
  if(vsize==0)
  {
    M5.Lcd.println("none");
  }
}

std::vector 主なメソッド

要素の追加:
push_back(const T& value)
: ベクターの最後に要素を追加します。
要素の削除:
pop_back(): ベクターの最後の要素を削除します。
erase(iterator position): 指定された位置の要素を削除します。
要素の大きさ:size()

2.Stringクラスとprintf("%s",str)の扱い。

printf("%s", str)のstrは”char型の配列”である必要があります。なので、Stringクラスのインスタンスをそのまま渡すことはできません。Stringクラスのインスタンスをchar型の配列に変換する方法として、c_str()メソッドを使用することができます。c_str()メソッドは、Stringクラスインスタンスのポインタを返します。

変換指定子%s
文字列へのポインタを実引数に指定し、null文字が出現する直前まで表示
null,空文字はASCIIコードでは、0x00で表現されます。

void loop() {
  String myString = "Hello";
  SerialBT.printf("%s", myString.c_str());
  delay(500);
}

3.Stringクラス 文字列の中から特定の文字を指定して、インデックスを取得し、文字列を抽出する。

char charAt(unsigned int index) const;

 charAtメソッドを使って特定文字の位置番号を取得します。これを使って、文字列の抽出に応用します。

/// @brief 文字列で特定文字のインデックスを見つける
/// @param str 走査文字列
/// @param target 検索文字
/// @return 
int findIndex(const String &str, char target) 
{
  int len = str.length();

  for (int i = 0; i < len; ++i) {
    if (str.charAt(i) == target) {
      return i; // インデックスが見つかればその位置を返す
    }
  }

  return -1; // インデックスが見つからなければ-1を返す
}

String substring(unsigned int beginIndex, unsigned int endIndex) const;

オーバーライド
String substring(unsigned int beginIndex) const { return substring(beginIndex, len());}

先ほどのfindIndex関数とsubstringを組み合わせて、目的の文字列を取り出します。

String str="24/01/16D 13:54:31T TueX\n"
int i = findIndex(str, 'D');
String Str1 = str.substring(0,n);   //先頭から、n番目までで文字列を抽出。24/01/16
int  j = findIndex(str, 'T');
String Str2 = str.substring(n+1,j); //n+1番目からj番目まで抽出。13:54:31
int  k = fineIndex(str, 'X'); 
String Str3 = str.substring(j+1,k); //j+1番目からk番目まで抽出。Thu

※Stringクラスには、indexOfメソッドもある。

4.Stringクラスインスタンスをbyte列に変換する。

// StringをUTF-8エンコーディングのバイト列に変換
byte* byteArray = (byte*)myString.c_str();

// バイト列の内容を表示
for (int i = 0; i < myString.length(); i++) {
  Serial.print(byteArray[i]);
  Serial.print(" ");
}

5.String::c_strの振る舞い

Stringインスタンスの長さ+1のメモリを確保したのちに、文字列をコピーする。そのあと、’¥0’を最後尾に追加する。
考えられる実装

const char* String::c_str() const {
  // 文字列の長さを取得
  size_t len = this->length();
  // ヌル文字を含むバッファを確保
  char* buffer = new char[len + 1];
  // 文字列をバッファにコピー
  std::copy(this->begin(), this->end(), buffer);
  // バッファの最後にヌル文字を追加
  buffer[len] = '\0';
  // バッファのポインタを返す
  return buffer;
}

この記事が気に入ったらサポートをしてみませんか?