%n
সি তে বিন্যাস নির্দিষ্টকরণের ব্যবহার কী ? কেউ উদাহরণ দিয়ে ব্যাখ্যা করতে পারে?
%n
তোলে printf
এবং আপনি উদাহরণস্বরূপ এতে ব্রেনফাক বাস্তবায়ন করতে পারেন, github.com/HexHive/printbf এবং তেলশেল.
%n
সি তে বিন্যাস নির্দিষ্টকরণের ব্যবহার কী ? কেউ উদাহরণ দিয়ে ব্যাখ্যা করতে পারে?
%n
তোলে printf
এবং আপনি উদাহরণস্বরূপ এতে ব্রেনফাক বাস্তবায়ন করতে পারেন, github.com/HexHive/printbf এবং তেলশেল.
উত্তর:
কিছুই মুদ্রিত। যুক্তিটি অবশ্যই একটি স্বাক্ষরিত ইন্টার এর পয়েন্টার হওয়া উচিত, যেখানে এখন পর্যন্ত লেখা অক্ষরের সংখ্যা সংরক্ষণ করা আছে।
#include <stdio.h>
int main()
{
int val;
printf("blah %n blah\n", &val);
printf("val = %d\n", val);
return 0;
}
পূর্ববর্তী কোড মুদ্রণ:
blah blah
val = 5
int
সর্বদা স্বাক্ষরিত হয়।
n format specifies disabled
। কি কারণ?
এই উত্তরগুলির মধ্যে বেশিরভাগই ব্যাখ্যা %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
(এবং সম্ভবত ত্রুটিগুলি প্রবর্তন করা) বিতর্কের জন্য উন্মুক্ত))
&n
একটি পয়েন্টার ( &
অপারেটরের ঠিকানা); একটি পয়েন্টার প্রয়োজনীয় কারণ সি পাস-বাই-মান, এবং একটি পয়েন্টার ছাড়াই, printf
এর মানটি পরিবর্তন করতে পারে না n
। %*s
মধ্যে ব্যবহারের printf
বিন্যাস স্ট্রিং একটি ছাপে %s
সুনির্দিষ্টভাবে উল্লেখ করা (এই ক্ষেত্রে খালি স্ট্রিং ""
) একটি ব্যবহার ক্ষেত্র প্রস্থ এর n
অক্ষর। মূল printf
নীতিগুলির ব্যাখ্যা মূলত এই প্রশ্নের (এবং উত্তর) আওতার বাইরে; আমি printf
ডকুমেন্টেশন পড়ার বা এসও তে আপনার নিজস্ব পৃথক প্রশ্ন জিজ্ঞাসা করার পরামর্শ দেব ।
আমি %n
স্পেসিফায়ারের বাস্তব ব্যবহারের অনেক বাস্তব ব্যবহার দেখিনি , তবে আমি মনে করি এটি ফর্ম্যাট স্ট্রিং আক্রমণ সহ ওল্ডস্কুলের প্রিন্টফ দুর্বলতায় ব্যবহৃত হয়েছিল বেশ কিছুক্ষণ আগে ।
এমন কিছু যা গেছে
void authorizeUser( char * username, char * password){
...code here setting authorized to false...
printf(username);
if ( authorized ) {
giveControl(username);
}
}
যেখানে কোনও দূষিত ব্যবহারকারীর নামটি প্যারামিটারটি ফর্ম্যাট স্ট্রিং হিসাবে প্রিন্টফে পাস করার সুবিধা নিতে পারে এবং এর সংমিশ্রণ ব্যবহার করতে পারে %d
,%c
এবং কল স্ট্যাকের মধ্য দিয়ে যেতে বা ডাব্লু / ই এর করতে পারে এবং তারপরে সত্যিকারের মান হিসাবে অনুমোদিত ভেরিয়েবলটি পরিবর্তন করতে পারে।
হ্যাঁ এটি একটি রহস্যজনক ব্যবহার, তবে সুরক্ষা গর্তগুলি এড়ানোর জন্য ডেমন লেখার সময় সর্বদা জেনে রাখা কার্যকর? : ডি
%n
হিসাবে চেক করা ইনপুট স্ট্রিংটি এড়ানো ছাড়া আরও অনেক কারণ রয়েছে printf
।
থেকে এখানে আমরা দেখতে যে এটা এতদূর মুদ্রিত অক্ষরের সংখ্যা সঞ্চয় করে।
n
আর্গুমেন্টটি একটি পূর্ণসংখ্যার পয়েন্টার হতে হবে যার মধ্যে এই কল দ্বারা এখন পর্যন্ত আউটপুটটিতে রচিত কোনও বাইটেরfprintf()
ফাংশনগুলির একটিতে লিখিত আছে । কোনও যুক্তি রূপান্তরিত হয় না।
একটি উদাহরণ ব্যবহার হবে:
int n_chars = 0;
printf("Hello, World%n", &n_chars);
n_chars
তাহলে একটি মান হবে 12
।
এখনও পর্যন্ত সমস্ত উত্তরগুলি সেগুলি সম্পর্কে রয়েছে %n
তবে কেন এটি প্রথমে কেউ চাইবে না। আমি sprintf
/ এর সাথে এটি কিছুটা কার্যকর বলে মনে snprintf
করি যখন আপনার পরে পরিণতিতে স্ট্রিং বিভক্ত বা সংশোধন করার দরকার হতে পারে, যেহেতু সঞ্চিত মান ফলাফল স্ট্রিংয়ের মধ্যে একটি অ্যারে সূচক হয়। এই অ্যাপ্লিকেশনটি আরও অনেক বেশি কার্যকর, তবে sscanf
, বিশেষতঃscanf
পরিবারের প্রক্রিয়া করা অক্ষরের সংখ্যা নয় তবে ক্ষেত্রের সংখ্যা প্রদান করে না।
অন্য অপারেশনের অংশ হিসাবে একটি সংখ্যা মুদ্রণের সময় অন্য একটি সত্যই হ্যাকিশ ব্যবহার একই সময়ে বিনামূল্যে একটি সিউডো-লগ 10 পাচ্ছে।
%n
, যদিও আমি "সমস্ত উত্তর ..." সম্পর্কে আলাদা হতে অনুরোধ করি। = পি
%n
কোনো আক্রমণকারী থেকে দুর্বলতার একেবারে শূন্য বিপদ হয়েছে। দুর্ভাগ্যজনকভাবে কুখ্যাতিটি %n
ফর্ম্যাট আর্গুমেন্ট হিসাবে ফর্ম্যাট স্ট্রিংয়ের পরিবর্তে বার্তা স্ট্রিংটি পাস করার মূ .় অভ্যাসের সাথে সম্পর্কিত। %n
বাস্তবে যখন ইচ্ছাকৃত বিন্যাসের স্ট্রিংটি ব্যবহৃত হচ্ছে তখন অবশ্যই এই পরিস্থিতি তৈরি হয় না ।
*p = f();
। %n
পয়েন্টার দ্বারা চিহ্নিত বস্তুর প্রতি ফলাফল লেখার কেবল অন্য উপায়, কেন পয়েন্টারটিকে নিজেরাই বিপজ্জনক বিবেচনা না করে "বিপজ্জনক" হিসাবে বিবেচনা করা উচিত?
অন্য দিন আমি নিজেকে এমন পরিস্থিতিতে পেয়েছি যেখানে %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);
snprintf
রিটার্ন মানগুলি পরীক্ষা করার সময় ঠিকঠাক কাজ করবে যেহেতু snprintf
লিখিত অক্ষরের সংখ্যা প্রদান করে। হয়তো ভালো কিছু: int begin = snprintf(..., "blah blah %s %f yada yada", ...);
এবং int end = snprintf(..., "%s", ...);
তারপর লেজ: snprintf(..., "blah blah");
।
snprintf
কলগুলির ক্ষেত্রে সমস্যাটি হ'ল বিকল্পগুলি অন্য লোকেলে পুনরায় সাজানো যেতে পারে, সুতরাং সেগুলি ভেঙে ফেলা যায় না।
%n
; আমি দাবি করছি যে %n
বিকল্পের চেয়ে বেশি সহজ ব্যবহার করা।
এটি কিছুই মুদ্রণ করে না। %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;
}
এটি সেই printf()
ফাংশনে এ পর্যন্ত মুদ্রিত অক্ষরের সংখ্যার মূল্য সঞ্চয় করবে ।
উদাহরণ:
int a;
printf("Hello World %n \n", &a);
printf("Characters printed so far = %d",a);
এই প্রোগ্রামের আউটপুট হবে
Hello World
Characters printed so far = 12
% n হল C99, ভিসি ++ এর সাথে কাজ করে না।
%n
সি 98 এ বিদ্যমান ছিল। এটি এমএসভিসির সাথে কাজ করে না কারণ মাইক্রোসফ্ট সুরক্ষা উদ্বেগের জন্য ডিফল্টরূপে এটি অক্ষম করেছে; _set_printf_count_output
এটি সক্ষম করার জন্য আপনাকে অবশ্যই প্রথমে কল করতে হবে। (মের্লিন মরগান-গ্রাহামের উত্তর দেখুন))
printf
কে ও আর এর দ্বিতীয় পরিশিষ্টের পরিশিষ্ট বি এর টেবিল বি -1 ( রূপান্তর) এ স্পষ্টভাবে তালিকাভুক্ত হয়েছে । (আমার অনুলিপিটির পৃষ্ঠা 244)) বা আইএসও সি 90 এর নির্দিষ্টকরণের বিভাগ 7.9.6.1 (পৃষ্ঠা 134) দেখুন।