web-dev-qa-db-ja.com

Arduino(C言語)区切り文字付きの文字列の解析(シリアルインターフェイスを介した入力)

Arduino(C言語)区切り文字付きの文字列の解析(シリアルインターフェイスを介した入力)

ここで答えが見つかりませんでした:/

シリアルインターフェイス(Serial.read())を介してarduinoに、コンマで区切られた3つの数値の単純な文字列を送信したいと思います。これらの3つの数値は、0〜255の範囲にすることができます。

例えば。 255,255,2550,0,01,20,10090,200,3

Arduinoに送信されたこの文字列を3つの整数(r、g、bとしましょう)に解析する必要があります。

だから私が100、50、30を送るとき、arduinoはそれを

int r = 100
int g = 50
int b = 30

私はたくさんのコードを試しましたが、どれもうまくいきませんでした。主な問題は、文字列(文字の束)を整数に変換することです。区切り文字の目的でstrtok_rが存在することを理解しましたが、それで終わりです。

提案をありがとう:)

11
user1461310

あなたが実際に尋ねた質問に答えるために、文字列オブジェクトは非常に強力であり、あなたが尋ねたことを正確に行うことができます。入力から直接解析ルールを制限すると、コードの柔軟性が低下し、再利用性が低下し、少し複雑になります。

文字列には、indexOf()と呼ばれるメソッドがあり、特定の文字の文字列の文字配列でインデックスを検索できます。文字が見つからない場合、メソッドは-1を返します。 2番目のパラメーターを関数呼び出しに追加して、検索の開始点を示すことができます。あなたの場合、区切り文字はコンマなので、次のように呼び出します。

int commaIndex = myString.indexOf(',');
//  Search for the next comma just after the first
int secondCommaIndex = myString.indexOf(',', commaIndex + 1);

次に、そのインデックスを使用して、Stringクラスのsubstring()メソッドを使用してサブストリングを作成できます。これは、特定の開始インデックスで始まり、2番目のインデックス(または、何も指定されていない場合はファイルの最後)の直前で終わる新しい文字列を返します。したがって、次のようなものを入力します。

String firstValue = myString.substring(0, commaIndex);
String secondValue = myString.substring(commaIndex + 1, secondCommaIndex);
String thirdValue = myString.substring(secondCommaIndex + 1); // To the end of the string

最後に、整数値は、Stringクラスの文書化されていないメソッドtoInt()を使用して取得できます。

int r = firstValue.toInt();
int g = secondValue.toInt();
int b = thirdValue.toInt();

Stringオブジェクトとそのさまざまなメソッドの詳細については、 Arduinoのドキュメント を参照してください。

21
dsnettleton

sscanfを使用します。

const char *str = "1,20,100"; // assume this string is result read from serial
int r, g, b;

if (sscanf(str, "%d,%d,%d", &r, &g, &b) == 3) {
    // do something with r, g, b
}

文字列のストリームを解析する場合は、ここに私のコードを使用しますex:255,255,255 0,0,0 1,20,100 90,200,3コンマ区切り文字列の解析関数

8
sdao

これは素晴らしい!

"thirdvalue = 0"に関する最後のコメントは、@ dsnettletonによって最も支持された応答で与えられたコードから当てはまります。ただし、「lastIndexOf( '、');」を使用する代わりに、@ dsnettletonがcommaIndex + 1に対して正しく行ったように、コードは「secondCommaIndex」に「+1」を追加するだけです(+1がない場合は、おそらくその人のタイプミスです)。

ここに更新されたコードがあります

int commaIndex = myString.indexOf(',');
int secondCommaIndex = myString.indexOf(',', commaIndex+1);
String firstValue = myString.substring(0, commaIndex);
String secondValue = myString.substring(commaIndex+1, secondCommaIndex);
String thirdValue = myString.substring(secondCommaIndex+1); //To the end of the string  

例)

MyString = "1,2,3"の場合

  • commaIndex = 1(インデックス0から検索し、文字1が撮影したスポットを最初のコンマの位置まで検索します)
  • secondCommaIndex = 3(インデックス2、文字2が撮影したスポットから、次のコンマの場所まで検索)
  • firstValueはインデックス0-1 = "1"から読み取ります
  • secondValueはインデックス2-3 = "2"から読み取ります
  • 3番目の値は、インデックス4-4(文字列の最後のインデックススポット)= "3"から読み取ります。

注:INDEXと文字列のLENGTHを混同しないでください。文字列の長さは5です。StringindexOfは0から始まるため、最後のインデックスは4です。

ちょうど理由

String thirdValue = myString.substring(secondCommaIndex);

.toInt()を使用すると0が返されます。これは、thirdValue = "、3"であり、 "3"ではなく、toInt()を台無しにするためです。

ps。申し訳ありませんがすべての手順を書き出していますが、メカとして、特に過去7年間コンサルティングに携わってきた誰かにコードを教えてもらいたい場合があります。今後ともよろしくお願いいたします。私のような人をたくさん助けてくれます!

1
mct

最も簡単なのは、このタスクを実行するためにparseInt()を使用することだと思います。

void loop(){
    if (Serial.available() > 0){
        int r = Serial.parseInt();
        int g = Serial.parseInt();
        int b = Serial.parseInt();
    }
}

トリックを行います。

1
R Zach

データを読み取るには、次のようなことをしたいと思います。

String serialDataIn;
String data[3];
int counter;


int inbyte;

void setup(){
  Serial.begin(9600);
  counter = 0;
  serialDataIn = String("");
}

void loop()
{
    if(serial.available){
        inbyte = Serial.read();
        if(inbyte >= '0' & inbyte <= '9')
            serialDataIn += inbyte;
        if (inbyte == ','){  // Handle delimiter
            data[counter] = String(serialDataIn);
            serialDataIn = String("");
            counter = counter + 1;
        }
        if(inbyte ==  '\r'){  // end of line
                handle end of line a do something with data
        }        
    }
}

次に、atoi()を使用してデータを整数に変換し、使用します。

1
cstrutton

文字列で区切られたn番号の場合

int end;
while((end=str.indexOf(","))!=-1){
  String num = str.substring(0,end);
  str= asc.substring(end+1,str.length());
  Serial.println(num);  
}
0