从EOL中删除字符

时间:2013-06-07 10:30:40

标签: c linux newline

我从串行设备读取缓冲区。它返回这些结果(每次2行)

Hello World.
My name is John.

Hello World.^M^JMy name 
is Mike.

Hello World.^M^JMy name 
is ^M^JERROR Peter.

这些结果在Linux命令行中。 ^ M ^ J是EOL,在Windows中表示\ r \ n。第一个结果还可以,但其他两个都很糟糕。有没有办法检查^ M ^ J字符并删除它们?因为我想要这些结果:

Hello World.
My name is John.

Hello World.
My name is Mike.

Hello World.
My name is Peter.

使用此代码我读取缓冲区

char buff[150];
memset(buff, 0, sizeof(buff));
for (;;)
{
  n=read(fd,buff,sizeof(buff));
  printf("%s", buff);
}

更新

我以这种方式打开并配置我的设备

int open_port(void)
{
int fd; // file description for the serial port 
fd = open("/dev/ttyAMA0", O_RDWR | O_NOCTTY | O_NDELAY);
if(fd == -1) // if open is unsucessful
{
 //perror("open_port: Unable to open /dev/ttyAMA0 - ");
 printf("open_port: Unable to open /dev/ttyAMA0. \n");
}
else
{
  fcntl(fd, F_SETFL, 0);
  printf("port is open.\n");
}

return(fd);
} //open_port

并配置端口

int configure_port(int fd)      // configure the port
{
 struct termios port_settings;      // structure to store the port settings in
 cfsetispeed(&port_settings, B9600);    // set baud rates
 cfsetospeed(&port_settings, B9600);
 port_settings.c_cflag &= ~PARENB;    // set no parity, stop bits, data bits
 port_settings.c_cflag &= ~CSTOPB;
 port_settings.c_cflag &= ~CSIZE;
 port_settings.c_cflag |= CS8;
 tcsetattr(fd, TCSANOW, &port_settings);    // apply the settings to the port
 return(fd);

} //configure_port

4 个答案:

答案 0 :(得分:0)

首先,^M^J是行尾,而不是文件结尾。

其次,read从指定的文件描述符中读取二进制数据。它会读取您指定的字符数,直到它到达文件末尾,或者出错。如果你想一次读取行,一次读取一个字节,或者使用其他一些面向行的I / O调用(sscanf,那种东西)

答案 1 :(得分:0)

您可以查看this问题,该问题提出了从文件中读取行并处理Windows回车的功能。

答案 2 :(得分:0)

printf()看到\r\n而不是孤独的\n时,^M^J会以有趣的方式表现。它将成对的字符行尾解释为不是行尾,因此它不是执行通常的行结束函数,而是向您显示\r。简单地消除 char buff[150]; int n = read(fd,buff,sizeof(buff)); // buff is not NUL terminated if (n < 0) { // deal with I/O error } if (n == 0) { // deal with end-of-file } else { for (int i=0; i<n; i++) { if (isprint(buff[i]) || (buff[i] == '\n')) { putchar(buff[i]); } else if (buff[i] == '\r') { ; // drop it } else { ; // TBD deal with unexpected control codes and codes 127-255 } } } 将为您提供所需的行为。

buff

注意:
1)您之前使用read()从串行设备填充read()。由于串行设备是二进制的,读取的字节可能包括NUL字节。读取缓冲区中偶尔散布NUL字节的字节数组并将其视为NUL终止字符串将导致错过数据。
2)\0不会将\r\n字节附加到它读取的缓冲区的末尾,并且可以解释您的“错误”。
3)通常,您正在读取二进制设备并写入文本输出。传入的二进制流可能是使用stdout作为行尾的ASCII文本,但您的\n想要使用stdout作为行尾。只要字节是可打印的ASCII(代码32-126),当打印到\0时,所有字节都按预期工作。但是当您阅读\r\n\r\n,配对{{1}},其他控制字符,通信错误等时,您需要考虑如何显示。

答案 3 :(得分:0)

使用O_TEXT

打开文件
#include <fcntl.h>
fd = open("/dev/ttyAMA0", O_RDWR | O_NOCTTY | O_NDELAY | O_TEXT);