সি ++ এ আকার_t মুদ্রণের কোড পরিষ্কার করুন (বা: সি ++ এ সি 99 এর% z এর নিকটতম সমতুল্য)


96

আমার কিছু সি ++ কোড রয়েছে যা একটি প্রিন্ট করে size_t:

size_t a;
printf("%lu", a);

আমি এটি 32- এবং 64-বিট উভয় আর্কিটেকচার উভয়ই সতর্কতা ছাড়াই সংকলন করতে চাই।

এটি যদি C99 হয় তবে আমি ব্যবহার করতে পারতাম printf("%z", a);। তবে AFAICT %zকোনও মানক সি ++ উপভাষায় বিদ্যমান নেই। সুতরাং পরিবর্তে, আমি করতে হবে

printf("%lu", (unsigned long) a);

যা সত্যিই কুৎসিত

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

কোন ধারনা?


সম্পাদনা করুন নির্মল কেন আমি printf ব্যবহার করছি: আমি অপেক্ষাকৃত বড় কোড বেস যে আমি পরিষ্কার আপ করছি না। এটি "সতর্কতা লিখুন, কোনও ফাইলে লগইন করুন, এবং সম্ভবত একটি ত্রুটিযুক্ত কোডটি প্রস্থান করুন" এর মতো জিনিসগুলি করতে প্রিন্টফ মোড়ক ব্যবহার করে। আমি যথেষ্ট সি ++ জোগাড় করতে সক্ষম হতে পারি - ফু একটি চাউড়ী মোড়কের সাহায্যে এটি করতে পারে, তবে আমি কেবল কিছু সংকলক সতর্কতা থেকে মুক্তি পেতে প্রোগ্রামে প্রতিটি সতর্কতা () কলকে পরিবর্তন করব না।


4
আপনি কেন প্রিন্টফ ব্যবহার করছেন তা প্রশ্ন হওয়া উচিত।
এড এস।

আপনার সংকলক প্রিন্টফ স্ট্রিং পরিদর্শন করে এবং আপনার জন্য চেক টাইপ করে?
পড

আমার সংকলক প্রকৃতপক্ষে প্রিন্টফ ফর্ম্যাট স্ট্রিংটি পরীক্ষা করে এবং এটি আমার জন্য পরীক্ষা করে টাইপ করে। আমি এই বৈশিষ্ট্যটি চালু রাখতে চাই।
জাস্টিন এল।

4
% zu, z একটি প্রস্থ নির্দিষ্টকরণকারী নয় টাইপ স্পেসিফায়ার। এটি সি প্রিন্টফের জন্য কাজ করে যা আপনি সি ++ থেকে নির্বিঘ্নে ব্যবহার করতে পারেন। ); আমি নিচে এটিতে মন্তব্য করেছি, তাই এটি জন্য ভোট
উইল

আপনি যদি ভিজুয়াল স্টুডিও ব্যবহার করছেন তবে আপনি কি কেবল ব্যবহার করতে পারবেন না "%l"? সবসময় সঠিক আকার হবে না? বা বহনযোগ্যতা কোন ব্যাপার?
মাকিং হাঁস

উত্তর:


61

বেশিরভাগ সংকলকগুলির নিজস্ব স্পেসিফার size_tএবং ptrdiff_tযুক্তি রয়েছে, উদাহরণস্বরূপ ভিজ্যুয়াল সি ++ যথাক্রমে% আইইউ এবং% আইডি ব্যবহার করে, আমি মনে করি যে জিসিসি আপনাকে% zu এবং% zd ব্যবহার করার অনুমতি দেবে।

আপনি একটি ম্যাক্রো তৈরি করতে পারেন:

#if defined(_MSC_VER) || defined(__MINGW32__) //__MINGW32__ should goes before __GNUC__
  #define JL_SIZE_T_SPECIFIER    "%Iu"
  #define JL_SSIZE_T_SPECIFIER   "%Id"
  #define JL_PTRDIFF_T_SPECIFIER "%Id"
#elif defined(__GNUC__)
  #define JL_SIZE_T_SPECIFIER    "%zu"
  #define JL_SSIZE_T_SPECIFIER   "%zd"
  #define JL_PTRDIFF_T_SPECIFIER "%zd"
#else
  // TODO figure out which to use.
  #if NUMBITS == 32
    #define JL_SIZE_T_SPECIFIER    something_unsigned
    #define JL_SSIZE_T_SPECIFIER   something_signed
    #define JL_PTRDIFF_T_SPECIFIER something_signed
  #else
    #define JL_SIZE_T_SPECIFIER    something_bigger_unsigned
    #define JL_SSIZE_T_SPECIFIER   something_bigger_signed
    #define JL_PTRDIFF_T_SPECIFIER something-bigger_signed
  #endif
#endif

ব্যবহার:

size_t a;
printf(JL_SIZE_T_SPECIFIER, a);
printf("The size of a is " JL_SIZE_T_SPECIFIER " bytes", a);

4
এটা যে সহজ নয়। %zসমর্থিত কিনা তা রানটাইমের উপর নির্ভর করে, সংকলক নয়। ব্যবহার __GNUC__অতএব কোন সমস্যা হওয়ার একটু, যদি আপনি জিসিসি / (এবং mingw এর উদ্দীপ্ত printf, ব্যবহার না করেই) msvcrt সঙ্গে mingw মিশ্রিত করা হয়।
jørgensen

68

printfবিন্যাস সুনির্দিষ্টভাবে উল্লেখ করা %zuসি ++ সিস্টেমে সূক্ষ্ম কাজ করবে; এটিকে আরও জটিল করার দরকার নেই।


9
@ ক্রিসমার্কল একটি দ্রুত পরীক্ষা আমাকে দেখায় যে এটি MinGW এ কাজ করে না। এছাড়াও এমএস সাইট এটি তালিকাভুক্ত করে না ( এমএসডিএন.মাইক্রোসফটকম /en-us/library/tcxf1dw6%28v=vs.100%29.aspx )। আমি মনে করি উত্তরটি হ'ল না।
wump

17

সি ++ 11

C ++ 11 আমদানি C99 তাই std::printfC99 %zuফর্ম্যাট স্পেসিফায়ারকে সমর্থন করে ।

সি ++ 98

বেশিরভাগ প্ল্যাটফর্মগুলিতে size_tএবং uintptr_tসমতুল্য, এক্ষেত্রে আপনি PRIuPTRম্যাক্রো সংজ্ঞায়িতভাবে ব্যবহার করতে পারেন <cinttypes>:

size_t a = 42;
printf("If the answer is %" PRIuPTR " then what is the question?\n", a);

আপনি যদি সত্যিই নিরাপদ থাকতে চান তবে কাস্ট করুন uintmax_tএবং ব্যবহার করুন PRIuMAX:

printf("If the answer is %" PRIuMAX " then what is the question?\n", static_cast<uintmax_t>(a));

16

উইন্ডোজ এবং প্রিন্টফের ভিজ্যুয়াল স্টুডিও বাস্তবায়নে

 %Iu

আমার জন্য কাজ কর. দেখতে MSDN


ধন্যবাদ VS 2008খুব কাজ করে। এছাড়াও মনে যে একটি ব্যবহার করতে পারেন রাখা %Id, %Ixএবং %IXখুব।
c00000fd

11

আপনি যেহেতু সি ++ ব্যবহার করছেন তাই আইওএসটিস্ট্রিম ব্যবহার করবেন না কেন? এটি সতর্কতা ছাড়াই সংকলন করে সঠিক টাইপ-সচেতন জিনিসটি করা উচিত, যতক্ষণ না আপনি মস্তিষ্ক-মৃত সি ++ বাস্তবায়ন ব্যবহার করেন না যা এর operator <<জন্য সংজ্ঞা দেয় না size_t

প্রকৃত আউটপুটটি যখন সম্পন্ন করতে হয় printf(), আপনি এখনও এটিকে আইওএসটিস্ট্রিমের সাথে সংযুক্ত করতে পারেন টাইপ-নিরাপদ আচরণ পেতে:

size_t foo = bar;
ostringstream os;
os << foo;
printf("%s", os.str().c_str());

এটি অতি দক্ষ নয়, তবে উপরের ক্ষেত্রে আপনার ফাইলটি I / O ফাইলের সাথে সম্পর্কিত, যাতে এটি আপনার বাধা, এই স্ট্রিং বিন্যাস কোড নয়।


আমি জানি যে গুগল তাদের কোডগুলিতে কাউট ব্যবহার নিষিদ্ধ করে। সম্ভবত জাস্টিন এল এই জাতীয় বিধিনিষেধের অধীনে কাজ করছেন।

আমার ক্ষেত্রে (উপরের সম্পাদনাটি দেখুন), একটি আকর্ষণীয় ধারণাটি হ'ল কোউটের ক্ষেত্রে সতর্কতা () ফাংশনটি চেষ্টা করে প্রয়োগ করতে পারে। তবে এর মধ্যে ম্যানুয়ালি ফরম্যাট স্ট্রিংগুলি পার্স করা জড়িত, যা ... জটিল। :)
জাস্টিন এল।

আপনার সর্বশেষ সম্পাদনাটি আসলে আমার পক্ষে কাজ করতে পারে বলে মনে হয় তার বিপরীত। আমি যে সমস্ত কোড মুদ্রণযন্ত্রের মুদ্রণযন্ত্রের আহ্বান জানাই তার সবই আবার লিখতে চাই না, তবে কাউট ব্যবহার করার জন্য প্রিন্টফ মোড়কের বাস্তবায়নের পুনরায় লেখার বিষয়ে আমার আপত্তি নেই। তবে আমি মনে করি না এটি ঘটতে চলেছে। :)
জাস্টিন এল।

std::stringstreamআইও স্ট্রিমের পরিবর্তে ব্যবহার করুন ।
টমাস এডিং

4
স্ট্রিমগুলির অদ্ভুত স্বরলিপি রয়েছে। তুলনা: printf("x=%i, y=%i;\n", x, y);বনাম cout << "x=" << x << ", y=" << y << ";" << std::endl;
আশ্চর্য.মাইস

7

এখানে একটি সম্ভাব্য সমাধান রয়েছে, তবে এটি বেশ সুন্দর সমাধান নয় ..

template< class T >
struct GetPrintfID
{
  static const char* id;
};

template< class T >
const char* GetPrintfID< T >::id = "%u";


template<>
struct GetPrintfID< unsigned long long > //or whatever the 64bit unsigned is called..
{
  static const char* id;
};

const char* GetPrintfID< unsigned long long >::id = "%lu";

//should be repeated for any type size_t can ever have


printf( GetPrintfID< size_t >::id, sizeof( x ) );

4
ভাল ... এটি আমার সুরক্ষার লক্ষ্য অর্জন করে এবং কোনও সতর্কবার্তা দেয় না। তবে ... ইয়েশ আমার যদি তা-ই করতে হয় তবে আমি সতর্কতা নেব। :)
জাস্টিন এল।

4
সুন্দর না?! স্বাদ উপর নির্ভর করে। এটি uintptr_t এবং একই রকমের পশুর সাথে প্রিন্টফের পুরোপুরি পোর্টেবল ব্যবহারের অনুমতি দেয়। দুর্দান্ত!
স্লাভা

@ user877329 আপনি সেই বিন্যাসের স্ট্রিংটি একটি স্ট্যান্ড :: স্ট্রিং হিসাবে তৈরি করতে পারেন এবং তারপরে আপনার প্রয়োজনীয় জায়গায় গেটপ্রিন্টআইডি <সাইজ_টি> :: আইডি যুক্ত করতে পারেন
স্টিঞ্জ করুন

@ স্টিজন অন্য কথায়: কোনও সংকলন-কাল কনটেনটেশন উপলভ্য নয়
কনটেনটেশন উপলভ্য নয়

@ ব্যবহারকারীর 73292929২৯ নং (ম্যাক্রো ব্যবহার না করা বা আমি কিছু মিস করছি না)। তবে কেন এটি একটি কঠিন প্রয়োজন হবে?
stijn

4

FMT গ্রন্থাগার একটি ফাস্ট পোর্টেবল (এবং নিরাপদ) বাস্তবায়ন উপলব্ধ printfসহ zজন্য পরিবর্তক size_t:

#include "fmt/printf.h"

size_t a = 42;

int main() {
  fmt::printf("%zu", a);
}

এটি পাইথনের মতো ফর্ম্যাট স্ট্রিং সিনট্যাক্সকে সমর্থন করে এবং প্রকারের তথ্য ক্যাপচার করে যাতে আপনাকে এটি ম্যানুয়ালি সরবরাহ করতে হবে না:

fmt::print("{}", a);

এটি বড় সংকলকগুলির সাথে পরীক্ষা করা হয়েছে এবং প্ল্যাটফর্মগুলিতে নিয়মিত আউটপুট সরবরাহ করে।

দাবি অস্বীকার : আমি এই গ্রন্থাগারের লেখক।


3

কার্যকর ধরণের অন্তর্নিহিত আকার_টি বাস্তবায়ন নির্ভর । সি স্ট্যান্ডার্ড এটি আকার হিসাবে অপারেটর দ্বারা ফেরত টাইপ হিসাবে সংজ্ঞায়িত করে; স্বাক্ষরবিহীন এবং এক ধরণের অবিচ্ছেদ্য প্রকার বাদে, সাইজ_টি আকারের চেয়ে বড় কিছু হতে পারে যা আকারের () দ্বারা প্রত্যাশিত সবচেয়ে বড় মানটি সমন্বিত করতে পারে।

ফলস্বরূপ আকারের জন্য ব্যবহৃত বিন্যাসের স্ট্রিংটি সার্ভারের উপর নির্ভর করে পরিবর্তিত হতে পারে। এটিতে সর্বদা "ইউ" থাকা উচিত তবে এটি ল বা ডি হতে পারে বা অন্য কিছু হতে পারে ...

কোনও কৌশলটি এটিকে মেশিনের বৃহত্তম ইন্টিগ্রাল টাইপের মধ্যে ফেলে দেওয়া হতে পারে, রূপান্তরটিতে কোনও ক্ষতি না করে এবং তারপরে এই পরিচিত ধরণের সাথে সম্পর্কিত ফর্ম্যাট স্ট্রিংটি ব্যবহার করে।


আমি size_tমেশিনের বৃহত্তম ইন্টিগ্রাল টাইপটিতে আমার প্রকারটি কাস্ট করতে এবং এই ধরণের সাথে সম্পর্কিত ফর্ম্যাট স্ট্রিংটি ব্যবহার করতে চাই। আমার প্রশ্নটি হল: ক্লিন কোড বজায় রেখে আমি কি এমন উপায় করতে পারি (কেবল বৈধ প্রিন্টফ ফর্ম্যাট স্ট্রিং ত্রুটির জন্য সতর্কতা, কোনও কুশ্রী কাস্ট ইত্যাদি)? আমি একটি মোড়ক লিখতে পারি যা ফর্ম্যাট স্ট্রিং পরিবর্তন করে, তবে আমি বৈধভাবে আমার ফর্ম্যাট স্ট্রিংটি গণ্ডগোল করলে জিসিসি আমাকে সতর্কতা দিতে সক্ষম হবে না।
জাস্টিন এল।

ধরণের আকারের জন্য সিপিপি ম্যাক্রোগুলি ব্যবহার করুন; যেটির সাথে মেলে তার জন্য যান এবং ফর্ম্যাট স্ট্রিংটি নির্দিষ্ট করে যা মিলবে টাইপের সাথে।
ক্লিয়ারার

0

#include <cstdio>
#include <string>
#include <type_traits>

namespace my{
    template<typename ty>
    auto get_string(ty&& arg){
        using rty=typename::std::decay_t<::std::add_const_t<ty>>;
        if constexpr(::std::is_same_v<char, rty>)
            return ::std::string{1,arg};
        else if constexpr(::std::is_same_v<bool, rty>)
            return ::std::string(arg?"true":"false");
        else if constexpr(::std::is_same_v<char const*, rty>)
            return ::std::string{arg};
        else if constexpr(::std::is_same_v<::std::string, rty>)
            return ::std::forward<ty&&>(arg);
        else
            return ::std::to_string(arg);
    };

    template<typename T1, typename ... Args>
    auto printf(T1&& a1, Args&&...arg){
        auto str{(get_string(a1)+ ... + get_string(arg))};
        return ::std::printf(str.c_str());
    };
};

পরে কোডে:

my::printf("test ", 1, '\t', 2.0);

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