我有一个随机字符缓冲区从XBee模块流入我的Arduino。我想提取它看到的第一个整数(如果这会产生差异,将是< = 3位数int),然后继续使用该数字并停止查看其余的传入字符。
作为参考,我试图将此作为与node.js服务器的双向握手的一部分,当其他Arduinos也试图握手或已连接时,该服务器不会搞砸并发送数据。
我认为我有一种方法可以提取一个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);
非常感谢任何建议/意见。
答案 0 :(得分:3)
不要与0到9之间的每个数字进行比较,而是使用标准C函数isdigit()
。
答案 1 :(得分:2)
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;
}
}
}
假设msg的第一个字符是数字:
intStart
设为0
intStart
尚未2
如果intStart
为0(它是,我们没有调整它)并且msg的第一个字符是数字(我们假设它是),然后将第一个字符追加到{ {1}}并制作intString
intStart = 1
如果
(它是,我们在prev步骤设置它)并且msg的第一个字符是数字(它仍然是第一个,intStart == 1
没有更改),然后将第一个字符追加到i
(很好,现在我有两次)并设置intString
(嘿,intStart=1
没有改变)。否则......我们可以忽略其他情况,我们处于intStart
then
和intStart==1
仍为0,而msg的第一个字符仍为数字。我应该继续还是能够做到?
本质上,msg的第一个字符是一个数字,你永远不会从i
离开,直到由于while (intStart != 2)
通过重复相同的fisrt char而增加了堆空间到处都是。
这就是你想要的吗?
在询问之前向你的橡皮鸭解释这个是不是很难?
(是的,我明白,Arduino没有调试器,但你仍然可以使用Serial。打印)
答案 2 :(得分:1)
[评论更新]
很抱歉,如果我不清楚,但它不一定以整数开头,整数可能在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
如果您不需要intString
,只需intValue
,请不要使用intString
- 最多bool hasDigits
来初始化false
1}}并设置为true
代替intString += msg[startScan];
(作为“没有遇到数字&#39;情况”的信号)。
如果您不需要intValue
,只需从使用它的代码中删除即可。
因此,如果我的提示不正确,则会出现以下问题:
我有一条
String
消息,该消息以最多 3个十进制数字开头,并可能与我不需要的其他信息结束。我希望这个“最多3位数字”#39;前缀转换为整数,供我进一步使用
如果这是你的问题,那就试试这个:
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');
}
答案 3 :(得分:0)
BTW有一个Arduino特定的堆栈交换。 arduino.stackexchange.com