передача строки в printf, в c

передача строки в printf не работает должным образом:

char p[50];
scanf("%s", p); 
printf(p, 10); 

ввод: value:%d\n

ожидаемый результат: value:10

вывод: value:10\n

Кроме того, я получил разные результаты в разное время. вывод одного и того же a.out при 3 последовательных выполнениях:

$./a.out

value: %d\n
value:

$./a.out

value:%d\n\n
value:10\n\n

$./a.out

value:%d\n
value:10\n

В приведенном выше value: %d\n соответствует scanf, а следующая строка — printf.


person jyothis    schedule 27.02.2013    source источник
comment
Я не верю в ваш код и пример вывода. Текстовое значение отображается в выводе, но не в коде. Вы набираете value?   -  person unwind    schedule 27.02.2013
comment
@unwind появляется на входе. Он передает ввод в качестве первого аргумента printf   -  person John Dvorak    schedule 27.02.2013
comment
Так ли это плохо, как кажется, передавать введенные пользователем строки непосредственно в printf?   -  person John Dvorak    schedule 27.02.2013
comment
@JanDvorak: Это очень плохая идея, в основном потому, что %n может записывать в произвольную память. Даже без него злоумышленник может раскрыть произвольные данные в стеке (например, пароль) или вызвать сбой вашей программы.   -  person nneonneo    schedule 27.02.2013
comment
извините, я не понимаю, но звучит интересно, что вы подразумеваете под прямым переходом к printf? @nneonneo   -  person fersarr    schedule 27.02.2013
comment
@fersarr: printf(s, ...), где строка формата s — это строка, предоставленная пользователем, т. е. переданная непосредственно в printf. Это противоречит жестко закодированной литеральной строке, что является нормой.   -  person nneonneo    schedule 27.02.2013
comment
ооооо!! понятно! спасибо... я привык к cpp.. спасибо   -  person fersarr    schedule 27.02.2013
comment
@JanDvorak Верно, спасибо. Это (как обычно) очевидно сейчас, если посмотреть на это чуть позже. :)   -  person unwind    schedule 27.02.2013


Ответы (2)


Будьте действительно осторожны при передаче введенного пользователем текста в качестве первого аргумента функции printf, иначе вы столкнетесь с уязвимостью строки формата. Кроме того, при использовании голого scanf вы также подвержены переполнению буфера. (Две уязвимости всего в трех строках кода!)

Тем не менее, причина, по которой вы получаете литерал \n в своем выводе, заключается в том, что когда вы вводите \n в консоли, вы получаете строку с буквальным обратным слэшем, за которым следует n, вместо символа новой строки.

Также обратите внимание, что scanf останавливается на любом пробеле, поэтому ввод value: xxx приведет к тому, что в буфер попадет только value:. Вместо этого вы должны использовать функцию типа fgets, если хотите прочитать всю строку.

person nneonneo    schedule 27.02.2013

Ваш код ведет себя именно так, как предполагалось. В вашем первом примере вы передали пробел перед «10», поэтому он не был напечатан.

Самым простым решением было бы использовать fgets() вместо scanf():

#include <stdlib.h>
#include <stdio.h>

void main () {
  char p[50];
  fgets(p, 50, stdin);
  //scanf("%s", p);
  printf(p, 10);
}

Причина в том, что fgets() получает просто одну строку из стандартного ввода, и ему все равно, какие символы в этой строке. scanf(), с другой стороны, требует, чтобы вы точно указали, какие символы и в каком порядке будут отображаться.

См. справочные страницы для scanf и fgets для получения дополнительной информации.

person kamituel    schedule 27.02.2013