C 在单独的else语句中修改字符数组时,为什么此函数不返回值1?
首先,在我解释发生了什么之前,让我向您展示我的代码:C 在单独的else语句中修改字符数组时,为什么此函数不返回值1?,c,arduino,C,Arduino,首先,在我解释发生了什么之前,让我向您展示我的代码: #include <SoftwareSerial.h> //Strings char inData[20]; //Allocate some space for the string char inChar; //Where to store the character read byte index = 0; //Index into array; where to store the character void setu
#include <SoftwareSerial.h>
//Strings
char inData[20]; //Allocate some space for the string
char inChar; //Where to store the character read
byte index = 0; //Index into array; where to store the character
void setup()
{
//Begin Serial Communication
Serial.begin(9600);
}
void loop(void){
//Determine if command mode should be entered
if(Comp("BTMODIFY") == 0)
{
Serial.print("Entering bluetooth command mode...);
}
}
char Comp(char* input){
//Internal variables
int i = 0;
while(Serial.available() > 0) //Don't read unless you know there is data
{
if(index < 19) //One less than the size of the array
{
inChar = Serial.read(); //Read a character
inData[index] = inChar; //Store it
index++; //Increment where to write next
inData[index] = '\0'; //Null terminate the string
}
}
if(strcmp(inData, input) == 0){
index = 0;
inData[index] = '\0';
return(0);
}
else{
index = 0;
inData[index] = '\0';
return(1);
}
}
然后代码正常工作,这意味着当我键入“BTMODIFY”时,终端上会打印一条语句。由于代码是现在的,没有发生任何事情-这意味着if(Comp(“BTMODIFY”)==0)
永远不会计算为true。很明显,我遗漏了一些东西
其思想是重用变量inData
,因此我只是在字符串的开头放置一个空终止符
任何建设性的输入都值得赞赏。程序可能陷入无限循环:
while(Serial.available() > 0) //Don't read unless you know there is data
{
if(index < 19) //One less than the size of the array
{
inChar = Serial.read(); //Read a character
...
}
}
或者,您可以重写Comp函数:
int Comp(char* input) {
//Internal variables
int i = 0;
int curr = 0;
while(Serial.available() > 0) //Don't read unless you know there is data
{
if(index < 19) //One less than the size of the array
{
inChar = Serial.read(); //Read a character
if(input[curr] == '\0') return 0; // Input ended, but data is still there.
if(input[curr++] != inChar) return 0; // Data doesn't match.
}
else return 1; // Data matches.
}
return 1; // Data matches.
}
int Comp(字符*输入){
//内部变量
int i=0;
int curr=0;
while(Serial.available()>0)//除非知道有数据,否则不要读取
{
if(index<19)//比数组的大小小一个
{
inChar=Serial.read();//读取字符
if(input[curr]=='\0')返回0;//输入结束,但数据仍然存在。
如果(输入[curr++]!=inChar)返回0;//数据不匹配。
}
else返回1;//数据匹配。
}
返回1;//数据匹配。
}
我认为这可能与阅读速度和执行函数的速度有关。下面是一段完全未经测试且未编译的代码,我认为(希望)它能满足您的需求
#include <SoftwareSerial.h>
#define MAXLEN 20
char getline(char* unsigned int);
void setup()
{
//Begin Serial Communication
Serial.begin(9600);
}
void loop(void){
//Determine if command mode should be entered
char cmd[MAXLEN];
while (!getline(cmd, MAXLEN))
; // Wait for a complete input line
if(strcmp("BTMODIFY", cmd) == 0)
{
Serial.print("Entering bluetooth command mode...");
}
}
char getline(char* input, unsigned int size){
static unsigned int i = 0;
static char done = 0;
while(Serial.available() > 0
&& i < size-1
&& !done)
{
char c = Serial.read(); //Read a character
input[i++] = c; //Store it and increment
if (c == '\n') //Or whatever newline your serial terminal is sending
{
done = 1;
}
}
input[i] = '\0';
if (done)
{
done = 0;
return 0;
}
return 1;
}
#包括
#定义MAXLEN 20
char getline(char*无符号整数);
无效设置()
{
//开始串行通信
Serial.begin(9600);
}
无效循环(无效){
//确定是否应进入命令模式
char cmd[MAXLEN];
而(!getline(cmd,MAXLEN))
;//等待完整的输入行
如果(strcmp(“BTMODIFY”,cmd)==0)
{
串行打印(“进入蓝牙命令模式…”);
}
}
char getline(char*输入,无符号整数大小){
静态无符号整数i=0;
静态字符完成=0;
而(Serial.available()>0
&&i<1号
&&!完成)
{
char c=Serial.read();//读取一个字符
输入[i++]=c;//存储并递增
如果(c=='\n')//或串行终端正在发送的任何新行
{
完成=1;
}
}
输入[i]='\0';
如果(完成)
{
完成=0;
返回0;
}
返回1;
}
Comp()
在数据到达时被多次调用
Serial.available()
如果Serial.available()。下一次调用Serial.available()
很容易返回0,因为此代码比数据到达的速度快得多。当else
块就位时,计数再次为零
如果没有else
块,数据有可能1)在inData
中累积并匹配“BTMODIFY”
或2)填充缓冲区,不再匹配
关键的逻辑错误是假设数据一次到达串行接口,而不是在char
之间存在潜在的大时间间隔(从CPU的角度来看)
建议的更改:
1) 当缓冲区已满时,清空最老的字符
。将inData
视为先进先出。
2) 在每个字符之后测试是否匹配
3) 避免使用像19这样的幻数-使用的派生值
char Comp(const char* input) {
size_t len = strlen(input);
int i = 0;
while(Serial.available() > 0) {
if (index > (sizeof inData - 2)) {
// toss eldest `char`
index = sizeof inData - 2;
memmove(&inData[0], &inData[1], index);
}
inChar = Serial.read(); //Read a character
inData[index] = inChar; //Store it
index++; //Increment where to write next
inData[index] = '\0'; //Null terminate the string **
if(index >= len && memcmp(&inData[index-len], input, len) == 0) {
index = 0;
inData[index] = '\0'; // **
return(0);
}
}
return(1);
}
**这些步骤是不需要的,inData
的大小可能是19。我同意,这很有趣。它似乎创建了一个无限循环,因为当未调用Serial.read()
时,数据被推出缓冲区。但是,它不起作用。如果数据被截断,那么下面的if
语句:(strcmp(inData,input)==0)
将不为真。使用strncmp
。我理解你的意思,但解决方案似乎不符合我所经历的症状。如果我在原始else块中对return(1)
之前的两条语句进行注释,则代码的行为与我预期的一样(打印出一条语句-没有无限循环)。然而,一旦我把这两行代码加进去,它就会停止工作(没有打印出来)。我无法解决您的问题。但是,您可以尝试更改Comp
功能,看看它是否有效。(只需删除整个该死的bug!)如果您在串行终端中输入BTMODIFY,则可能是您实际在程序中输入了“BTMODIFY\n”。您是对的。根据终端设置,我正在发送一个清除和一个新线信号以及字符串。然而,到目前为止,这似乎还没有造成问题。唯一的问题是我的else语句中的两行;inData[index]='\0'
使我认为您的函数读取串行数据的速度比可用的速度快。尝试更改为while(Serial.available()>8
或类似的功能。但是,如果读入速度不够快,您可能会遇到换行符的问题。有趣的想法。我已经删除了换行符(在HC-05蓝牙芯片上使用AT命令的剩余部分),并将尝试一下。
#include <SoftwareSerial.h>
#define MAXLEN 20
char getline(char* unsigned int);
void setup()
{
//Begin Serial Communication
Serial.begin(9600);
}
void loop(void){
//Determine if command mode should be entered
char cmd[MAXLEN];
while (!getline(cmd, MAXLEN))
; // Wait for a complete input line
if(strcmp("BTMODIFY", cmd) == 0)
{
Serial.print("Entering bluetooth command mode...");
}
}
char getline(char* input, unsigned int size){
static unsigned int i = 0;
static char done = 0;
while(Serial.available() > 0
&& i < size-1
&& !done)
{
char c = Serial.read(); //Read a character
input[i++] = c; //Store it and increment
if (c == '\n') //Or whatever newline your serial terminal is sending
{
done = 1;
}
}
input[i] = '\0';
if (done)
{
done = 0;
return 0;
}
return 1;
}
char Comp(const char* input) {
size_t len = strlen(input);
int i = 0;
while(Serial.available() > 0) {
if (index > (sizeof inData - 2)) {
// toss eldest `char`
index = sizeof inData - 2;
memmove(&inData[0], &inData[1], index);
}
inChar = Serial.read(); //Read a character
inData[index] = inChar; //Store it
index++; //Increment where to write next
inData[index] = '\0'; //Null terminate the string **
if(index >= len && memcmp(&inData[index-len], input, len) == 0) {
index = 0;
inData[index] = '\0'; // **
return(0);
}
}
return(1);
}