সি / সি ++ লাইন নম্বর


110

ডিবাগিং উদ্দেশ্যে, আমি কি সি / সি ++ সংকলকগুলিতে লাইন নম্বর পেতে পারি ? (নির্দিষ্ট সংকলকগুলির জন্য আদর্শ উপায় বা নির্দিষ্ট উপায়)

যেমন

if(!Logical)
    printf("Not logical value at line number %d \n",LineNumber);
    // How to get LineNumber without writing it by my hand?(dynamic compilation)

17
@ লুকাস: আমাদের মধ্যে কেউ কেউ ডিবাগারদের সাথে গোলযোগ না করা পছন্দ করে। এই ধরণের "দরিদ্র ব্যক্তির দৃ statement় বক্তব্য" কখনও কখনও আরও স্পষ্ট হয় কারণ এটি কোডের একটি স্থায়ী অংশ, এবং গণনার অবস্থা সম্পর্কে সত্য হওয়া উচিত এমন জিনিসগুলির স্থায়ী ডকুমেন্টেশন।
এস .লট

13
@ লুকাস: দীর্ঘকাল ধরে চলমান প্রোগ্রামগুলিতে অন্তর্বর্তী সমস্যাগুলির জন্য বা ক্লায়েন্ট সাইটগুলিতে মোতায়েন করা সফ্টওয়্যারগুলির সমস্যা সম্পর্কিত তথ্য সংগ্রহের জন্য ডিবাগারগুলিও কম কার্যকর are এই ক্ষেত্রেগুলিতে একমাত্র বিকল্প হ'ল পরবর্তী বিশ্লেষণের জন্য প্রোগ্রামটির যথাসম্ভব তথ্য সম্পর্কে লগ করা।
কিথবি 17'10

1
@ লুকাস এবং ডিবাগাররা এই তথ্য পেতে কিছু এম্বেড থাকা সিস্টেমে এত ভাল কাজ করে না।
জর্জ স্টিকার

উত্তর:


180

আপনার প্রিপ্রসেসর ম্যাক্রো __LINE__এবং ব্যবহার করা উচিত __FILE__। এগুলি পূর্বনির্ধারিত ম্যাক্রো এবং সি / সি ++ স্ট্যান্ডার্ডের অংশ। প্রিপ্রোসেসিংয়ের সময়, তারা যথাক্রমে একটি ধ্রুবক স্ট্রিং দ্বারা বর্তমান লাইন নম্বর উপস্থাপন করে এবং বর্তমান ফাইলের নাম দ্বারা প্রতিস্থাপিত হয়।

অন্যদের প্রিপ্রোসেসর ভেরিয়েবল:

  • __func__: ফাংশন নাম (এটি C99 এর অংশ , সমস্ত সি ++ সংকলক এটি সমর্থন করে না)
  • __DATE__ : "এমএম ডিডি ইয়িআই" ফর্মের একটি স্ট্রিং
  • __TIME__ : ফর্মের একটি স্ট্রিং "এইচএইচ: মিমি: এসএস"

আপনার কোডটি হবে:

if(!Logical)
  printf("Not logical value at line number %d in file %s\n", __LINE__, __FILE__);

2
C99 __Function__ এর চেয়ে __func__ ব্যবহার করে, যা AFAIK আংশিকভাবে হ্রাস পেয়েছে। পার্থক্যটি আপনার কোডটিকে ভেঙে দিতে পারে, কারণ __func__ সি এর ধ্রুব স্ট্রিং কনকেন্টেশনের জন্য ব্যবহার করা যায় না।
জোসেফ কুইনসে

1
জিসিসি ম্যানুয়াল থেকে রেফারেন্স: "__FUNCTION__ এবং __PRETTY_FUNCTION__ এ স্ট্রিং লিটারাল হিসাবে বিবেচনা করা হত; তারা চর অ্যারে আরম্ভ করার জন্য ব্যবহার করা যেতে পারে এবং এগুলি অন্যান্য স্ট্রিং ল্যাটারাল দিয়ে সংমিশ্রিত করা যেতে পারে। জিসিসি 3.4 এবং পরে তাদেরকে __func__ এর মত চলক হিসাবে বিবেচনা করা হবে। সি ++, __FUNCTION__ এবং __PRETTY_FUNCTION__ সর্বদা পরিবর্তনশীল ছিল। "
জোসেফ কুইনসে

স্ট্রিং হিসাবে লাইন নম্বরটি ফাইলের নামের মতো পাওয়ার কি কোনও উপায় আছে? আমি প্রাক প্রসেসর চাই আমাকে যেমন স্ট্রিং আক্ষরিক "22" পরিবর্তে পূর্ণসংখ্যা 22. দিতে
sep332

1
@ sep332 হ্যাঁ, তবে সিপিপি একটি অদ্ভুত জন্তু, তাই এটি ম্যাক্রো যুক্তি সহ দুটি পদক্ষেপে অবশ্যই করা উচিত। #define S1(N) #N #define S2(N) S1(N) #define LINESTR S2(__LINE__)C-faq.com/ansi/stringize.html
কাজ

1
কড়া কথায় বলতে গেলে __func__ম্যাক্রো নয়, এটি সুস্পষ্টভাবে ঘোষিত পরিবর্তনশীল।
হলিব্ল্যাকট্যাগ

64

সি ++ স্ট্যান্ডার্ডের অংশ হিসাবে এখানে কিছু প্রাক-সংজ্ঞায়িত ম্যাক্রো রয়েছে যা আপনি ব্যবহার করতে পারেন। সি ++ স্ট্যান্ডার্ডের ১.8.৮ ধারাটি __LINE__ম্যাক্রো সম্পর্কিত অন্যান্য বিষয়ের মধ্যে সংজ্ঞা দেয় ।

__LINE__: বর্তমান উত্স রেখার লাইন নম্বর (দশমিক ধ্রুবক)।
__FILE__: উত্স ফাইলের অনুমিত নাম (একটি অক্ষরের স্ট্রিং আক্ষরিক)।
__DATE__: উত্স ফাইলটি অনুবাদ করার তারিখ (একটি অক্ষর স্ট্রিং আক্ষরিক ...)
__TIME__: উত্স ফাইলটি অনুবাদ করার সময় (একটি অক্ষর স্ট্রিং আক্ষরিক ...)
__STDC__:__STDC__ পূর্বনির্ধারিত কিনা
__cplusplus: নামটি __cplusplus199711L মান হিসাবে সংজ্ঞায়িত করা হয় যখন একটি সি ++ অনুবাদ ইউনিট সংকলন

সুতরাং আপনার কোডটি হবে:

if(!Logical)
  printf("Not logical value at line number %d \n",__LINE__);

19

আপনি প্রিন্টফ () এর মতো একই আচরণের সাথে একটি ম্যাক্রো ব্যবহার করতে পারেন , এটি ছাড়াও এতে ফাংশন নাম, শ্রেণি এবং লাইন নম্বর এর মতো ডিবাগ তথ্য অন্তর্ভুক্ত থাকে:

#include <cstdio>  //needed for printf
#define print(a, args...) printf("%s(%s:%d) " a,  __func__,__FILE__, __LINE__, ##args)
#define println(a, args...) print(a "\n", ##args)

এই ম্যাক্রোগুলির জাভা স্ট্যাকট্রেস-জাতীয় তথ্য অন্তর্ভুক্ত করার সময় প্রিন্টফ () এর সাথে একইরকম আচরণ করা উচিত । এখানে একটি উদাহরণ প্রধান:

void exampleMethod() {
    println("printf() syntax: string = %s, int = %d", "foobar", 42);
}

int main(int argc, char** argv) {
    print("Before exampleMethod()...\n");
    exampleMethod();
    println("Success!");
}

নিম্নলিখিত ফলাফলের ফলাফল যা:

main (main.cpp: 11) উদাহরণের আগে ম্যাথোড () ...
উদাহরণমথোড (মেইন সিপিপি: 7) প্রিন্টফ () সিনট্যাক্স: স্ট্রিং = ফুবার, ইনট = 42
মেন (মেইন সিপিপি: 13) সাফল্য!


গ উন্নয়নের জন্য, আপনি পরিবর্তন হবে #includeথেকে<stdio.h>
phyatt

11

ব্যবহার করুন __LINE__(এটি ডাবল-আন্ডারস্কোর লাইন ডাবল-আন্ডারস্কোর), প্রিপ্রসেসর এটির সাথে লাইন নম্বরটি প্রতিস্থাপন করবে on



5

সি ++ 20 স্ট্যান্ড :: সোর্স_লোকেশন ব্যবহার করে এটি অর্জনের জন্য একটি নতুন উপায় সরবরাহ করে । এটি বর্তমানে যেমন জিসিসি একটি ঝনঝন মধ্যে প্রবেশযোগ্য std::experimental::source_locationসঙ্গে #include <experimental/source_location>

ম্যাক্রোগুলির মতো সমস্যাটি __LINE__হ'ল যদি আপনি উদাহরণস্বরূপ একটি লগিং ফাংশন তৈরি করতে চান যা কোনও বার্তার পাশাপাশি বর্তমান লাইন নম্বরকে ছাড়িয়ে যায় তবে আপনাকে সর্বদা __LINE__একটি ফাংশন আর্গুমেন্ট হিসাবে পাস করতে হবে , কারণ এটি কল সাইটে প্রসারিত। এটার মতো কিছু:

void log(const std::string msg) {
    std::cout << __LINE__ << " " << msg << std::endl;
}

ফাংশন ঘোষণার রেখাটি সর্বদা আউটপুট দেয় এবং লাইনটি যেখানে আসত সেখান logথেকে নয়। অন্যদিকে, std::source_locationআপনি এই জাতীয় কিছু লিখতে পারেন:

#include <experimental/source_location>
using std::experimental::source_location;

void log(const std::string msg, const source_location loc = source_location::current())
{
    std::cout << loc.line() << " " << msg << std::endl;
}

এখানে, locযেখানে logডাকা হয়েছিল সেই অবস্থানটির দিকে নির্দেশ করে লাইন নম্বর দিয়ে সূচনা করা হয়েছে । আপনি এটি এখানে অনলাইনে চেষ্টা করতে পারেন।


4

চেষ্টা করুন __FILE__এবং __LINE__
আপনি খুঁজে পেতে __DATE__এবং __TIME__দরকারী হতে পারে ।
যদিও আপনি ক্লায়েন্টাইডে একটি প্রোগ্রাম ডিবাগ করতে না পারেন এবং এইভাবে এই তথ্যগুলি লগ করার দরকার নেই আপনার স্বাভাবিক ডিবাগিং ব্যবহার করা উচিত।


আমাকে কেন এই বিষয়ে ভোট দেওয়া হয়েছিল এবং মাইমাররা কেন আমার পোস্টটি সম্পাদনা করেছিল?
সান্টাকুস 2099

@ স্যানক্টাস ২০৯৯: এটি সম্পাদনা করা হয়েছিল, কারণ মার্কডাউন আপনার ডাবল আন্ডারস্কোরগুলিকে ফোল্ড এবং লাইনকে গা bold় ফন্টে প্রদর্শনের জন্য রূপান্তরিত করেছে (আপনার উত্তরটি কেমন দেখাচ্ছে তা পরীক্ষা করেন না?) আরেকটি বিষয় হতে পারে (কমপক্ষে এটি এখন আমার কাছে এটি দেখায়) যে আপনি ইতিমধ্যে সঠিক উত্তর দেওয়ার 1 ঘন্টা পরে একটি উত্তর দিয়েছেন, সুতরাং আপনি কোনও মূল্য যোগ করেন নি।
ফেলিক্স ক্লিং

ডাবল আন্ডারস্কোর জন্য মার্কআপ সিনট্যাক্স হল সাহসী । ডাবল আন্ডারস্কোর সঠিকভাবে প্রদর্শন করতে, আপনাকে অবশ্যই এগুলি থেকে বাঁচতে হবে raw code(এটির মতো : \ _ \ _) বা তাদের চিহ্নিত করতে ব্যাকটিকগুলি ব্যবহার করতে হবে (এটির মতো: `__`)। @mmyers সাহায্যের চেষ্টা করেছেন, কিন্তু তিনি শুধুমাত্র আন্ডারস্কোর এক পলান, এবং এইভাবে আপনার জন্য মার্কআপ সিনট্যাক্স সঙ্গে বাকি ছিল তির্যক । ডাউনভোটগুলি এখানে কিছুটা কঠোর, যদিও আমি সম্মত।
ম্যাট বি।

ঠিক আছে আমি ডাবল আন্ডারস্কোরগুলি পাঠ্যকে গা bold় রূপান্তরিত করার বিষয়টি বুঝতে পারি নি এবং আমাকে যেতে হয়েছিল এবং আমার উত্তর কীভাবে দেখছে তা দেখার সময় আমার ছিল না। আমি এখন বুঝতে পারি। আমার উত্তরটি এক ঘন্টা দেরিতে হলেও এটি এখনও একটি ভাল উত্তর ছিল। এটি কোনও মান যোগ করেনি তবে এটি ভুল ছিল না তাই ডাউনভোটের কোনও কারণ নেই। সাহায্যের চেষ্টা করার জন্য এটিই আপনি
পেয়েছেন

2
@ সান্টাকুস ২০৯৯ কিছু লোক নিখরচায় দ্রুত ভোট দেয়, এজন্য আপনার উত্তরটি সঠিক কিনা তা নিশ্চিত করা গুরুত্বপূর্ণ। এই ক্ষেত্রে, আপনি একটি ভুল উত্তর পোস্ট করেছেন এবং এটি 4 ঘন্টার জন্য অশিক্ষিত রেখেছেন। আপনি নিজেকে ছাড়া অন্যকে দোষী সাব্যস্ত করেছেন।
মেগার

1

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

পটভূমি: সি ++ এ টেক্সট আর্গুমেন্ট হিসাবে নন-টাইপ পূর্ণসংখ্যার মানগুলি ব্যবহার করতে পারেন। এটি টেমপ্লেট আর্গুমেন্ট হিসাবে ডেটা টাইপের সাধারণ ব্যবহারের চেয়ে পৃথক। সুতরাং ধারণাটি হ'ল ফাংশন কলের জন্য এই জাতীয় পূর্ণসংখ্যার মানগুলি ব্যবহার করা।

#include <iostream>

class Test{
    public:
        template<unsigned int L>
        int test(){
            std::cout << "the function has been called at line number: " << L << std::endl;
            return 0;
        }
        int test(){ return this->test<0>(); }
};

int main(int argc, char **argv){
    Test t;
    t.test();
    t.test<__LINE__>();
    return 0;
}

আউটপুট:

ফাংশনটি লাইন নম্বরে কল করা হয়েছে: 0

ফাংশনটি লাইন নম্বরে কল করা হয়েছে: 16

এখানে উল্লেখ করার মতো একটি বিষয় হ'ল সি ++ 11 স্ট্যান্ডার্ডে টেমপ্লেট ব্যবহার করে ফাংশনগুলির জন্য ডিফল্ট টেম্পলেট মান দেওয়া সম্ভব। প্রি সি ++ এ নন-টাইপ আর্গুমেন্টের জন্য 11 ডিফল্ট মানগুলি কেবল শ্রেণীর টেম্পলেট আর্গুমেন্টের জন্য কাজ করে বলে মনে হয়। সুতরাং, সি ++ 11 এ উপরের মতো ডুপ্লিকেট ফাংশন সংজ্ঞা থাকা দরকার নেই। সি ++ ১১-এ এটি কনস্ট চর * টেম্পলেট আর্গুমেন্ট থাকাও বৈধ তবে এখানে উল্লিখিত মত __FILE__বা আক্ষরিক সহ এগুলি ব্যবহার করা সম্ভব নয় ।__func__

সুতরাং শেষ পর্যন্ত আপনি যদি সি ++ বা সি ++ 11 ব্যবহার করছেন তবে কলিং লাইনটি পাওয়ার জন্য ম্যাক্রোর ব্যবহারের চেয়ে এটি একটি আকর্ষণীয় বিকল্প হতে পারে।


1

ব্যবহার করুন __LINE__, তবে এর ধরন কী?

লাইন বর্তমান উত্স রেখার (বর্তমান সংস্থার ফাইলের মধ্যে) অনুমান করা রেখা নম্বর (একটি পূর্ণসংখ্যার ধ্রুবক)।

একটি সংখ্যার ধ্রুবক হিসাবে , কোডটি প্রায়শই মানটি ধরে নিতে পারে __LINE__ <= INT_MAXএবং তাই টাইপটি int

সি মুদ্রণ করতে, printf()ম্যাচিং সুনির্দিষ্টভাবে উল্লেখ করা দরকার: "%d"। এটি সি ++ এর সাথে অনেক কম উদ্বেগ cout

পেডেন্টিক উদ্বেগ: যদি লাইন নম্বরটি INT_MAX1 ছাড়িয়ে যায় (16-বিট দিয়ে কিছুটা অনুমেয় int) তবে আশা করি সংকলকটি একটি সতর্কতা তৈরি করবে। উদাহরণ:

format '%d' expects argument of type 'int', but argument 2 has type 'long int' [-Wformat=]

বিকল্পভাবে, কোড বৃহত্তর ধরণেরকে এই ধরনের সতর্কতাগুলি ফরেস্ট করতে বাধ্য করতে পারে।

printf("Not logical value at line number %ld\n", (long) __LINE__);
//or
#include <stdint.h>
printf("Not logical value at line number %jd\n", INTMAX_C(__LINE__));

এড়াতে printf()

সমস্ত সংখ্যার সীমাবদ্ধতা এড়াতে: স্ট্রিংফাই করুন । কোডটি printf()কল ছাড়াই সরাসরি মুদ্রণ করতে পারে : 2 টি পরিচালনা করার ক্ষেত্রে ত্রুটি এড়ানোর জন্য একটি দুর্দান্ত জিনিস ।

#define xstr(a) str(a)
#define str(a) #a

fprintf(stderr, "Not logical value at line number %s\n", xstr(__LINE__));
fputs("Not logical value at line number " xstr(__LINE__) "\n", stderr);

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

2 ডিবাগিংয়ের ক্ষেত্রে, কখনও কখনও কোডটি আশানুরূপভাবে কাজ করে না। জটিল ক্রিয়াকলাপগুলিতে কল *printf()করাতে ইস্যুগুলি বনাম একটি সাধারণ বিষয় হতে পারে fputs()


1

যাদের প্রয়োজন হতে পারে তাদের জন্য সহজেই ফাইল এবং লাইন মুদ্রণের জন্য একটি "FILE_LINE" ম্যাক্রো:

#define STRINGIZING(x) #x
#define STR(x) STRINGIZING(x)
#define FILE_LINE __FILE__ ":" STR(__LINE__)
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.