__FILE__ ম্যাক্রো পুরো পথ দেখায়


164

__FILE__সি তে উপলব্ধ স্ট্যান্ডার্ড পূর্বনির্ধারিত ম্যাক্রো ফাইলটির পুরো পথ দেখায়। পথ ছোট করার কোনও উপায় আছে কি? আমি এর পরিবর্তে বলতে চাই

/full/path/to/file.c

আমি দেখি

to/file.c

অথবা

file.c

18
প্রিপ্রোসেসর-কেবলমাত্র সমাধানটি খুঁজে পাওয়া সত্যিই দুর্দান্ত হবে। আমি ভীত যে স্ট্রিং অপারেশনগুলির উপর ভিত্তি করে পরামর্শগুলি রানটাইম এ কার্যকর হবে।
সিডলিওনার্ড

9
যেহেতু আপনি জিসিসি ব্যবহার করছেন, আমার মনে হয় আপনি __FILE__কমান্ড লাইনে যে ফাইল নামটি দিয়েছিলেন তা পরিবর্তন করে আপনি যা পরিবর্তন করতে পারেন । পরিবর্তে gcc /full/path/to/file.c, চেষ্টা করুন cd /full/path/to; gcc file.c; cd -;। অবশ্যই এর থেকে আরও কিছুটা যদি আপনি অন্তর্ভুক্ত পথ বা আউটপুট ফাইলের অবস্থানের জন্য জিসিসির বর্তমান ডিরেক্টরিতে নির্ভর করে থাকেন। সম্পাদনা: জিসিসি ডক্স যে সুপারিশ এটি সম্পূর্ণ পাথ, এর না ইনপুট ফাইল নাম যুক্তি, কিন্তু যে আমি Cygwin উপর জিসিসি 4.5.3 কি দেখছি না। সুতরাং আপনি পাশাপাশি এটি লিনাক্সে চেষ্টা করে দেখতে পারেন।
স্টিভ জেসোপ

4
জিসিসি ৪.৪.১ (বিশেষত আর্ম-নো-ইবি-র জন্য নির্মিত) এর কমান্ড লাইনে ফাইলের নামের সঠিক পাঠ্যটি ব্যবহার করে। আমার ক্ষেত্রে এটি বর্তমান ডিরেক্টরিটি কোথাও বুদ্ধিমান (প্রকল্পের ফাইলের অবস্থান, সম্ভবত?) না রেখে বা সেখান থেকে আপেক্ষিক পথগুলি ব্যবহার করার পরিবর্তে সমস্ত ফাইলের নাম সহ পুরোপুরি যোগ্যতার সাথে জিসিসির অনুরোধ করা আইডিইয়ের দোষ ছিল। আমার সন্দেহ হয় যে অনেকগুলি আইডিই এটি করে (বিশেষত উইন্ডোজে) কোনও জিইআইআই অ্যাপ্লিকেশনটির জন্য "বর্তমান" ডিরেক্টরিটি সত্যই কোথায় তা বোঝানোর সাথে সম্পর্কিত কোনও ধরণের অস্বস্তি ছাড়াই।
RBerteig

3
@ স্টিভ জেসোপ - আশা করি আপনি এই মন্তব্যটি পড়েছেন। আমার এমন পরিস্থিতি রয়েছে যেখানে আমি __FILE__মুদ্রিত হিসাবে দেখতে পাই ../../../../../../../../rtems/c/src/lib/libbsp/sparc/leon2/../../shared/bootcard.cএবং আমি জানতে চাই যেখানে জিসিসি ফাইলটি এমনভাবে সংকলন করেছে যে এই ফাইলটি তুলনামূলকভাবে এটি প্রদর্শিত হওয়ার মতো অবস্থিত।
চান কিম

1
এই প্রশ্নটি লিঙ্কযুক্তটির একটি অর্থ নয়। একটির জন্য, লিঙ্কযুক্তটি প্রায় সি ++ এর সম্পর্কে, এবং উত্তরগুলি ফলস্বরূপ সি ++ ম্যাক্রো এসোটেরিকার অন্তর্ভুক্ত। দ্বিতীয়ত, ওপির প্রশ্নের মধ্যে এমন কোনও কিছুই নেই যা ম্যাক্রো সমাধানকে বাধ্যতামূলক করে। এটি কেবলমাত্র এক সমস্যা চিহ্নিত করে এবং একটি মুক্ত সমাপ্ত প্রশ্ন জিজ্ঞাসা করে।
অধ্যাপক ফ্যালকেন

উত্তর:


166

চেষ্টা

#include <string.h>

#define __FILENAME__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)

উইন্ডোজের জন্য '/' এর পরিবর্তে '\\' ব্যবহার করুন।


13
/উইন্ডোজ মধ্যে একটি বৈধ পাথ বিভাজক।
হ্যান্স প্যাস্যান্ট

11
/ক্রিয়েটফাইলে () এবং এর আগে পাস করা ফাইল নামের একটি বৈধ পথ বিভাজক। যাইহোক, এর অর্থ সর্বদা এই নয় যে আপনি /উইন্ডোতে যে কোনও জায়গায় ব্যবহার করতে পারবেন যেহেতু /কমান্ড প্রম্পটে আর্গুমেন্ট লিড হিসাবে ব্যবহার করার একটি traditionতিহ্য রয়েছে (সিপিএম থেকে উত্তরাধিকার সূত্রে প্রাপ্ত) । তবে কোনও গুণমানের সরঞ্জামটি ব্যবহার করতে পরিচালিত লোকদের জন্য কোনও সমস্যা এড়াতে স্ল্যাশ এবং ব্যাকস্ল্যাশ অক্ষর উভয় ক্ষেত্রেই ফাইলের নামগুলি বিভক্ত করা সতর্ক থাকবে /
আরবার্টেইগ

5
@ অ্যামিগিয়েবল ক্লার্কক্যান্ট, আপনি একই ফাইলের নামে উভয় বিভাজককে মিশ্রিত করতে পারবেন না।
আরবার্টেইগ

2
আপনার প্ল্যাটফর্ম যদি এটি সমর্থন করে তবে char* fileName = basename(__FILE__); এটি অবশ্যই লিনাক্স এবং ওএস এক্সে রয়েছে, তবে উইন্ডোজ সম্পর্কে জানেন না।
জেরেমিপি

14
এটি সংক্ষিপ্ত করা যেতে পারে strrchr("/" __FILE__, '/') + 1। "/" তে __FILE__প্রিণ্ডেন্ড করে স্ট্রিচারকে কিছু খুঁজে পাওয়ার নিশ্চয়তা দেওয়া হয়, এবং এভাবে শর্তসাপেক্ষ?: আর প্রয়োজন হয় না।
urউরোবুরɳ

54

আপনি যদি চাক ব্যবহার করছেন তবে এখানে একটি টিপস's থেকে: http://public.kitware.com/pipermail/cmake/2013- জানুয়ারি 053117.html

আমি টিপটি অনুলিপি করছি তাই এটি এই পৃষ্ঠায় রয়েছে:

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D__FILENAME__='\"$(subst
  ${CMAKE_SOURCE_DIR}/,,$(abspath $<))\"'")

আপনি যদি জিএনইউ মেক ব্যবহার করছেন তবে আমি নিজের মেকফিলগুলিতে এটি প্রসারিত করতে না পারার কোনও কারণ আমি দেখতে পাচ্ছি না। উদাহরণস্বরূপ, আপনার কাছে এটির মতো একটি লাইন থাকতে পারে:

CXX_FLAGS+=-D__FILENAME__='\"$(subst $(SOURCE_PREFIX)/,,$(abspath $<))\"'"

$(SOURCE_PREFIX)আপনি যে উপসর্গটি মুছে ফেলতে চান তা কোথায় ।

তারপর ব্যবহার __FILENAME__স্থানে __FILE__


11
আমি ভীত তারপর এই জন্য কাজ করে না থাকি ফাইল হেডার ফাইলে রেফারেন্সড।
বায়ান হুয়াং

2
@ বাইয়ানহুয়াংয়ের সাথে সম্মত হন তবে মন্তব্যটি পরিষ্কার কিনা তা নিশ্চিত নন। __FILE__একটি সাধারণ প্রিপ্রোসেসর প্রতীক নয়, এটি বর্তমান ফাইলে পরিবর্তিত হয় প্রায়শই বর্তমান ফাইলের নাম নির্ধারণের জন্য ব্যবহৃত হয় (শিরোনাম বা উত্স মডিউল)। এই __FILENAME__শুধুমাত্র দূরতম উৎস হবে
nhed

3
এই উত্তরের সমাধান বহনযোগ্য নয় কারণ এটি বোর্ন শেল ব্যবহার করে পালিয়ে যায়। এটি পরিষ্কার এবং পোর্টেবল উপায়ে প্রয়োগ করতে সিএমকে ব্যবহার করা আরও ভাল। এখানে Define_file_basename_for_Source ম্যাক্রোর উত্তর দেখুন ।
কলিন ডি বেনেট

3
এর জিএনইউ মেক রূপটি হ'ল সিএফএলএগএস + = -ডি__এফআইএলএফ __ = \ "not (নটডির) <) \"
সিটিফলি

4
@ ফায়ারগুরাফিকু এম্বেড করা প্ল্যাটফর্মগুলিতে, কোডের আকার প্রায়শই গতির চেয়ে বাধা হয়ে থাকে। আপনার যদি প্রতিটি ফাইলে ডিবাগ স্টেটমেন্ট থাকে তবে তা পূর্ণ-পাথ স্ট্রিং সহ দ্রুত ফাইল-আকারের বেলুন আপ করতে পারে। আমি এই মুহুর্তে এই জাতীয় প্ল্যাটফর্মটি নিয়ে কাজ করছি এবং __FILE__সর্বত্র রেফারেন্সিং কোড-স্পেসের বাইরে চলে যাচ্ছে।
শ্রীমতী

26

আমি কেবল এটির দুর্দান্ত সমাধানের কথা চিন্তা করেছি যা উত্স এবং শিরোনাম ফাইল উভয়ের সাথেই কাজ করে, খুব কার্যকরী এবং সংকলক-নির্দিষ্ট এক্সটেনশন ছাড়াই সমস্ত প্ল্যাটফর্মে সংকলনের সময় কাজ করে। এই সমাধানটি আপনার প্রকল্পের আপেক্ষিক ডিরেক্টরি কাঠামো সংরক্ষণ করে, তাই আপনি জানেন যে ফাইলটি কোন ফোল্ডারে রয়েছে এবং কেবলমাত্র আপনার প্রকল্পের মূলের সাথে সম্পর্কিত।

আপনার বিল্ড সরঞ্জামটি দিয়ে উত্স ডিরেক্টরিটির আকার পেতে এবং এটি কেবল __FILE__ম্যাক্রোর সাথে যুক্ত করে ডিরেক্টরিটি সম্পূর্ণভাবে সরিয়ে ফেলা হয় এবং কেবলমাত্র আপনার উত্স ডিরেক্টরিতে ফাইল নামটি দেখানো হয় The

নিম্নলিখিত উদাহরণটি সিএমকে ব্যবহার করে প্রয়োগ করা হয়েছে, তবে এটি অন্য কোনও বিল্ড সরঞ্জামগুলির সাথে কাজ করবে না এমন কোনও কারণ নেই, কারণ কৌশলটি খুব সহজ।

CMakeLists.txt ফাইলটিতে, এমন ম্যাক্রো সংজ্ঞায়িত করুন যা সিএমকে আপনার প্রকল্পের পথটির দৈর্ঘ্য রয়েছে:

# The additional / is important to remove the last character from the path.
# Note that it does not matter if the OS uses / or \, because we are only
# saving the path size.
string(LENGTH "${CMAKE_SOURCE_DIR}/" SOURCE_PATH_SIZE)
add_definitions("-DSOURCE_PATH_SIZE=${SOURCE_PATH_SIZE}")

আপনার উত্স কোডে, একটি __FILENAME__ম্যাক্রো সংজ্ঞায়িত করুন যা কেবল ম্যাক্রোতে উত্স পথের আকার যুক্ত করে __FILE__:

#define __FILENAME__ (__FILE__ + SOURCE_PATH_SIZE)

তারপরে কেবল ম্যাক্রোর পরিবর্তে এই নতুন ম্যাক্রোটি ব্যবহার করুন __FILE__। এটি কাজ করে কারণ __FILE__আপনার সিএমকে উত্স দিরের পথে সর্বদা পথটি শুরু হবে। __FILE__স্ট্রিং থেকে এটিকে অপসারণ করে প্রিপ্রেসেসর সঠিক ফাইলের নাম নির্দিষ্ট করে দেওয়ার যত্ন নেবে এবং এটি সমস্ত আপনার সিএমকে প্রকল্পের মূলের সাথে সম্পর্কিত হবে।

আপনি যদি পারফরম্যান্স সম্পর্কে চিন্তা করেন তবে এটি ব্যবহারের মতো দক্ষ __FILE__, কারণ উভয়ই __FILE__এবংSOURCE_PATH_SIZE টাইপ কনস্ট্যান্ট সংকলন হিসাবে পরিচিত, তাই এটি সংকলক দ্বারা অপ্টিমাইজ করা যায়।

এটি ব্যর্থ হওয়ার একমাত্র জায়গা হ'ল যদি আপনি এটি উত্পন্ন ফাইলগুলিতে ব্যবহার করেন এবং সেগুলি অফ-সোর্স বিল্ড ফোল্ডারে থাকে। তারপরে আপনাকে সম্ভবত CMAKE_BUILD_DIRপরিবর্তকের পরিবর্তে আরও একটি ম্যাক্রো তৈরি করতে হবে CMAKE_SOURCE_DIR


4
আমি প্রথমে বুঝতে পারিনি। আমি উদাহরণগুলি কোড আপ করেছি এবং এগুলিকে জিসিসি এবং কলঙ্কের বিরুদ্ধে চালিয়েছি এবং তারা কাজ করে। আমি কেবল বিভিন্ন আক্ষরিক সংখ্যাসূচক মান যুক্ত করার জন্যও পরীক্ষা করেছি এবং এটি আমার প্রত্যাশা অনুযায়ী আচরণ করে। তারপর অবশেষে এটি আমার উপর ছড়িয়ে পড়ে। __FILE__বাইটের অ্যারের পয়েন্টার। সুতরাং একটি সংখ্যার আক্ষরিক যোগ করা কেবল পয়েন্টার সংযোজন। খুব চালাক @ রেনাটোউচচ
ড্যানিয়েল

এটি কেবল তখনই কাজ করে যদি কোনও উত্স ফাইল cmake তালিকা ডিরেক্টরিতে থাকে। যদি কোনও উত্স ফাইল বাইরে থাকে তবে এটি ভেঙে যাবে, আক্ষরিক স্ট্রিংয়ের বাইরে অ্যাক্সেস থাকতে পারে। সুতরাং যে সাবধান।
অ্যান্ড্রি

এটি আসলে কোডের আকার হ্রাস করে না। আমার ধারণা পুরো পথটি এখনও বাইনারিতে সংকলিত আছে, কেবল পয়েন্টারটি সংশোধন করা হয়েছে।
Tarion

__FILE__ম্যাক্রো এবং SOURCE_PATH_SIZE ম্যাক্রোগুলি উভয়ই সংকলন সময়ে পরিচিত ধ্রুবক। আমি আশা করছিলাম যে আধুনিক অপ্টিমাইজ করা সংকলকরা স্ট্রিংয়ের সেই অংশটি ব্যবহৃত হয়নি তা সনাক্ত করতে সক্ষম হন এবং কেবল এটি বাইনারি থেকে সরান। যাইহোক, আমি মনে করি না এই কয়েকটি বাইটগুলি বাইনারি আকারে একটি উল্লেখযোগ্য পার্থক্য তৈরি করবে, তাই আমি সত্যিই এটি সম্পর্কে যত্ন নেব না।
রেনাটোসচ

@ রেনাটোসচ প্রকল্পে আমি যে প্রকল্পে কাজ করছি তার একটি পরিবর্তন রয়েছে যা কেবলমাত্র ফাইলের নাম নির্দিষ্ট করে, তবে শিরোনামকেও সি ফাইলের নাম দেওয়ার অসুবিধা রয়েছে। পরিবর্তনগুলি পুনরুত্পাদনযোগ্য বিল্ডগুলি পাওয়ার জন্য করা হয়েছিল। সুতরাং-ও 2 সহ জিসিসির সাথে, স্ট্রিংটি কী সত্যই অনুকূলিত হবে এবং বিল্ডটি পুনরুত্পাদনযোগ্য করে তুলবে?
পল স্টেলিয়ান

18

বিশুদ্ধরূপে এখানে সময় সংকলন সমাধান করুন। এটি sizeof()একটি স্ট্রিং আক্ষরিক তার দৈর্ঘ্য +1 প্রদান করে যে উপর ভিত্তি করে ।

#define STRIPPATH(s)\
    (sizeof(s) > 2 && (s)[sizeof(s)-2] == '/' ? (s) + sizeof(s) - 1 : \
    sizeof(s) > 3 && (s)[sizeof(s)-3] == '/' ? (s) + sizeof(s) - 2 : \
    sizeof(s) > 4 && (s)[sizeof(s)-4] == '/' ? (s) + sizeof(s) - 3 : \
    sizeof(s) > 5 && (s)[sizeof(s)-5] == '/' ? (s) + sizeof(s) - 4 : \
    sizeof(s) > 6 && (s)[sizeof(s)-6] == '/' ? (s) + sizeof(s) - 5 : \
    sizeof(s) > 7 && (s)[sizeof(s)-7] == '/' ? (s) + sizeof(s) - 6 : \
    sizeof(s) > 8 && (s)[sizeof(s)-8] == '/' ? (s) + sizeof(s) - 7 : \
    sizeof(s) > 9 && (s)[sizeof(s)-9] == '/' ? (s) + sizeof(s) - 8 : \
    sizeof(s) > 10 && (s)[sizeof(s)-10] == '/' ? (s) + sizeof(s) - 9 : \
    sizeof(s) > 11 && (s)[sizeof(s)-11] == '/' ? (s) + sizeof(s) - 10 : (s))

#define __JUSTFILE__ STRIPPATH(__FILE__)

প্রকল্পের সর্বাধিক সংবেদনশীল ফাইলের নামটিতে শর্তসাপেক্ষ অপারেটর ক্যাসকেড প্রসারিত করতে দ্বিধা বোধ করবেন। পাথের দৈর্ঘ্য কোনও বিষয় নয়, যতক্ষণ আপনি স্ট্রিংয়ের শেষে থেকে যথেষ্ট পরিমাণে পরীক্ষা করেন।

আমি দেখতে পাব যে আমি ম্যাক্রো পুনঃবৃদ্ধির সাথে কোনও হার্ড-কোডড দৈর্ঘ্য না থাকলে একই ধরণের ম্যাক্রো পাব কিনা ...


3
দুর্দান্ত উত্তর। -O1কমপাইল-টাইম হতে আপনার এটি কমপক্ষে ব্যবহার করতে হবে।
ডিজিটাল ট্রমা

1
এটা কি পিছনের দিকে নয়? আপনি '/' এর শেষ ঘটনাটি খুঁজতে চান , যার অর্থ আপনার sizeof(s) > 2চেকটি শুরু করা উচিত । এছাড়াও, এটি আমার জন্য সংকলনের সময়, ওএস-এ কাজ করে না। সম্পূর্ণ পাথ স্ট্রিংগুলি আউটপুট বাইনারিতে উপস্থিত ছিল।
শ্রীমতী 14

15

কমপক্ষে জিসিসি-র জন্য , কম্পাইলারের কমান্ড লাইনে উল্লিখিত__FILE__ ফাইল পাথের মান । আপনি যদি এটির মতো সংকলন করেন :file.c

gcc -c /full/path/to/file.c

__FILE__প্রসারিত হবে "/full/path/to/file.c"। আপনি যদি পরিবর্তে এটি করেন:

cd /full/path/to
gcc -c file.c

তারপরে ন্যায়বিচারে __FILE__প্রসারিত হবে "file.c"

এটি ব্যবহারিক হতে পারে বা নাও হতে পারে।

সি স্ট্যান্ডার্ডটির এই আচরণের প্রয়োজন হয় না। এ সম্পর্কে __FILE__যা বলা হয় তা হ'ল এটি "বর্তমান উত্সের অনুমানিত নাম (লে (একটি চরিত্রের স্ট্রিং আক্ষরিক)" এ প্রসারিত হয়।

একটি বিকল্প #lineনির্দেশিকা ব্যবহার করা হয় । এটি বর্তমান লাইন নম্বর এবং optionচ্ছিকভাবে উত্স ফাইলের নামটিকে ওভাররাইড করে। আপনি যদি ফাইলের নামটি ওভাররাইড করতে চান তবে লাইন নম্বরটি একা ছেড়ে যান, __LINE__ম্যাক্রোটি ব্যবহার করুন ।

উদাহরণস্বরূপ, আপনি এটি শীর্ষের নিকটে যোগ করতে পারেন file.c:

#line __LINE__ "file.c"

এটির সাথে একমাত্র সমস্যাটি হ'ল এটি নিম্নলিখিত রেখায় নির্দিষ্ট লাইন নম্বরটি নির্ধারণ করে এবং প্রথম যুক্তিটি #lineএকটি ডিজিটিক সিকোয়েন্স হতে হয় যাতে আপনি এর মতো কিছু করতে না পারেন

#line (__LINE__-1) "file.c"  // This is invalid

#lineনির্দেশে থাকা ফাইলটির নামটি ফাইলের প্রকৃত নামের সাথে মিল রয়েছে তা নিশ্চিত করে অনুশীলন করা হয়েছে।

কমপক্ষে জিসিসির জন্য, এটি ডায়াগনস্টিক বার্তাগুলিতে উল্লিখিত ফাইলের নামটিকেও প্রভাবিত করবে।


1
কেথ থম্পসন এটি দুর্দান্ত সমাধান, আপনাকে ধন্যবাদ। একমাত্র সমস্যা হ'ল মনে হচ্ছে যে এই ম্যাক্রো __LINE__একের সাথে মান কেটে দেয় । __LINE__লাইন xভঙ্গিতে তাই মূল্যায়ন করা হয় x-1। কমপক্ষে জিসিসি 5.4 সহ।
elklepo

1
@ ক্লেপাক: আপনি ঠিক বলেছেন, এবং এটি আদর্শ আচরণ। নির্দেশিকাটি "প্রয়োগের সাথে আচরণের কারণ হিসাবে সূত্রের রেখার নীচের ক্রমটি উত্স রেখার সাথে শুরু হয় যার একটি সংখ্যা রেখা দ্বারা উল্লিখিত একটি লাইন নম্বর রয়েছে"। এবং এটি একটি ডিজিটিক সিকোয়েন্স হতে হবে , যাতে আপনি ব্যবহার করতে পারবেন না #line __LINE__-1, "file.c"। আমি আমার উত্তর আপডেট করব।
কিথ থম্পসন

1
এটি অন্য সংকলক যেমন ক্ল্যাং, এমএসভিসি, বা ইনটেল সি সংকলকগুলির জন্য কীভাবে হবে?
ফ্রাঙ্কলিন ইউ

7

পার্টিতে কিছুটা দেরি হলেও জিসিসির পক্ষে -ffile-prefix-map=old=newবিকল্পটি একবার দেখুন :

পুরানো ডিরেক্টরিতে থাকা ফাইলগুলি সংকলন করার সময়, সংকলনের ফলস্বরূপ তাদের সাথে যে কোনও রেফারেন্স রেকর্ড করুন যেন ফাইলগুলি ডিরেক্টরিতে নতুন পরিবর্তে থাকে। এই বিকল্পটি নির্দিষ্ট করে দেওয়া সমস্ত স্বতন্ত্র -f*-prefix-mapবিকল্পগুলি নির্দিষ্ট করার সমান । এটি পুনরুত্পাদনযোগ্য বিল্ডগুলি তৈরি করতে ব্যবহৃত হতে পারে যা অবস্থানের স্বাধীন। এছাড়াও দেখুন -fmacro-prefix-mapএবং -fdebug-prefix-map

সুতরাং আমার জেনকিনস বিল্ডগুলির জন্য আমি যুক্ত করব -ffile-prefix-map=${WORKSPACE}/=/এবং অন্য একটি স্থানীয় দেব প্যাকেজ ইনস্টল উপসর্গটি সরিয়ে ফেলব ।

দ্রষ্টব্য দুর্ভাগ্যক্রমে -ffile-prefix-mapবিকল্পটি জিসিসি 8-তে কেবলমাত্র উপলভ্য, -fmacro-prefix-mapযা আমি মনে করি , __FILE__অংশটি করে। কারণ, বলুন, জিসিসি 5, আমাদের কেবল এটিই -fdebug-prefix-map(প্রভাবিত হয় না) __FILE__


1
বিকল্প -ffile-prefix-mapপ্রকৃতপক্ষে উভয় -fdebug-prefix-mapএবং -fmacro-prefix-mapবিকল্প বোঝায় । আরও দেখুন এ রেফারেন্স reproducible-builds.org/docs/build-path জিসিসি বাগ গানগুলি -fmacro-prefix-mapএবং -ffile-prefix-mapহয় gcc.gnu.org/bugzilla/show_bug.cgi?id=70268
Lekensteyn

6
  • সি ++ 11
  • msvc2015u3, gcc5.4, clang3.8.0

    template <typename T, size_t S>
    inline constexpr size_t get_file_name_offset(const T (& str)[S], size_t i = S - 1)
    {
        return (str[i] == '/' || str[i] == '\\') ? i + 1 : (i > 0 ? get_file_name_offset(str, i - 1) : 0);
    }
    
    template <typename T>
    inline constexpr size_t get_file_name_offset(T (& str)[1])
    {
        return 0;
    }

    '

    int main()
    {
         printf("%s\n", &__FILE__[get_file_name_offset(__FILE__)]);
    }

কোড অফসেট একটি সংকলন সময় জেনারেট করে যখন:

  • gcc: কমপক্ষে gcc6.1 + -O1
  • msvc: কনস্টেক্সপ্র ভেরিয়েবলের ফলাফল রাখুন:

      constexpr auto file = &__FILE__[get_file_name_offset(__FILE__)];
      printf("%s\n", file);
  • clang: সময় মূল্যায়ন সংকলন না জেদ

সমস্ত 3 সংকলককে জোর করার জন্য একটি কৌশল রয়েছে যা অক্ষম অপটিমাইজেশন সহ ডিবাগ কনফিগারেশনে এমনকি সময় মূল্যায়ন সংকলন করে:

    namespace utility {

        template <typename T, T v>
        struct const_expr_value
        {
            static constexpr const T value = v;
        };

    }

    #define UTILITY_CONST_EXPR_VALUE(exp) ::utility::const_expr_value<decltype(exp), exp>::value

    int main()
    {
         printf("%s\n", &__FILE__[UTILITY_CONST_EXPR_VALUE(get_file_name_offset(__FILE__))]);
    }

https://godbolt.org/z/u6s8j3


ম্যান, এটি সুন্দর এবং এটি কাজ করে, আপনাকে ধন্যবাদ! কেন এই উত্তর এত আন্ডাররেটেড হয় জানি না।
রোমান

5

ভিসি, যখন ব্যবহার /FC, __FILE__, পূর্ণ পথে বিস্তৃতি ছাড়া /FCবিকল্প __FILE__ফাইলের নাম বিস্তৃতি ঘটে। রেফ: এখানে


4

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


1
strrchrউত্তর -এর সম্ভাব্য প্রাক প্রসেসর দ্বারা নয় অবশ্যই এখনও যদিও, কম্পাইল-সময়ে নির্ণিত যেতে পারে। আমি জানি না যে জিসিসি আসলে এটি করে কিনা, আমি চেক করি নি, তবে আমি নিশ্চিত যে এটি strlenসংকলন-সময়ে স্ট্রিং লিটারেলের গণনা করে ।
স্টিভ জেসোপ

@ স্টিভ - হতে পারে, তবে এটি সংকলক নির্দিষ্ট আচরণের উপর একটি বড় নির্ভরতা।
শন

আমি এটি একটি বড় নির্ভরতা বলে মনে করি না, কারণ আমি খুব সন্দেহ করি যে এই কোডটি কার্য-সমালোচনা। এবং যদি এটি হয় তবে এটিকে লুপ থেকে সরিয়ে নিন। এটি একটি বিশাল চুক্তি হিসাবে, যেখানে আপনার একেবারে বেসনেম যুক্ত স্ট্রিং আক্ষরিক প্রয়োজন , উত্সের উপর দিয়ে কিছু স্ক্রিপ্ট চালিয়ে আপনি সম্ভবত নির্মাণের সময় সঠিক স্ট্রিংটি গণনা করতে পারেন ।
স্টিভ জেসোপ

5
এটি পারফরম্যান্স সমালোচনামূলক নাও হতে পারে তবে এটিকে সহজেই গোপনীয়তার সমালোচনা হিসাবে দেখা যেতে পারে। প্রকাশিত EXE ফাইলে হিমায়িত স্ট্রিংগুলিতে আমার প্রতি গ্রাহক সাংগঠনিক অনুশীলনগুলি প্রকাশ করার কোনও সঠিক কারণ নেই। সবচেয়ে খারাপ, কোনও গ্রাহকের পক্ষে তৈরি করা অ্যাপ্লিকেশনগুলির জন্য, এই স্ট্রিংগুলি এমন জিনিস প্রকাশ করতে পারে যা আমার গ্রাহক পছন্দ করতে পারে না, যেমন তাদের নিজস্ব পণ্যের লেখক না হওয়া। যেহেতু __FILE__সুস্পষ্টভাবে আহ্বান জানানো হয়েছে assert(), তাই এই ফাঁস অন্য কোনও ছাড়পত্র ছাড়াই ঘটতে পারে।
আরবার্টেইগ

@ আরবার্টইগের __FILE__নিজের নামের নামটি গ্রাহককে পছন্দ নাও হতে পারে এমন জিনিসগুলি প্রকাশ করতে পারে, তাই __FILE__এটি যে কোনও জায়গায় ব্যবহার করা - এটিতে সম্পূর্ণ পরম পথ বা কেবল বেসনাম রয়েছে - আপনার একই বিষয়গুলির মধ্যে একই বিষয় রয়েছে has এই পরিস্থিতিতে সমস্ত আউটপুট যাচাই করা দরকার এবং গ্রাহকদের আউটপুট দেওয়ার জন্য একটি বিশেষ এপিআই চালু করা উচিত। বাকি আউটপুটটি / dev / NULL এ ফেলে দিতে হবে বা স্টডআউট এবং স্টার্ডার বন্ধ করতে হবে। :-)
টিচেন

4

বেসনাম () ফাংশনটি ব্যবহার করুন বা আপনি উইন্ডোতে থাকলে, _স্প্লিটপথ () ব্যবহার করুন

#include <libgen.h>

#define PRINTFILE() { char buf[] = __FILE__; printf("Filename:  %s\n", basename(buf)); }

এছাড়াও man 3 basenameএকটি শেল চেষ্টা করুন ।


2
@mahmood: char file_copy[] = __FILE__; const char *filename = basename(__FILE__);। অনুলির কারণ হ'ল বেসনেম ইনপুট স্ট্রিংটি পরিবর্তন করতে পারে ify আপনাকে আরও নজর রাখতে হবে যে ফলাফল পয়েন্টারটি basenameআবার কল না করা পর্যন্ত ভাল । এর অর্থ এটি থ্রেড-নিরাপদ নয়।
স্টিভ জেসোপ

@ স্টিভ জেসোপ, আহ আমি ভুলে গেছি সত্য।
অধ্যাপক ফ্যালকেন

1
@ অভিবাসী: ন্যায়সঙ্গত হওয়ার জন্য, আমার সন্দেহ হয় যে basenameআসলে ইনপুট স্ট্রিংটি পরিবর্তিত হবে না যা ফলাফল আসে __FILE__, কারণ ইনপুট স্ট্রিংটির /শেষে থাকে না এবং তাই পরিবর্তনের দরকার নেই। সুতরাং আপনি এটির সাথে পালিয়ে যেতে পারেন, তবে আমি প্রথমবারের মতো কেউ দেখি basename, তাদের সমস্ত সীমাবদ্ধতার সাথে দেখা উচিত।
স্টিভ জেসোপ

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

@ স্টিভ জেসোপ, হেই, আমি এখন মাত্র চার বছর পরে আপনার মন্তব্যটি মনোযোগ সহকারে দেখার পরে বুঝতে পারি যে /স্ট্রিংয়ের শেষে বেসনেমের যুক্তিটি সংশোধন করার কোনও ভাল কারণ থাকতে পারে।
অধ্যাপক ফ্যালকেন

4

আপনি যদি CMAKEজিএনইউ সংকলক ব্যবহার করে থাকেন তবে এই globalসংজ্ঞাটি ভাল কাজ করে:

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D__MY_FILE__='\"$(notdir $(abspath $<))\"'")

4

আমি @Patrick এর সঙ্গে একই সমাধান ব্যবহার করেন উত্তর বছর ধরে।

পুরো পথটিতে প্রতীক-লিঙ্ক থাকা অবস্থায় এটি একটি ছোট সমস্যা রয়েছে।

আরও ভাল সমাধান।

set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-builtin-macro-redefined -D'__FILE__=\"$(subst $(realpath ${CMAKE_SOURCE_DIR})/,,$(abspath $<))\"'")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-builtin-macro-redefined -D'__FILE__=\"$(subst $(realpath ${CMAKE_SOURCE_DIR})/,,$(abspath $<))\"'")

কেন এটি ব্যবহার করা উচিত?

  • -Wno-builtin-macro-redefined__FILE__ম্যাক্রোর নতুন সংজ্ঞা দেওয়ার জন্য সংকলক সতর্কতা নিঃশব্দ করা ।

    এই সংকলকরা এটি সমর্থন করে না, নীচে জোরালো উপায় দেখুন।

  • ফাইল পাথ থেকে প্রকল্পের পথটি স্ট্রিপ করা আপনার আসল প্রয়োজন। header.hফাইল কোথায় আছে তা খুঁজে বের করার জন্য আপনি সময় নষ্ট করতে পছন্দ করবেন না src/foo/header.hবা src/bar/header.h

  • আমাদের কনফিগারেশন ফাইলে __FILE__ম্যাক্রো ফেলা উচিত cmake

    এই ম্যাক্রো বেশিরভাগ বিদ্যমান কোডগুলিতে ব্যবহৃত হয়। কেবল পুনরায় সংজ্ঞা দেওয়া এটি আপনাকে মুক্ত করতে পারে।

    কমলার gccলাইন আর্গুমেন্ট থেকে এই ম্যাক্রোর পূর্বনির্ধারিত সংকলকগুলি । এবং সম্পূর্ণ পাথ লিখেছেন makefileএর দ্বারা উত্পাদিত cmake

  • হার্ড কোড CMAKE_*_FLAGSপ্রয়োজন।

    এখন পর্যন্ত, আরো কিছু সম্প্রতি সংস্করণে কম্পাইলার অপশন বা সংজ্ঞা যোগ মত কিছু কমান্ড হয় add_definitions()এবং add_compile_definitions()। এই কমান্ডগুলি substউত্স ফাইলগুলিতে প্রয়োগের মতো মেক ফাংশনকে বিশ্লেষণ করবে । সেটা আমরা চাই না।

শক্তিশালী উপায় -Wno-builtin-macro-redefined

include(CheckCCompilerFlag)
check_c_compiler_flag(-Wno-builtin-macro-redefined SUPPORT_C_WNO_BUILTIN_MACRO_REDEFINED)
if (SUPPORT_C_WNO_BUILTIN_MACRO_REDEFINED)
    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-builtin-macro-redefined")
endif (SUPPORT_C_WNO_BUILTIN_MACRO_REDEFINED)
include(CheckCXXCompilerFlag)
check_cxx_compiler_flag(-Wno-builtin-macro-redefined SUPPORT_CXX_WNO_BUILTIN_MACRO_REDEFINED)
if (SUPPORT_CXX_WNO_BUILTIN_MACRO_REDEFINED)
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-builtin-macro-redefined")
endif (SUPPORT_CXX_WNO_BUILTIN_MACRO_REDEFINED)

set(*_FLAGS ... -D__FILE__=...)লাইন থেকে এই সংকলক বিকল্প অপসারণ মনে রাখবেন ।


ফাইল অন্তর্ভুক্ত থেকে আসা সামগ্রীগুলির জন্য এটি কাজ করে না।
chqrlie

আপনি কিছু কোড পোস্ট করতে পারেন? একটি সাধারণ কেস হল স্থানীয় স্কোপে ভেরিয়েবল সেট করা এবং এটি অন্যটিতে ব্যবহার করা।
লেবি.জি

উদাহরণস্বরূপ, যদি আপনি __FILE__কোনও শিরোনাম ফাইলে সংজ্ঞায়িত একটি ইনলাইন ফাংশনটিতে ডায়াগনস্টিক তৈরি করতে আপনার সংজ্ঞাটি ব্যবহার করেন, রানটাইম ডায়াগোনস্টিক অন্তর্ভুক্ত ফাইলটির নামের পরিবর্তে সংকলকটিতে পাস করা ফাইলটির নাম জানাবে, যেখানে লাইন নম্বরটি হবে অন্তর্ভুক্ত ফাইল পড়ুন।
chqrlie

হ্যাঁ, এটি এমনটি তৈরি করা হয়েছে, সর্বাধিক সাধারণ ব্যবহারের জন্য #define LOG(fmt, args...) printf("%s " fmt, __FILE__, ##args)LOG()ম্যাক্রো ব্যবহার করার সময় , আপনি log.hবার্তাগুলিতে সত্যিই দেখতে চান না । সর্বোপরি, __FILE__ম্যাক্রো অন্তর্ভুক্ত করা ফাইলগুলির পরিবর্তে প্রতিটি সি / সিপিপি ফাইল (সংকলন ইউনিট) এ প্রসারিত হয়।
লেবি.জি

3

@ Red1ynx প্রস্তাবিত কি বিষয়ে একটি সামান্য তারতম্যটি নিম্নলিখিত ম্যাক্রো তৈরি করবে:

#define SET_THIS_FILE_NAME() \
    static const char* const THIS_FILE_NAME = \
        strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__;

আপনার প্রতিটি .c (পিপি) ফাইলগুলিতে যুক্ত করুন:

SET_THIS_FILE_NAME();

তারপরে আপনি এর THIS_FILE_NAMEপরিবর্তে উল্লেখ করতে পারেন __FILE__:

printf("%s\n", THIS_FILE_NAME);

এর অর্থ প্রতি ম্যাক্রো রেফারেন্সের পরিবর্তে প্রতিবার .c (পিপি) ফাইলে নির্মাণ করা হয়।

এটি কেবলমাত্র .c (পিপি) ফাইলগুলি থেকে সীমাবদ্ধ এবং এটি হেডার ফাইলগুলি থেকে অকার্যকর হবে।


3

আমি এমন ম্যাক্রো করেছি __FILENAME__যা প্রতিবারের মতো পুরোপুরি কাটতে এড়ানো যায়। সমস্যাটি হ'ল ফলস্বরূপ ফাইলটির নাম সিপিপি-লোকাল ভেরিয়েবলের মধ্যে রাখা।

এটি .h ফাইলে একটি স্ট্যাটিক গ্লোবাল ভেরিয়েবল সংজ্ঞায়নের মাধ্যমে সহজেই করা যায় । এই সংজ্ঞা প্রতিটি পৃথক ও স্বাধীন ভেরিয়েবল দেয় .cpp যে ফাইলটি অন্তর্ভুক্ত । মাল্টিথ্রেডিং-প্রুফ হওয়ার জন্য এটি ভেরিয়েবল (গুলি) স্থানীয় (টিএলএস) থ্রেড করারও উপযুক্ত।

একটি পরিবর্তনশীল ফাইলের নাম সংরক্ষণ করে (সঙ্কুচিত)। অন্য একটি নন-কাট মান __FILE__দিয়েছে যা দিয়েছে। এইচ ফাইল:

static __declspec( thread ) const char* fileAndThreadLocal_strFilePath = NULL;
static __declspec( thread ) const char* fileAndThreadLocal_strFileName = NULL;

ম্যাক্রো নিজেই সমস্ত যুক্তি দিয়ে পদ্ধতিটিকে কল করে:

#define __FILENAME__ \
    GetSourceFileName(__FILE__, fileAndThreadLocal_strFilePath, fileAndThreadLocal_strFileName)

এবং ফাংশনটি এভাবে প্রয়োগ করা হয়:

const char* GetSourceFileName(const char* strFilePath, 
                              const char*& rstrFilePathHolder, 
                              const char*& rstrFileNameHolder)
{
    if(strFilePath != rstrFilePathHolder)
    {
        // 
        // This if works in 2 cases: 
        // - when first time called in the cpp (ordinary case) or
        // - when the macro __FILENAME__ is used in both h and cpp files 
        //   and so the method is consequentially called 
        //     once with strFilePath == "UserPath/HeaderFileThatUsesMyMACRO.h" and 
        //     once with strFilePath == "UserPath/CPPFileThatUsesMyMACRO.cpp"
        //
        rstrFileNameHolder = removePath(strFilePath);
        rstrFilePathHolder = strFilePath;
    }
    return rstrFileNameHolder;
}

সরানোপথ () বিভিন্ন উপায়ে প্রয়োগ করা যেতে পারে তবে দ্রুত এবং সহজ স্ট্রিংক্রের সাথে মনে হয়:

const char* removePath(const char* path)
{
    const char* pDelimeter = strrchr (path, '\\');
    if (pDelimeter)
        path = pDelimeter+1;

    pDelimeter = strrchr (path, '/');
    if (pDelimeter)
        path = pDelimeter+1;

    return path;
}


2

কেবল ফাইল ম্যাক্রোকে কিছুটা উন্নত করার আশা করছি:

#define FILE (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : strrchr(__FILE__, '\\') ? strrchr(__FILE__, '\\') + 1 : __FILE__)

এই ক্যাচ / এবং \, যেমন জারেক টমস্কাক অনুরোধ করেছিল এবং এটি আমার মিশ্র পরিবেশে দুর্দান্ত কাজ করে।


6
নাম FILEঅন্তর্ভুক্ত ম্যাক্রো সংজ্ঞায়িত করা যদি আপনি অন্তর্ভুক্ত করেন তবে সত্যিই খারাপ ধারণা <stdio.h>
কিথ থম্পসন

জানা ভাল. আমি স্রেজকে আমার C / সমাধানটি দেখাতে চেয়েছিলাম, তাই আমি নামকরণের স্কিমগুলি নিয়ে বিরক্ত হই না।
আলেকজান্ডার

2

চেষ্টা

#pragma push_macro("__FILE__")
#define __FILE__ "foobar.c"

আপনার উত্স ফাইলটিতে বিবৃতি অন্তর্ভুক্ত করার পরে এবং অ্যাড করুন

#pragma pop_macro("__FILE__")

আপনার উত্স ফাইলের শেষে।


2
push_macroএবং pop_macroঅ-মানক হয়। (জিসিসি মাইক্রোসফ্ট উইন্ডোজ সংকলকগুলির সাথে সামঞ্জস্যের জন্য তাদের সমর্থন করে)) কোনও ক্ষেত্রেই, সংজ্ঞাটিকে ধাক্কা দেওয়ার এবং পপ করার কোনও মানে নেই __FILE__; পুনরুদ্ধার করা মানটি যাইহোক উত্স ফাইল শেষ হওয়ার পরে ব্যবহৃত হবে না। এর মান পরিবর্তন করার একটি ক্লিনার উপায় __FILE__হ'ল#line __LINE__ "foobar.c"
কিথ থম্পসন

1
এবং এটি জিসিসির প্রিপ্রসেসরটিতে অভ্যন্তরীণ ত্রুটি ঘটায়। gcc.gnu.org/bugzilla/show_bug.cgi?id=69665
কিথ থম্পসন

1

এখানে একটি পোর্টেবল ফাংশন যা লিনাক্স (পাথ '/') এবং উইন্ডোজ উভয় ('\' এবং '/' এর মিশ্রণ) এর জন্য কাজ করে।
জিসিসি, ঝনঝন এবং বনাম সহ সংকলিত

#include <string.h>
#include <stdio.h>

const char* GetFileName(const char *path)
{
    const char *name = NULL, *tmp = NULL;
    if (path && *path) {
        name = strrchr(path, '/');
        tmp = strrchr(path, '\\');
        if (tmp) {
             return name && name > tmp ? name + 1 : tmp + 1;
        }
    }
    return name ? name + 1 : path;
}

int main() {
    const char *name = NULL, *path = NULL;

    path = __FILE__;
    name = GetFileName(path);
    printf("path: %s, filename: %s\n", path, name);

    path ="/tmp/device.log";
    name = GetFileName(path);
    printf("path: %s, filename: %s\n", path, name);

    path = "C:\\Downloads\\crisis.avi";
    name = GetFileName(path);
    printf("path: %s, filename: %s\n", path, name);

    path = "C:\\Downloads/nda.pdf";
    name = GetFileName(path);
    printf("path: %s, filename: %s\n", path, name);

    path = "C:/Downloads\\word.doc";
    name = GetFileName(path);
    printf("path: %s, filename: %s\n", path, name);

    path = NULL;
    name = GetFileName(NULL);
    printf("path: %s, filename: %s\n", path, name);

    path = "";
    name = GetFileName("");
    printf("path: %s, filename: %s\n", path, name);

    return 0;
}

স্ট্যান্ডার্ড আউটপুট:

path: test.c, filename: test.c
path: /tmp/device.log, filename: device.log
path: C:\Downloads\crisis.avi, filename: crisis.avi
path: C:\Downloads/nda.pdf, filename: nda.pdf
path: C:/Downloads\word.doc, filename: word.doc
path: (null), filename: (null)
path: , filename: 

1

সংকলন-সময় গণনা ব্যবহার করে এমন সমাধান এখানে দেওয়া হয়েছে:

constexpr auto* getFileName(const char* const path)
{
    const auto* startPosition = path;
    for (const auto* currentCharacter = path;*currentCharacter != '\0'; ++currentCharacter)
    {
        if (*currentCharacter == '\\' || *currentCharacter == '/')
        {
            startPosition = currentCharacter;
        }
    }

    if (startPosition != path)
    {
        ++startPosition;
    }

    return startPosition;
}

std::cout << getFileName(__FILE__);

1

আপনি যদি এই পৃষ্ঠায় শেষ হয়ে থাকেন তবে আপনি যে বাইনারিটি চালাচ্ছেন তার থেকে কুৎসিত বিল্ডিংয়ের দিকে ইঙ্গিত করছে এমন নিখুঁত উত্স পথটি সরানোর কোনও উপায় সন্ধান করছেন, নীচে আপনার প্রয়োজন অনুসারে হতে পারে।

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

OPTION(CMAKE_USE_RELATIVE_PATHS "If true, cmake will use relative paths" ON)

উপরের ভেরিয়েবলটি সেট করা ONবিন্যাসে বিল্ড কমান্ড উত্পন্ন করবে:

cd /ugly/absolute/path/to/project/build/src && 
    gcc <.. other flags ..> -c ../../src/path/to/source.c

ফলস্বরূপ, __FILE__ম্যাক্রো সমাধান করবে../../src/path/to/source.c

সিএমকে ডকুমেন্টেশন

ডকুমেন্টেশন পৃষ্ঠায় সতর্কতা থেকে সাবধান থাকুন যদিও:

আপেক্ষিক পাথ ব্যবহার করুন (কাজ নাও করতে পারে!)।

এটি সব ক্ষেত্রেই কাজ করার গ্যারান্টিযুক্ত নয়, তবে খনিতে কাজ করেছে - সিএমকেক 3.13 + জিসিসি 4.5


সিএমকে ৩.৪+ ডকুমেন্টেশন বলছে যে "এই পরিবর্তনশীলটির কোনও প্রভাব নেই previous এটি পূর্ববর্তী রিলিজে আংশিকভাবে প্রয়োগিত প্রভাব সিএমকে ৩.৪ এ অপসারণ করা হয়েছিল।" যদি এটি আপনার সাথে ৩.১৩ কাজ করে, তার আর একটি কারণ আছে।
mike.dld

0

আপনি জিসিসি ব্যবহার করছেন থেকে, আপনি যা করতে পারেন সদ্ব্যবহার এর

__BASE_FILE__এই ম্যাক্রো একটি সি স্ট্রিং ধ্রুবক আকারে মূল ইনপুট ফাইলটির নামে প্রসারিত করে। এটি উত্স ফাইল যা প্রিপ্রসেসর বা সি সংকলকটির কমান্ড লাইনে নির্দিষ্ট ছিল

এবং তারপরে সংকলন সময়ে উত্স ফাইল উপস্থাপনা (পূর্ণ পথ / আপেক্ষিক পথ / বেসনাম) পরিবর্তন করে আপনি কীভাবে ফাইলের নাম প্রদর্শন করতে চান তা নিয়ন্ত্রণ করুন।


6
কোন পার্থক্য করে না। আমি ব্যবহার করেছি __FILE__এবং __BASE_FILE__তবে তারা দুজনেই ফাইলের পুরো পথ দেখায়
মাহমুদ

আপনি কিভাবে সংকলক প্রার্থনা করবেন?
ziu

2
তারপরে আমি বাজি ধরছি এসসিএনএস এইভাবে জিসিসি কল করছে gcc /absolute/path/to/file.c। আপনি যদি এই আচরণটি পরিবর্তনের কোনও উপায় খুঁজে পান (এসও, লোল? এর উপর অন্য একটি প্রশ্ন খোলার), আপনার রানটাইমে স্ট্রিংটি পরিবর্তন করার দরকার নেই
ziu

17
এই উত্তরটি 100% ভুল। __BASE_FILE__(ডকস যেমন বলেছেন, অস্পষ্টভাবেই) কমান্ড লাইনে নির্দিষ্ট করা ফাইলটির নাম উত্পন্ন করে , যেমন test.cবা /tmp/test.cআপনি কীভাবে সংকলকটি চালু করেছিলেন তার উপর নির্ভর করে। এটি হুবহু একই জিনিস __FILE__, আপনি যদি কোনও শিরোনামের ফাইলের মধ্যে থাকেন তবে এই ক্ষেত্রে __FILE__বর্তমান ফাইলটির নাম (যেমন foo.h) __BASE_FILE__উত্পন্ন হয় যেখানে উত্পাদন অবিরত থাকে test.c
কুক্সপ্লসোন

0

স্ট্রিং লাইব্রেরি (লিনাক্স কার্নেল, এমবেডেড সিস্টেম ইত্যাদি) নেই এমন পরিবেশের জন্য কাজ করে এমন একটি সমাধান এখানে দেওয়া হয়েছে:

#define FILENAME ({ \
    const char* filename_start = __FILE__; \
    const char* filename = filename_start; \
    while(*filename != '\0') \
        filename++; \
    while((filename != filename_start) && (*(filename - 1) != '/')) \
        filename--; \
    filename; })

এখন শুধু FILENAMEপরিবর্তে ব্যবহার করুন __FILENAME__। হ্যাঁ, এটি এখনও রানটাইমের জিনিস তবে এটি কার্যকর।


প্ল্যাটফর্মের উপর নির্ভর করে '/' এবং 'both' উভয়ই পরীক্ষা করতে চাই।
টেকনোফিল

0
#include <algorithm>
#include <string>
using namespace std;
string f( __FILE__ );
f = string( (find(f.rbegin(), f.rend(), '/')+1).base() + 1, f.end() );

// searches for the '/' from the back, transfers the reverse iterator 
// into a forward iterator and constructs a new sting with both

0

উইন্ডোজ এবং * নিক্স উভয়ের জন্য একটি সংক্ষিপ্ত, কার্যকারী উত্তর:

#define __FILENAME__ std::max<const char*>(__FILE__,\
    std::max(strrchr(__FILE__, '\\')+1, strrchr(__FILE__, '/')+1))

ন্যায়বিচারের std::max<const char*>পরিবর্তে আপনার প্রয়োজন কেন std::max?
chqrlie
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.