C:删除新行/ null终止输入字符串

时间:2016-03-23 16:27:27

标签: c arduino embedded

在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;
}

它要读取的字符串是这样的: &#34; 111 \ r \ n&#34; (后面有一个马车+新线)

正在使用

在Arduino中打印出来
serial.print("1");
serial.print("1");
serial.println("1");

使用serialport_read_until方法(char直到&#39; \ r \ n &#39;),我想确保我正确读取整个缓冲区。

以下哪一项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;吗?

1 个答案:

答案 0 :(得分: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文档。特别是,它处理空格的方式并不总是直观的。