предаване на низ към 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

Имам такъв проблем - трябва да направя джаджа, която ще изглежда като панел с някои неща върху него и долните раздели. Видях доста същите раздели в прегледа на примерите на Sencha, но не можах да намеря примерен код за тях. Особено с помощта на UiBinder. Може ли някой да ми помогне с това?

  -  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() получава просто един ред от stdin, не се интересува какви знаци има в този ред. scanf(), от друга страна, изисква да посочите точно кои знаци ще се появяват в какъв ред.

Вижте страниците с ръководство за scanf и fgets за повече информация.

person kamituel    schedule 27.02.2013