2016-01-25 7 views
0

Я тестирую метод имитации конкретного ввода в приложение. Это приложение:Имитировать вход для STDIN с EOL

#include <stdio.h> 

int main() 
{ 
     int num1; 
     char buffer[6] = {0}; 

     scanf("%d", &num1); 
     read(0, buffer, 6); 

     printf("num1 = %d\n", num1); 

     for(num1=0; num1 < 6; num1++) 
     { 
       printf("%02X\n", buffer[num1]); 
     } 

     return 0; 
} 

Я пытаюсь имитировать ввод с помощью следующей команды Баша:

echo -ne "1337\\x0A\\x31\\x02\\x03\\x04\\x05\\x06" | ./test 

Выхода я получаю следующее:

num1 = 1337 
00 
00 
00 
00 
00 
00 

Как вам видно, что буфер не был заполнен значениями, переданными в STDIN.

EDIT: Функция ниже используется только для иллюстрации идеи автоматизации ввода в смешанных входных/выходных функций, я получил эту функцию с помощью обратного проектирования двоичный файл, можно автоматизировать ввод?

Я ценю вашу помощь.

Спасибо,

ответ

0

Что здесь происходит?

  • echo делает запись ровно столько символов, вы положили в командной строке (как вы используете -n флаг он не выводит окончательный \n символов).
  • Вы используете scanf() на трубе, поэтому сначала считывает полный буфер, а затем проверяет буфер на целое число. Он возвращает n = read(0, buffer, BUFSIZ);, возвращая 11 в качестве числа символов, читаемых в scanf, а затем scanf сканирует буфер, возвращая 1337 в качестве числа, считанного и оставляющего все символы, прошедшие через него в буфер.
  • , тогда вы делаете read(0, buffer, 6);, который возвращает 0, а буфер не инициализируется данными.
  • затем вы печатаете предыдущий, неинициализированный буферный контент в стандартный вывод.

Фигулы (или трубы) ведут себя совсем иначе, чем терминалы на входе. Драйвер терминала просто заставляет читать, когда вы нажимаете клавишу enter, делая чтение, чтобы получить фактическое количество символов, прочитанных одной строкой ввода. Когда вы делаете это с помощью fifo, процесс чтения блокируется до тех пор, пока не будет получено достаточное количество символов (фактическое число, запрошенное чтением), и затем этот номер (фактически запрошенное количество символов) возвращается путем чтения.

Если вы были предусмотрительно проверки read(2) возвращаемого значения, вы должны получить фактическое количество прочитанных символов (которые должны быть 0 как scanf(3) съел весь буфер, как это меньше, чем BUFSIZ константа, в первом прочитайте)

+0

Спасибо за отличный ответ !. Можем ли мы сказать в качестве вывода, что автоматизировать вход в функцию выше невозможно, потому что scanf будет читать весь буфер stdin? Есть ли у вас какие-либо идеи передавать данные без труб? – Xedar

+0

Он попытается прочитать. Обычно, когда вход поступает с терминального устройства, он получает столько же ввода до символа новой строки (терминал даже переводит ASCII CR в ASCII LF в соответствии с соглашением UNIX). В этом случае является драйвером терминала, который решает объем данных вернуться. Это причина необходимости всегда проверять возвращаемое значение 'read (2)' syscall, потому что вы не всегда получаете столько данных, сколько вы запросили. –

0

Никогда не смешивайте STDIO функции, такие как зсапЕ с низким уровнем Io функции, такие как чтение. Stdio поддерживает буфер для повышения эффективности и если какие-либо дополнительные данные доступны при вызове scanf, скорее всего, он будет читать его для заполнения буфера.

Используйте вместо чтения прочитанный fread. Кроме того, не забудьте проверить возвращаемые значения этих функций.

+0

Спасибо, Джони, на самом деле я не написал приложение. Это отменено из двоичного кода, и я пытаюсь автоматизировать ввод. – Xedar

1

Вы смешиваете scanf() (section 3 man page) и read() (section 2 man page). Выполняются функции scanf()буферизированный читает и пишет. Раздел 2 read() не буферизирован. Байты, которые вы пытаетесь читать с read(), уже были прочитаны и помещены в буфер scanf().

Если вы прокомментируете вашу scanf() линии, и изменить свою команду

echo -ne "\\x0A\\x31\\x02\\x03\\x04\\x05\\x06" | ./test 

вы получите

num1 = 0 
0A 
31 
02 
03 
04 
05 

Так просто использовать буферизованные функции или небуферизованные функции. Выбери один.

+0

Спасибо за ценную информацию. На самом деле этот код не был написан мной. У меня только скомпилированный двоичный файл, но я отменил его до простой формы для фрагмента, который вы можете увидеть выше. Мне было интересно, можно ли автоматизировать это, даже если функции смешаны. – Xedar

+0

@xedar. Если вы что-то перепроектируете, не используйте 'scanf()', который будет буферизовать все входные данные в буфере stdio, а затем заставляет 'read()' возвращать 0 байтов (так как здесь есть канал и эхо просто передайте все байты, которые вы передали ему на выход). Вы не проверили возвращаемое значение чтения, чтобы проверить это, и предположим, что чтение читает 6 байтов. –