2013-06-07 3 views
1

Я прочитал буфер с последовательного устройства. Он возвращает мне эти результаты (по 2 строки каждый раз)удалить символы из EOL

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 и означает \ r \ n в Windows. Первый результат в порядке, но два других ужасных. Есть ли способ проверить символы^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); 
} 

UPDATE

открыть и настроить свое устройство таким образом

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 
+0

Я думаю, что вы должны проверить полукокс по полукоксу для значения ASCii http://en.wikipedia.org/wiki/ASCII#ASCII_control_code_chart – tikend

+0

Что происходит в окнах после вас 'read()' EOF? читает стоп? –

+0

Я не знаю, что происходит в Windows. Я использую Linux, и у меня есть эти символы – dali1985

ответ

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

Примечание:
1) Вы заполнили buff раньше от последовательного устройства с использованием read(). Поскольку последовательные устройства являются двоичными, считываемые байты могут включать в себя NUL байты. Чтение массива байтов со спорадически пересекающимися байтами NUL в буфере и обработка его, как символьная строка с нулевым символом, приведет к пропущенным данным.
2) A read() не добавляет байт \0 в конец буфера, который он читает, и может объяснить вашу «ОШИБКУ».
3) В общем, вы читаете двоичное устройство и записываете текстовый вывод. Входящий двоичный поток, скорее всего, является ASCII-текстом, используя \r\n как конец строки, но ваш stdout хочет использовать \n как конец строки. Пока байты печатаются ASCII (коды 32-126), все работает как ожидается при печати на stdout. Но когда вы читаете \0, \r, \n, в паре \r\n, другие контрольные символы, ошибки связи и т. Д., Вам нужно подумать о том, как вы хотите отображать.

+0

Благодарим вас за ответ. Я обновил сообщение с помощью функций open и configure, которые я написал – dali1985

+0

Один вопрос, потому что я получаю fd как int, могу ли я использовать его с fgets? Я думаю, что нет! – dali1985

+0

Я вижу это в вашем обновлении и исправляю свой ответ. (Должно было видеть это в исходном 'read()'.) – chux

0

Во-первых, ^M^J - это конец строки, а не конец файла.

Во-вторых, read считывает двоичные данные из указанного файлового дескриптора. Он считывает количество символов, которые вы указали, до тех пор, пока не достигнет конца файла, или не получите ошибку. Если вы хотите читать строки за раз, читайте по одному байту за один раз или используйте другие вызовы ввода-вывода, ориентированные на линию (sscanf, что-то вроде этого)

+0

Наше, стучите мне в голову, Ответ удалил, извините. – icbytes

0

Вы можете задать вопрос this, в котором предлагается функция для чтения строк из файла и обращения с возвратом каретки Windows.

0

Открыть файл с O_TEXT

#include <fcntl.h> 
fd = open("/dev/ttyAMA0", O_RDWR | O_NOCTTY | O_NDELAY | O_TEXT); 
+0

С этим решением (с этим заголовком) у меня есть ошибка: «O_TEXT» не был объявлен в этой области. – dali1985

+0

Либо 1) 'O_TEXT' находится в файле include, например' ',' ',' 'или 2)' 'или вы используете Unix-подобную систему, которая не различает двоичные и текстовые файлы , Если # 2 - это случай, и блок, отправляющий сообщение, является ПК-подобным, то _it_ должен использовать флаг O_TEXT. – chux

Смежные вопросы