簡體   English   中英

在Arduino上從String中提取int

[英]Extracting int from String on Arduino

我有一個隨機字符緩沖區,它從XBee模塊流到Arduino中。 我想提取它看到的第一個整數(如果有區別,將為<= 3位數整數),然后繼續使用該數字並停止查看其余的傳入字符。

作為參考,我正在嘗試將它用作與node.js服務器進行2次握手的一部分,當其他Arduino也嘗試握手或已經連接並發送數據時,不會弄亂它。

我認為我有一種可能可以提取一個int的方法,但是它看起來確實很丑陋,因此我認為必須采用一種更短/更干凈的方法來實現此目的。 這是我很長的代碼,可能要做的很簡單:

String intString = "";
int intStart = 0;
for (int i = 0; i < msg.length(); i++) {
    while (intStart != 2) {
        if (intStart == 0) {
            if ((msg[i] == '0') || (msg[i] == '1') || (msg[i] == '2') || 
                    (msg[i] == '3') || (msg[i] == '4') || (msg[i] == '5') || 
                    (msg[i] == '6') || (msg[i] == '7') || (msg[i] == '8') || 
                    (msg[i] == '9')) {
                        intString += msg[i];
                        intStart = 1;
                 }
        }
        // previous int, next is still int
        if (intStart == 1) {
            if ((msg[i] == '0') || (msg[i] == '1') || (msg[i] == '2') || 
                    (msg[i] == '3') || (msg[i] == '4') || (msg[i] == '5') || 
                    (msg[i] == '6') || (msg[i] == '7') || (msg[i] == '8') || 
                    (msg[i] == '9')) {
                        intString += msg[i];
                        intStart = 1;
                 }
        }
        // previous int, next is not int
        else if ((msg[i] != '0') && (msg[i] != '1') && (msg[i] != '2') && 
                         (msg[i] != '3') && (msg[i] != '4') && (msg[i] == '5') && 
                         (msg[i] != '6') && (msg[i] != '7') && (msg[i] == '8') && 
                         (msg[i] != '9')) {
                             intStart = 2;
        }
    } 
}
int number = intString.toInt();
Serial.println(number);

任何建議/建議,不勝感激。

不要使用標准C函數isdigit()與0到9之間的每個數字進行比較。

String intString = "";
int intStart = 0;
for (int i = 0; i < msg.length(); i++) {
    while (intStart != 2) {
        if (intStart == 0) {
            if (isdigit(msg[i])){
                        intString += msg[i];
                        intStart = 1;
                 }
        }
        // previous int, next is still int
        if (intStart == 1) {
            if (isdigit(msg[i])) {
                        intString += msg[i];
                        intStart = 1;
                 }
        }
        // previous int, next is not int
        else if ( isdigit(msg[i]) ) {
                             intStart = 2;
        }
    } 
}

“橡皮鴨調試”

假設味精的第一個字符是一個數字:

  1. intStart設置為0
  2. 取味精的第一個字符
  3. intStart2
  4. 如果intStart為0(即我們尚未對其進行調整),並且味精的第一個字符為digit(我們假定為),則將第一個字符附加到intString ,並使intStart = 1
  5. 如果intStart == 1intStart == 1 ,我們在上一步中將其設置),而味精的第一個字符是digit(它仍然是第一個, i沒有改變),然后將第一個字符附加到intString (很好,現在我有兩次)並設置intStart=1 (嘿, intStart沒變)。 否則,我們可以忽略其他情況, then我們處於良好狀態
  6. 回到第3步,使用intStart==1i仍然為0,味精的第一個字符仍然為數字。

我應該繼續還是您能夠做到?

本質上,由於msg的第一個字符為數字,因此直到intString不斷重復使用相同的intString char來增長intString之前,您永遠不會退出while (intStart != 2)

那是你要的嗎?

在問SO之前向您的橡皮鴨解釋這個問題是如此難嗎?
(是的,我知道,Arduino沒有調試器,但是您仍然可以使用Serial.print)

[評論更新]

抱歉,如果我不清楚,但不一定以整數開頭,則該整數可能位於char緩沖區的中間。

char緩沖區中任意長度的第一個數字序列(實際上不必限制為最大3位數,只要它使它更容易)

因此,在開始收集之前,我們只需要將自己放置在字符串緩沖區的第一位

int startScan=0;
// no body for the cycle, everything works just from 
// the exit condition and increment
for(
  ; 
  startScan < msg.length() && ! isdigit(msg[i]); // as long as it's not a digit
  startScan++
);

// from this position, start collecting for as long as we have digits
int intValue=0;
String intString;
for(; startScan < msg.length() && isdigit(msg[startScan]); startScan++) {
  intString += msg[startScan]; // take it inside the string

  // careful with this one, it may overflow if too many digits
  intValue = intValue*10 + (msg[startScan]-'0');
}
// if we reached here with an empty intString, we didn't find any digits

如果您不需要intStringintString需要intValue ,不要使用intString最多將bool hasDigits初始化為false並設置為true代替intString += msg[startScan]; (作為“未遇到數字”情況的信號)。

如果不需要intValue ,只需從使用它的代碼中清除即可。


因此,如果我的陳述不足,那么您將遇到以下問題:

我有一個String消息,該消息最多以 3個十進制數字開頭,並可能以我不需要的其他信息結尾。 我希望將“至多3個數字”前綴轉換為整數,以便我進一步使用

如果這是您的問題,請嘗試以下操作:

int intValue=0;
String intString;
int maxLookInto=(msg.length() > 3 ? 3 : msg.length()); // at most 3 digits
for(int i=0; i<maxLookInto && isdigit(msg[i]); i++) {
  // if we got here, we know msg[i] is still a digit, otherwise
  // we get out of cycle ealier
  intString += msg[i]; // take it inside the string
  intValue = intValue*10 + (msg[i]-'0'); // transforming in base 10 in an int
}
// Do what you like with either intString (textual representation of the
//  at-most-3-digits or with the same value converted already to a number
//  in intValue

如果Arduino沒有提供isdigit功能,則可以實現自己的

int isdigit(char c) {
  // we are using ASCII encoding for characters, aren't we?
  return (c>='0' && c <='9');
}

一種方法是使用String對象。 這有一個toInt方法。

順便說一句,有一個特定於Arduino的堆棧交換。 arduino.stackexchange.com

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM