2015-05-20 3 views
12

मैं गतिशील पैरामीटर के साथ printf() कार्यों उत्पादन प्रारूप को नियंत्रित करना चाहते हैं, नीचे दिए गए कोड से पता चला है बस के रूप में:मैं गतिशील तर्कों के साथ printf के आउटपुट प्रारूप को क्यों सेट नहीं कर सकता?

#include<stdio.h> 

    int main(int argc,char ** argv) 
    { 
     printf(argv[1],"hello,world"); 
     return 0; 
    } 

तब मैं संकलन और इसे चलाने:

$ gcc -o test test.c 
$ ./test "\t%s\n" 

परिणाम अजीब है:

\thello,world\n$ 

क्यों "\n" और "\t" का कोई प्रभाव नहीं है?

+6

कि आर्ग साथ printf के प्रारूप वैसे आप स्पष्ट रूप से सेट कर सकते हैं के लिए man bash में के हवाले से देखें, तो आप अभी भी अपने \ t और \ N है। समस्या यह है कि इन वर्णों को सारणीकरण और रेखा फ़ीड के रूप में पढ़ा नहीं जा रहा है। साथ ही, ** उपयोगकर्ता इनपुट से पहले तर्क के साथ प्रिंट को कॉल न करें, यह एक सुरक्षा चेतावनी है !!! ** – Eregrith

+6

देखें [प्रारूप स्ट्रिंग भेद्यता] (http://www.cis.syr.edu/~wedu/Teaching/ cis643/व्याख्यानNotes_New/Format_String.pdf) उदाहरण के लिए :) – Eregrith

+1

यह प्रश्न (या इसका उत्तर) वास्तव में सी या 'printf' के बारे में नहीं है, लेकिन क्यों आपके खोल में \ t' और' \ n' स्ट्रिंग के अंदर नहीं है सी संकलक के समान ही है। –

उत्तर

9

क्योंकि आपके द्वारा उपयोग किए जाने वाले भागने (\t और \n) सी संकलक द्वारा स्ट्रिंग अक्षर के अंदर व्याख्या किए जाते हैं, printf() द्वारा नहीं। यह:

const char *newline1 = "\n", newline2[] = { '\n', 0 }; 

newline1 और newline2, या नहीं, इन कभी printf() को पास किया जाता की परवाह किए बिना में ठीक उसी सामग्री उत्पन्न होगा; वैसे भी तार हैं।

आपका कोड बर्ताव करता है जैसे यह होगा:

printf("\\t%s\\n", "hello,world"); 

यहाँ, मैं अपने कमांड लाइन तर्क, के रूप में ही वास्तविक सामग्री के साथ एक स्ट्रिंग उत्पन्न करने के लिए डबल-भाग निकले गए विशेष वर्ण यानी "\t%s\n" (छह चार की बजाय पात्र)।

printf() गतिशील रूप से नियंत्रित करने का उचित तरीका कोड में प्रारूप स्ट्रिंग बनाना है। यदि आप रनटाइम पर सी-जैसे भागना चाहते हैं, तो आपको किसी भी तरह से स्वयं को समझने की आवश्यकता है।

+1

यदि कोई विशेष भागने के अनुक्रमों को समझने के लिए शैल चाहता है, तो बैकक्वॉट्स के बीच एक और कमांड का उपयोग पहले से बचने के लिए और स्ट्रिंग के रूप में प्रोग्राम को पास करने के लिए कर सकता है। – Eregrith

4

ऐसा इसलिए है क्योंकि संकलक "\n" इत्यादि जैसे बचने के अनुक्रमों को संभालता है, और यह केवल स्ट्रिंग या वर्ण अक्षर में करता है।

6

एक स्ट्रिंग या चरित्र C/C शाब्दिक में अनुक्रम \n ++ अंकीय मान 10 (एक ASCII सिस्टम पर) के साथ एक एकल बाइट है। टर्मिनल पर आउटपुट (putchar(10) आज़माएं!) यह टर्मिनल पर अगले पंक्ति के लिए आउटपुट स्थिति को अगली पंक्ति (ऑन * निक्स पर, मैकोज़ पर, मुझे लगता है कि आपको अतिरिक्त \r, या 13 के लिए लाइन की शुरुआत में आउटपुट स्थिति रखने के लिए कैरिज रिटर्न)।

इसी तरह, \t मूल्य 9 के साथ एक बाइट के लिए संकेत है, जो अधिकांश टर्मिनलों को अपने कर्सर को अगली टैबलेटर स्थिति में अग्रिम बनाता है।

आपको कमांड लाइन में इन मानों का एक बाइट डालने की आवश्यकता है। यह कैसे किया जा सकता है आपके खोल पर निर्भर करता है; बैश में आप शेल को पहले से Ctrl-V दबाकर विशेष वर्णों को समझने से रोक सकते हैं। वह आउटपुट उदा। एक टैब, कुछ रिक्त स्थान दिखाकर प्रदर्शित किया जाता है (खोल बनाने के बजाय संभव स्ट्रिंग निरंतरता या बैश में जो भी टैब करता है) दिखाता है। सिंगल या डबल कोट्स में बैश तारों में बिना किसी प्रयास के न्यूलाइन शामिल हो सकते हैं - बस एंटर दबाएं।

यहां एक साइगविन टर्मिनल में बैश के साथ एक नमूना चलाया गया है। मैंने संकेतित पदों पर संकेतित कुंजी दबा दी; मैंने दूसरी पंक्ति पर समापन एकल उद्धरण के बाद [वापसी] के साथ सामान्य के रूप में आदेश समाप्त किया।

pressed Ctrl-v,[TAB] here | pressed [return] there 
        v  v 
$ ./printf-arg.exe ' %s 
> ' 
     hello,world 

> दूसरी पंक्ति में खोल से उत्पादन के बाद मैं दबाया स्ट्रिंग एकल उद्धरण से सीमांकित भीतर दर्ज किया गया था। (जो स्ट्रिंग में एक नई लाइन डालता है)। यह एक संकेत है कि उस रेखा पर संपादित स्ट्रिंग जारी है।

एक तरफ के रूप में, संभावित रूप से शत्रुतापूर्ण वातावरण में कमांड लाइन तर्कों का उपयोग करना संभवतः असुरक्षित है। सावधानी से तैयार किए गए तारों में स्मृति का उपयोग किया जा सकता है जिसका उपयोग नहीं किया जाना चाहिए और उदा। वापसी पते को पुनर्निर्देशित करें, इस प्रकार प्रोग्राम को दूषित कर दें।

3

यदि आप आदेश देने के लिए "\ t% s \ n" व्याख्या करते हैं तो यह काम करेगा। हालांकि खोल में ऐसी स्ट्रिंग का निर्माण करना मुश्किल है। सबसे आसान तरीका है मुझे पता है:

./test $'\t%s\n' 

एएनएसआई $'magick'

संबंधित मुद्दे