সিটিতে% n ফর্ম্যাট স্পেসিফায়ার ব্যবহার কী?


125

%nসি তে বিন্যাস নির্দিষ্টকরণের ব্যবহার কী ? কেউ উদাহরণ দিয়ে ব্যাখ্যা করতে পারে?


25
সূক্ষ্ম ম্যানুয়ালটি পড়ার সূক্ষ্ম শিল্পের কী পরিণত হয়েছে?
জেনস

8
আমি মনে করি আসল প্রশ্নটি হ'ল এই বিকল্পটির পয়েন্ট কী ? কেন যে কেউ চাইলে মুদ্রিত চরের সংখ্যার মান জানতে চাইবে সেই মানটি সরাসরি স্মৃতিতে লিখুন। এটি দেখে মনে হচ্ছিল যে বিকাশকারীরা বিরক্ত হয়ে সিদ্ধান্ত নিয়েছেন যে কর্নালে একটি বাগ প্রবর্তন করার জন্য
jia chen

এই কারণেই বায়োনিক এটি ছেড়ে দেয়।
solidak

1
এটি আসলে একটি বৈধ প্রশ্ন এবং সূক্ষ্ম ম্যানুয়ালগুলি সম্ভবত উত্তর দেবে না এমন একটি; এটি আবিষ্কার করা হয়েছে যা দুর্ঘটনাক্রমে টুরিং-সম্পূর্ণ করে %nতোলে printfএবং আপনি উদাহরণস্বরূপ এতে ব্রেনফাক বাস্তবায়ন করতে পারেন, github.com/HexHive/printbf এবং তেলশেল.
জন ফ্রেজার

উত্তর:


147

কিছুই মুদ্রিত। যুক্তিটি অবশ্যই একটি স্বাক্ষরিত ইন্টার এর পয়েন্টার হওয়া উচিত, যেখানে এখন পর্যন্ত লেখা অক্ষরের সংখ্যা সংরক্ষণ করা আছে।

#include <stdio.h>

int main()
{
  int val;

  printf("blah %n blah\n", &val);

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

  return 0;

}

পূর্ববর্তী কোড মুদ্রণ:

blah  blah
val = 5

1
আপনি উল্লেখ করেছেন যে আর্গুমেন্টটি অবশ্যই স্বাক্ষরিত ইন্টির জন্য একটি পয়েন্টার হতে পারে, তারপরে আপনি নিজের উদাহরণটিতে একটি স্বাক্ষরবিহীন ইনট ব্যবহার করেছেন (সম্ভবত কেবল একটি টাইপো)।
বিটিএ

1
@ অ্যান্ড্রুস: কারণ ফাংশনটি ভেরিয়েবলের মান পরিবর্তন করবে।
জ্যাক

3
@ জ্যাক intসর্বদা স্বাক্ষরিত হয়।
জেমসডলিন

1
@ জামেসডলিন: আমার ভুল আমি দুঃখিত .. আমি জানি না আমি কোথায় পড়েছি।
জ্যাক

1
কিছু কারণে নমুনা নোট সহ ত্রুটি উত্থাপন করে n format specifies disabled। কি কারণ?
জনি_ডি

186

এই উত্তরগুলির মধ্যে বেশিরভাগই ব্যাখ্যা %n করে যা কী করে (যা কোনও কিছুই মুদ্রণ করা এবং এমনভাবে ছাপানো অক্ষরের সংখ্যা লিখতে হবে যা intচলক পর্যন্ত ) তবে এখন পর্যন্ত কেউ এর ব্যবহারের সত্যতা উদাহরণ দেয় নি । এখানে একটি:

int n;
printf("%s: %nFoo\n", "hello", &n);
printf("%*sBar\n", n, "");

মুদ্রণ করবে:

hello: Foo
       Bar

ফু এবং বার সারিবদ্ধ হয়েছে ( %nএই বিশেষ উদাহরণটি ব্যবহার না করে এটি করা তুচ্ছ এবং সাধারণভাবে সর্বদা এই প্রথম printfকলটি ব্রেক আপ করতে পারে :

int n = printf("%s: ", "hello");
printf("Foo\n");
printf("%*sBar\n", n, "");

সামান্য যোগ করা সুবিধার্থে জাতীয় কিছু ব্যবহার করার উপযুক্ত কিনা %n(এবং সম্ভবত ত্রুটিগুলি প্রবর্তন করা) বিতর্কের জন্য উন্মুক্ত))


3
ওহ আমার - এটি প্রদত্ত ফন্টে পিক্সেল আকারের পংক্তি গণনা করার একটি চরিত্র-ভিত্তিক সংস্করণ!

& N এবং * গুলি কেন প্রয়োজন তা আপনি ব্যাখ্যা করতে পারেন। তারা উভয় পয়েন্টার?
অ্যান্ড্রু এস

9
@ অ্যান্ড্রুস &nএকটি পয়েন্টার ( &অপারেটরের ঠিকানা); একটি পয়েন্টার প্রয়োজনীয় কারণ সি পাস-বাই-মান, এবং একটি পয়েন্টার ছাড়াই, printfএর মানটি পরিবর্তন করতে পারে না n%*sমধ্যে ব্যবহারের printfবিন্যাস স্ট্রিং একটি ছাপে %sসুনির্দিষ্টভাবে উল্লেখ করা (এই ক্ষেত্রে খালি স্ট্রিং "") একটি ব্যবহার ক্ষেত্র প্রস্থ এর nঅক্ষর। মূল printfনীতিগুলির ব্যাখ্যা মূলত এই প্রশ্নের (এবং উত্তর) আওতার বাইরে; আমি printfডকুমেন্টেশন পড়ার বা এসও তে আপনার নিজস্ব পৃথক প্রশ্ন জিজ্ঞাসা করার পরামর্শ দেব ।
জেমসডলিন

3
ব্যবহার-কেস দেখানোর জন্য ধন্যবাদ আমি বুঝতে পারি না কেন লোকেরা মূলত ম্যানুয়ালটিকে এস-তে অনুলিপি করে এবং কখনও কখনও এটি পুনরায় পাঠ করে। আমরা মানুষ এবং সব কিছু একটি কারণের জন্য সম্পন্ন হয়েছে যা সর্বদা উত্তরে ব্যাখ্যা করা উচিত। "কিছুই না" বলতে "শীতল শব্দের অর্থ শীতল" - প্রায় অকেজো জ্ঞান like
the_endian

1
@ এসপোসিক এটি অতিরিক্ত মাত্রার ইন্ডিরিয়ারেশন না জুড়েই সংশ্লেষিত এবং ত্রুটি-প্রবণ যথেষ্ট।
জেমসডলিন

18

আমি %nস্পেসিফায়ারের বাস্তব ব্যবহারের অনেক বাস্তব ব্যবহার দেখিনি , তবে আমি মনে করি এটি ফর্ম্যাট স্ট্রিং আক্রমণ সহ ওল্ডস্কুলের প্রিন্টফ দুর্বলতায় ব্যবহৃত হয়েছিল বেশ কিছুক্ষণ আগে ।

এমন কিছু যা গেছে

void authorizeUser( char * username, char * password){

    ...code here setting authorized to false...
    printf(username);

    if ( authorized ) {
         giveControl(username);
    }
}

যেখানে কোনও দূষিত ব্যবহারকারীর নামটি প্যারামিটারটি ফর্ম্যাট স্ট্রিং হিসাবে প্রিন্টফে পাস করার সুবিধা নিতে পারে এবং এর সংমিশ্রণ ব্যবহার করতে পারে %d,%c এবং কল স্ট্যাকের মধ্য দিয়ে যেতে বা ডাব্লু / ই এর করতে পারে এবং তারপরে সত্যিকারের মান হিসাবে অনুমোদিত ভেরিয়েবলটি পরিবর্তন করতে পারে।

হ্যাঁ এটি একটি রহস্যজনক ব্যবহার, তবে সুরক্ষা গর্তগুলি এড়ানোর জন্য ডেমন লেখার সময় সর্বদা জেনে রাখা কার্যকর? : ডি


1
ফর্ম্যাট স্ট্রিং %nহিসাবে চেক করা ইনপুট স্ট্রিংটি এড়ানো ছাড়া আরও অনেক কারণ রয়েছে printf
কিথ থমসন

13

থেকে এখানে আমরা দেখতে যে এটা এতদূর মুদ্রিত অক্ষরের সংখ্যা সঞ্চয় করে।

n আর্গুমেন্টটি একটি পূর্ণসংখ্যার পয়েন্টার হতে হবে যার মধ্যে এই কল দ্বারা এখন পর্যন্ত আউটপুটটিতে রচিত কোনও বাইটের fprintf()ফাংশনগুলির একটিতে লিখিত আছে । কোনও যুক্তি রূপান্তরিত হয় না।

একটি উদাহরণ ব্যবহার হবে:

int n_chars = 0;
printf("Hello, World%n", &n_chars);

n_charsতাহলে একটি মান হবে 12


10

এখনও পর্যন্ত সমস্ত উত্তরগুলি সেগুলি সম্পর্কে রয়েছে %nতবে কেন এটি প্রথমে কেউ চাইবে না। আমি sprintf/ এর সাথে এটি কিছুটা কার্যকর বলে মনে snprintfকরি যখন আপনার পরে পরিণতিতে স্ট্রিং বিভক্ত বা সংশোধন করার দরকার হতে পারে, যেহেতু সঞ্চিত মান ফলাফল স্ট্রিংয়ের মধ্যে একটি অ্যারে সূচক হয়। এই অ্যাপ্লিকেশনটি আরও অনেক বেশি কার্যকর, তবে sscanf, বিশেষতঃscanf পরিবারের প্রক্রিয়া করা অক্ষরের সংখ্যা নয় তবে ক্ষেত্রের সংখ্যা প্রদান করে না।

অন্য অপারেশনের অংশ হিসাবে একটি সংখ্যা মুদ্রণের সময় অন্য একটি সত্যই হ্যাকিশ ব্যবহার একই সময়ে বিনামূল্যে একটি সিউডো-লগ 10 পাচ্ছে।


+1 এর জন্য ব্যবহারের উল্লেখ করার জন্য %n, যদিও আমি "সমস্ত উত্তর ..." সম্পর্কে আলাদা হতে অনুরোধ করি। = পি
জেমসডলিন

1
খারাপ ছেলেরা আপনার
প্রিন্টফ

6
@ নোলোডার: কীভাবে? ব্যবহারের %n কোনো আক্রমণকারী থেকে দুর্বলতার একেবারে শূন্য বিপদ হয়েছে। দুর্ভাগ্যজনকভাবে কুখ্যাতিটি %nফর্ম্যাট আর্গুমেন্ট হিসাবে ফর্ম্যাট স্ট্রিংয়ের পরিবর্তে বার্তা স্ট্রিংটি পাস করার মূ .় অভ্যাসের সাথে সম্পর্কিত। %nবাস্তবে যখন ইচ্ছাকৃত বিন্যাসের স্ট্রিংটি ব্যবহৃত হচ্ছে তখন অবশ্যই এই পরিস্থিতি তৈরি হয় না ।
আর .. গীটহাব বন্ধ করুন ICE

% n আপনাকে মেমোরিতে লিখতে দেয়। আমি মনে করি আপনি ধরে নিচ্ছেন যে আক্রমণকারী সেই পয়েন্টারটি নিয়ন্ত্রণ করে না (আমি ভুল হতে পারি)। যদি আক্রমণকারী পয়েন্টারটি নিয়ন্ত্রণ করে (এটি প্রিন্টফের ঠিক আরও একটি প্যারামিটার), তবে সে / সে 4 বাইট রচনা সম্পাদন করতে পারে। সে লাভ করতে পারে কিনা তা আলাদা গল্প।
jww

8
@ নোলোডার: পয়েন্টারগুলির কোনও ব্যবহার সম্পর্কে এটি সত্য। লেখার জন্য কেউ "খারাপ লোকেরা আপনাকে ধন্যবাদ" বলে না *p = f();%nপয়েন্টার দ্বারা চিহ্নিত বস্তুর প্রতি ফলাফল লেখার কেবল অন্য উপায়, কেন পয়েন্টারটিকে নিজেরাই বিপজ্জনক বিবেচনা না করে "বিপজ্জনক" হিসাবে বিবেচনা করা উচিত?
আর .. গীটহাব বন্ধ করুন ICE

10

উইলের সাথে যুক্ত আর্গুমেন্টটিকে %nএকটি হিসাবে বিবেচনা করা হবে int*এবং এর সেই বিন্দুতে মুদ্রিত মোট অক্ষরের সংখ্যায় পূর্ণ রয়েছে printf


9

অন্য দিন আমি নিজেকে এমন পরিস্থিতিতে পেয়েছি যেখানে %nআমার সমস্যাটি সুন্দরভাবে সমাধান করবে। আমার আগের উত্তরটির মতো নয় নয়, এক্ষেত্রে আমি একটি ভাল বিকল্প তৈরি করতে পারি না।

আমার একটি জিইউআই নিয়ন্ত্রণ রয়েছে যা কিছু নির্দিষ্ট পাঠ্য প্রদর্শন করে। এই নিয়ন্ত্রণটি সেই পাঠ্যের কিছু অংশ সাহসী (বা তির্যক, বা আন্ডারলাইন ইত্যাদিতে) প্রদর্শন করতে পারে এবং অক্ষর সূচকগুলি শুরু এবং শেষ করে নির্দিষ্ট অংশটি নির্দিষ্ট করতে পারি।

আমার ক্ষেত্রে, আমি নিয়ন্ত্রণটি দিয়ে পাঠ্যটি তৈরি করছি snprintfএবং আমি চাই যে বিকল্পগুলির মধ্যে একটি সাহসী করা হোক made এই প্রতিস্থাপনের সূচনা এবং সূচকগুলি সন্ধান করা অ-তুচ্ছ কারণ কারণ:

  • স্ট্রিংটিতে একাধিক বিকল্প রয়েছে এবং বিকল্পগুলির একটির মধ্যে রয়েছে নির্বিচারে, ব্যবহারকারী-নির্দিষ্ট পাঠ্য। এর অর্থ হ'ল আমি যে সাবস্টিটিউশনের বিষয়ে যত্নশীল তার জন্য একটি পাঠ্য অনুসন্ধান করা সম্ভাব্য অস্পষ্ট is

  • ফর্ম্যাট স্ট্রিং স্থানীয়করণ হতে পারে এবং এটি $পজিশনাল ফর্ম্যাট স্পেসিফায়ারের জন্য পসিক্স এক্সটেনশন ব্যবহার করতে পারে । সুতরাং ফর্ম্যাট স্পেসিফায়ারের জন্য মূল ফর্ম্যাট স্ট্রিংটি অনুসন্ধান করা অ-তুচ্ছ।

  • স্থানীয়করণের দিকটিও এর অর্থ হ'ল আমি সহজেই একাধিক কলগুলিতে বিন্যাসের স্ট্রিংটি ভাঙ্গতে পারি না snprintf

সুতরাং নির্দিষ্ট প্রতিস্থাপনের আশেপাশের সূচকগুলি খুঁজে পাওয়ার সর্বাধিক সরল উপায় হ'ল:

char buf[256];
int start;
int end;

snprintf(buf, sizeof buf,
         "blah blah %s %f yada yada %n%s%n yakety yak",
         someUserSpecifiedString,
         someFloat,
         &start, boldString, &end);
control->set_text(buf);
control->set_bold(start, end);

আমি আপনাকে ব্যবহারের ক্ষেত্রে +1 দেব। তবে আপনি একটি নিরীক্ষণ ব্যর্থ হতে চলেছেন, তাই আপনার সাহসী পাঠ্যের শুরু এবং শেষ চিহ্নিত করার জন্য সম্ভবত অন্য কোনও উপায় তৈরি করা উচিত। তিনটি মনে হচ্ছে snprintfরিটার্ন মানগুলি পরীক্ষা করার সময় ঠিকঠাক কাজ করবে যেহেতু snprintfলিখিত অক্ষরের সংখ্যা প্রদান করে। হয়তো ভালো কিছু: int begin = snprintf(..., "blah blah %s %f yada yada", ...);এবং int end = snprintf(..., "%s", ...);তারপর লেজ: snprintf(..., "blah blah");
jww

3
@jww একাধিক snprintfকলগুলির ক্ষেত্রে সমস্যাটি হ'ল বিকল্পগুলি অন্য লোকেলে পুনরায় সাজানো যেতে পারে, সুতরাং সেগুলি ভেঙে ফেলা যায় না।
জেমসডলিন

উদাহরণের জন্য ধন্যবাদ। তবে আপনি কি ফিল্ডের ঠিক আগে আউটপুটটিকে সাহসী করতে একটি টার্মিনাল কন্ট্রোল সিক্যুয়েন্স লিখতে এবং তারপরে একটি সিকোয়েন্স লিখতে পারেন না? আপনি যদি টার্মিনাল নিয়ন্ত্রণ সিকোয়েন্সগুলিকে হার্ডকোড না করেন তবে আপনি সেগুলিকেও স্থিতিশীল (পুনরায় সাজানোযোগ্য) করতে পারেন।
পিএসকোকিক

1
@ স্পস্কিক আপনি যদি কোনও টার্মিনালে আউটপুট দিচ্ছেন। আপনি যদি উইন 32 সমৃদ্ধ-সম্পাদনা নিয়ন্ত্রণের সাথে কাজ করছেন, তবে আপনি যদি পিছনে যেতে না চান এবং টার্মিনাল নিয়ন্ত্রণের ক্রমগুলি পরবর্তীতে পার্স করতে না চান তবে তা সাহায্য করবে না। এটি ধরেও নিয়েছে যে আপনি বাকী বিকল্পে টার্মিনাল নিয়ন্ত্রণের অনুক্রমকে সম্মান করতে চান; যদি আপনি না করেন, তবে আপনাকে সেগুলি ফিল্টার করে বা পালাতে হবে। আমি বলছি না এটি করা অসম্ভব %n; আমি দাবি করছি যে %nবিকল্পের চেয়ে বেশি সহজ ব্যবহার করা।
জেমসডলিন

1

এটি কিছুই মুদ্রণ করে না। %nফর্ম্যাট স্ট্রিংয়ে উপস্থিত হওয়ার আগে কতগুলি অক্ষর মুদ্রিত হয়েছিল তা নির্ধারণ করতে ব্যবহৃত হয় , এবং সরবরাহিত ইনটকে আউটপুট দেয়:

#include <stdio.h>

int main(int argc, char* argv[])
{
    int resultOfNSpecifier = 0;
    _set_printf_count_output(1); /* Required in visual studio */
    printf("Some format string%n\n", &resultOfNSpecifier);
    printf("Count of chars before the %%n: %d\n", resultOfNSpecifier);
    return 0;
}

(এর জন্য ডকুমেন্টেশন_set_printf_count_output )


0

এটি সেই printf()ফাংশনে এ পর্যন্ত মুদ্রিত অক্ষরের সংখ্যার মূল্য সঞ্চয় করবে ।

উদাহরণ:

int a;
printf("Hello World %n \n", &a);
printf("Characters printed so far = %d",a);

এই প্রোগ্রামের আউটপুট হবে

Hello World
Characters printed so far = 12

যখন আমি আপনার কোডটি চেষ্টা করি তা আমাকে দেয়: হ্যালো ওয়ার্ল্ড অক্ষর এ পর্যন্ত ছাপা হয়েছে = 36 ,,,,, কেন 36 ?! আমি উইন্ডোজ মেশিনে একটি 32 বিবিটি জিসিসি ব্যবহার করি।
সিনা কারভান্দি

-6

% n হল C99, ভিসি ++ এর সাথে কাজ করে না।


2
%nসি 98 এ বিদ্যমান ছিল। এটি এমএসভিসির সাথে কাজ করে না কারণ মাইক্রোসফ্ট সুরক্ষা উদ্বেগের জন্য ডিফল্টরূপে এটি অক্ষম করেছে; _set_printf_count_outputএটি সক্ষম করার জন্য আপনাকে অবশ্যই প্রথমে কল করতে হবে। (মের্লিন মরগান-গ্রাহামের উত্তর দেখুন))
জেমসডলিন

না, সি 89 এই বৈশিষ্ট্যটি / ব্যাকডোরব্যাগটি সংজ্ঞায়িত করে না। কে অ্যান্ড আর + এএনএসআই-সি অ্যামাজন / প্রোগ্র্যামিং- ল্যাঙ্গুয়েজ ২ য় - ব্রায়ান- কর্নিগান / ডিপি /… দেখুন মন্তব্যগুলির জন্য ইউআরএল-ট্যাগার কোথায় ??
ব্যবহারকারী411313

4
আপনি কেবল ভুল। এটি printfকে ও আর এর দ্বিতীয় পরিশিষ্টের পরিশিষ্ট বি এর টেবিল বি -1 ( রূপান্তর) এ স্পষ্টভাবে তালিকাভুক্ত হয়েছে । (আমার অনুলিপিটির পৃষ্ঠা 244)) বা আইএসও সি 90 এর নির্দিষ্টকরণের বিভাগ 7.9.6.1 (পৃষ্ঠা 134) দেখুন।
জেমসডলিন

অ্যান্ড্রয়েড% n নির্দিষ্টকারীকেও সরিয়ে দিয়েছে।
jww

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.