c - 从 EOL 中删除字符

标签 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

最佳答案

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

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

关于c - 从 EOL 中删除字符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16981980/

相关文章:

c - STM32F4探索和CAN编程

c - 未指定的参数数量和传递给 C 函数的可变参数数量之间有什么区别?

linux - 稍后执行脚本的命令

linux - Linux 上的 OpenVPN : passing username and password in command line

c++ - 为什么 'new line' 偏移 .txt 文件中的所有字符字节位置 +1?

c - 使用多个变量时,如何通过 printf 函数删除 C 中多余的换行符?

c - Xcode:类型 'struct dirent' 在不同翻译单元中具有不兼容的定义

c - 我在哪里可以学习链接列表/堆栈?

linux - 当我遇到 pid 冲突并且服务器未处理 php 时如何重新启动 apache2

C 删除字符串末尾的换行符,行为很奇怪