সি / সি ++ ম্যাক্রো স্ট্রিং সংমিশ্রণ


121
#define STR1      "s"
#define STR2      "1"
#define STR3      STR1 ## STR2

এসআরটি 3 == "এস 1" যুক্ত করা কি সম্ভব? আপনি আর কোনও ম্যাক্রো ফাংশনে আর্গগুলি পাস করে এটি করতে পারেন। তবে কি কোন সরাসরি পথ আছে?


এটি # সংজ্ঞায়িত এসটি 3 এসআরটি 1 ## এসটি 2 হওয়া উচিত নয়
শ্রনিধি

এটি হয় না কারণ এটি স্ট্রফ 3টিকে প্রিপ্রোসেসিং টোকেন এসটিআরএসটিআর 2 হিসাবে সংজ্ঞা দেয়। এবং অন্য ম্যাক্রো ফাংশনে আরোগুলি পাঠানো কোনও উপকারে আসে না, কারণ স্ট্রিং লিটারালগুলি এক সাথে আটকানো যায় না - "s" "1" একটি বৈধ টোকেন নয়।
জিম বাল্টার

উত্তর:


157

যদি সেগুলি উভয় স্ট্রিং হয় তবে আপনি কেবল করতে পারেন:

#define STR3 STR1 STR2

প্রিপ্রোসেসর স্বয়ংক্রিয়ভাবে সংলগ্ন স্ট্রিংগুলিকে সম্মতি দেয়।

সম্পাদনা করুন:

নীচে উল্লিখিত হিসাবে, এটি প্রিপ্রোসেসর নয় বরং সংকলক যা সংমিশ্রণটি করে।


17
প্রযুক্তিগতভাবে স্ট্রিং কনটেনটেশন ভাষা পর্যায়ে করা হয়।
মার্টিন ইয়র্ক

47
প্রিপ্রোসেসর এ জাতীয় কোনও কাজ করে না। এটি সি ভাষা যথাযথ যা সংলগ্ন স্ট্রিং লিটারালগুলি এমনভাবে আচরণ করে যেন তারা একক স্ট্রিং আক্ষরিক হয়।
জিম বাল্টার

7
এটি কারিগরির চেয়েও বেশি - আপনি সংমিশ্রণ করতে L"a"এবং "b"পেতে পারেন না L"ab", তবে আপনি সংমিশ্রণ করতেL"a" এবং L"b"পেতে পারেন L"ab"
এমসাল্টারস

115

স্ট্রিং লিটারালগুলির জন্য আপনার এই ধরণের সমাধানের দরকার নেই, যেহেতু তারা ভাষা স্তরে সংমিশ্রিত হয় এবং এটি কোনওভাবেই কাজ করবে না কারণ "s" "1" একটি বৈধ প্রিপ্রোসেসর টোকেন নয়।

[সম্পাদনা করুন: দুর্ভাগ্যক্রমে বেশ কয়েকটি উত্সাহ পেয়েছে যে নীচে ভুল "জাস্ট ফর রেকর্ড" মন্তব্যের জবাবে, আমি উপরের বিবৃতিটির পুনরাবৃত্তি করব এবং পর্যবেক্ষণ করব যে প্রোগ্রামটি খণ্ডিত হয়েছে

#define PPCAT_NX(A, B) A ## B
PPCAT_NX("s", "1")

gcc এর প্রিপ্রোসেসিং পর্ব থেকে এই ত্রুটি বার্তাটি উত্পন্ন করে: ত্রুটি: "" s "" এবং "" 1 "" আটকানো একটি বৈধ প্রাকপ্রসেসিং টোকেন দেয় না

]

তবে সাধারণ টোকেন পেস্ট করার জন্য এটি ব্যবহার করে দেখুন:

/*
 * Concatenate preprocessor tokens A and B without expanding macro definitions
 * (however, if invoked from a macro, macro arguments are expanded).
 */
#define PPCAT_NX(A, B) A ## B

/*
 * Concatenate preprocessor tokens A and B after macro-expanding them.
 */
#define PPCAT(A, B) PPCAT_NX(A, B)

তারপরে, উদাহরণস্বরূপ, উভয় PPCAT_NX(s, 1)এবং PPCAT(s, 1)সনাক্তকারী উত্পাদন করুন s1, যদি না sম্যাক্রো হিসাবে সংজ্ঞায়িত হয়, যেখানে ক্ষেত্রে PPCAT(s, 1)উত্পাদিত হয় <macro value of s>1

থিম অবিরত এই ম্যাক্রোগুলি:

/*
 * Turn A into a string literal without expanding macro definitions
 * (however, if invoked from a macro, macro arguments are expanded).
 */
#define STRINGIZE_NX(A) #A

/*
 * Turn A into a string literal after macro-expanding it.
 */
#define STRINGIZE(A) STRINGIZE_NX(A)

তারপর,

#define T1 s
#define T2 1
STRINGIZE(PPCAT(T1, T2)) // produces "s1"

বিপরীতে,

STRINGIZE(PPCAT_NX(T1, T2)) // produces "T1T2"
STRINGIZE_NX(PPCAT_NX(T1, T2)) // produces "PPCAT_NX(T1, T2)"

#define T1T2 visit the zoo
STRINGIZE(PPCAT_NX(T1, T2)) // produces "visit the zoo"
STRINGIZE_NX(PPCAT(T1, T2)) // produces "PPCAT(T1, T2)"

8
কেবল রেকর্ডের জন্য, "s""1"সি (এবং সি ++) এ বৈধ। এগুলি দুটি টোকেন (স্ট্রিং লিটারালস) যে সংকলকটি নিজেই একত্রিত হবে এবং এক টোকেন হিসাবে হুমকির সম্মুখীন হবে।
শাহবাজ

4
আপনি আমার মন্তব্য এবং সি ভাষা উভয়ই ভুল বুঝে। আমি বললাম "s""1" isn't a valid token- এটা ঠিক; এটি যেমনটি আপনি বলেছেন, দুটি টোকেন। তবে তাদেরকে ## দিয়ে একত্রে টেক করা তাদেরকে দুটি টোকেন নয়, একটি একক প্রিপ্রোসেসিং টোকন হিসাবে তৈরি করে এবং তাই সংকলক একটি স্বাক্ষর করতে পারে না, বরং লেক্সার তাদের প্রত্যাখ্যান করবে (ভাষার জন্য ডায়াগনস্টিক প্রয়োজন)।
জিম বাল্টার

8
@ এমআর 5 মন্তব্যগুলি মনোযোগ সহকারে পড়ুন। ম্যাক্রো আর্গুমেন্ট হিসাবে পাস করা ম্যাক্রোর নামগুলি পাস হওয়ার আগে প্রসারিত হয় না। এগুলি অবশ্য ম্যাক্রোর শরীরে প্রসারিত হয়। সুতরাং A কে FRED হিসাবে সংজ্ঞায়িত করা হলে, STRINGIZE_NX (A) "A" তে প্রসারিত হয় তবে STRINGIZ (A) STRINGIZE_NX (FRED) এ প্রসারিত হয় যা "FRED" তে প্রসারিত হয়।
জিম বাল্টার

1
@ ভারতে ফলস্বরূপ স্ট্রিংটি হ'ল "পিপিসিএটি (টি 1, টি 2)" - যেমনটি প্রত্যাশিত ও পছন্দসই। এবং প্রত্যাশিত "এস 1" নয় - মোটেই প্রত্যাশিত নয়। আমাদের অতিরিক্ত ইন্ডায়ারেশন / বাসা বাঁধতে কেন দরকার? - কোড মন্তব্যগুলি, এবং 6 টি আপভোটের সাথে উপরে আমার মন্তব্য পড়ুন। শুধুমাত্র ম্যাক্রোগুলির দেহগুলি প্রসারিত হয়; ম্যাক্রো বডিগুলির বাইরে ম্যাক্রোগুলিতে প্রেরণের আগে বন্ধনীগুলির মধ্যে ম্যাক্রো যুক্তিগুলি প্রসারিত হয় না । সুতরাং STRINGIZE_NX(whatever occurs here)যাই হোক না কেন, ঘটুক বা এখানে যাই হোক না কেন তার ম্যাক্রো সংজ্ঞা নির্বিশেষে "এখানে যা কিছু ঘটে" তে প্রসারিত হয়।
জিম বাল্টার

1
@ ভারথ অবশ্যই এটি "নাম এ" মুদ্রণ করে না - এ প্যারামিটারের নাম, ম্যাক্রোর পক্ষে যুক্তি নয়, যা এএলএক্স X আপনি দাবি করেছেন if A is defined as FRED then STRINGIZE_NX(A) still expands to "FRED"- এটি মিথ্যা, এবং এটি আপনার পরীক্ষার মতো কিছু নয়। আপনি এই অধিকারটি না বোঝার বা না পাওয়ার জন্য কঠোর চেষ্টা করছেন এবং আমি আপনাকে আর উত্তর দেব না।
জিম বাল্টার

24

ইঙ্গিত: STRINGIZEউপরের ম্যাক্রোটি দুর্দান্ত, তবে যদি আপনি কোনও ভুল করেন এবং এর যুক্তিটি ম্যাক্রো না হয় - আপনার নামে একটি টাইপ ছিল, বা #includeশিরোনামের ফাইলে ভুলে গিয়েছিলেন - তবে সংকলকটি খুশির সাথে পছন্দসই ম্যাক্রোটির নামটি এতে রেখে দেবে কোন ত্রুটি সঙ্গে স্ট্রিং।

যদি আপনি মানা করেন যে যুক্তিটি STRINGIZEসর্বদা একটি সাধারণ সি মান সহ একটি ম্যাক্রো হয় তবে

#define STRINGIZE(A) ((A),STRINGIZE_NX(A))

এটি একবার প্রসারিত করবে এবং বৈধতার জন্য এটি যাচাই করবে, এটিকে বাতিল করবে এবং তারপরে আবার স্ট্রিংয়ে প্রসারিত করবে।

এর পরিবর্তে কেন STRINGIZE(ENOENT)শেষ হচ্ছে তা বুঝতে আমার কিছুটা সময় লেগেছে ... আমি এতে অন্তর্ভুক্ত ছিলাম না ।"ENOENT""2"errno.h


2
,অপারেটরের সঠিক ব্যবহারের জন্য গুরুত্বপূর্ণ পর্যবেক্ষণ এবং +1 + :)
জেসি চিশলম

2
স্ট্রিংয়ের বিষয়বস্তুটি একটি বৈধ সি এক্সপ্রেশন হওয়ার কারণ নেই particular আপনি যদি এটি করতে চান, আমি এটির জন্য আলাদা আলাদা নাম দেওয়ার পরামর্শ দিচ্ছি, যেমন STRINGIZE_EXPR।
জিম বাল্টার

সেই কৌশলটি বিচ্ছিন্ন হয়ে কাজ করতে পারে। তবে এটি সংমিশ্রিত হবে এমন স্ট্রিংয়ের ক্রম দেখতে কম্পাইলারকে বাধা দেয়। ( ((1),"1") "." ((2),"2")কেবল "" 1 "" এর পরিবর্তে সিকোয়েন্সগুলির ফলে । "" 2 ")
om:

কেবল অটোমোরফিক কী বলছে তা স্পষ্ট করার জন্য: মূল STRINGIZEসংজ্ঞা সহ, "The value of ENOENT is " STRINGIZE(ENOENT)কাজ করে, যেখানে "The value of ENOENT is" STRINGIZE_EXPR(X)একটি ত্রুটি জন্মায়।
জিম বাল্টার
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.