在 C 中,我使用串行库中的此方法:
int serialport_read_until(int fd, char* buf, char until, int buf_max, int timeout)
{
char b[1]; // read expects an array, so we give it a 1-byte array
int i=0;
do {
int n = read(fd, b, 1); // read a char at a time
if( n==-1) return -1; // couldn't read
if( n==0 ) {
usleep( 1 * 1000 ); // wait 1 msec try again
timeout--;
if( timeout==0 ) return -2;
continue;
}
#ifdef SERIALPORTDEBUG
printf("serialport_read_until: i=%d, n=%d b='%c'\n",i,n,b[0]); // debug
#endif
buf[i] = b[0];
i++;
} while( b[0] != until && i < buf_max && timeout>0 );
buf[i] = 0; // null terminate the string
return 0;
}
它将读取的字符串如下所示: “111\r\n”(后面有一个回车+换行符)
它正在 Arduino 中使用打印出来
serial.print("1");
serial.print("1");
serial.println("1");
使用serialport_read_until方法(字符直到为“\r\n”),我想确保正确读取整个缓冲区。
char* buf 最后看起来像下面哪一个?
1) 111\r\n
2) 111\r\n\0
3) 111\0
4) 111
在使用 sscanf 方法将字符串正确转换为整数之前,我需要弄清楚这部分,但我不确定使用哪个:
sscanf(buf, "%d\r\n", #num);
或 sscanf(buf, "%d", #num);
此外,我是否应该将倒数第二行: buf[i] = 0;
更改为 buf[i-1] = 0;
?
最佳答案
在我看来,你应该期待 111\r\n\0
。请注意,条件b[0] != until
递增 i
后检查,因此当收到换行符并退出循环时,i
指向 \n
之后的下一个字节。然后b[i]=0
在那里存储一个空字节。
请注意,此代码似乎有一个错误:如果 until
从未收到字符,循环将运行直到 i == buf_max
然后用空终止符再存储一个字节。所以总共buf_max+1
存储字节,这意味着以下代码将出现缓冲区溢出:
char mybuf[123];
serialport_read_until(fd, buf, 'x', 123, 42);
除非文档说 buf_max
应该比缓冲区的大小小一,这违反直觉并且容易出错,循环终止条件可能应该是 i+1 < buf_max
或类似的东西。
此外,自 i
在最后检查,即使进行此修复,如果您传入 buf_max == 0
,代码仍将存储一个字节。 (但如果没有修复,它将存储两个字节)。所以这是另一个错误。
char b[1];
声明和附带的评论也有点奇怪。简单地声明 char b;
会更惯用。然后通过 &b
至read()
.
因此,如果这是您的代码,那么还有更多工作要做。如果是其他人的代码,如果这个函数可以表明质量,我会非常小心地使用这个库。
正在做buf[i-1]=0
最后会避免溢出,但也意味着如果 until
未接收到字符,接收到的最后一个字节将丢失。如果您使用 buf_max == 0
调用该函数,它也会中断。 。所以这不是你想要的。
如果您使用sscanf
,是否存在尾随空格的问题无关紧要; sscanf("%d")
只会忽略它。您应该仔细阅读图书馆的 sscanf
文档。特别是,它处理空白的方式并不总是直观的。
关于C:删除新行/空终止输入字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36183623/