c++ - int একটি[]={1,2,}; অদ্ভুত কমা অনুমোদিত। কোন বিশেষ কারণ?




syntax grammar (13)

অনেক কিছু পছন্দ করে, একটি অ্যারে প্রারম্ভিকের মধ্যে পূর্ববর্তী কমাটি সি ++ থেকে উত্তরাধিকারী (এবং চিরকালের জন্য সমর্থন করতে হবে) এর মধ্যে একটি। এখানে রাখা যারা থেকে সম্পূর্ণ ভিন্ন ভিন্ন একটি বই "গভীর সি গোপন" বই উল্লেখ করা হয়।

একাধিক "কমা প্যারাডক্সিস" সহ একটি উদাহরণের পরে সেখানে:

char *available_resources[] = {
"color monitor"           ,
"big disk"                ,
"Cray"                      /* whoa! no comma! */
"on-line drawing routines",
"mouse"                   ,
"keyboard"                ,
"power cables"            , /* and what's this extra comma? */
};

আমরা পড়ি:

... চূড়ান্ত সূচনাকারীর পরে কমা অনুসরণকারীটি টাইপো নয়, তবে এবিজিজিন সি থেকে সিন্ট্যাক্সে একটি আলিঙ্গন । তার উপস্থিতি বা অনুপস্থিতি অনুমোদিত কিন্তু কোন তাত্পর্য নেই । এএনএসআই সি রেশেশনে দাবি করা যুক্তিটি সিটির স্বয়ংক্রিয় প্রজন্মকে সহজ করে তোলে। প্রতিটি কমা-সেপিএ-রেট তালিকাতে কমা অনুসরণ করার অনুমতি দেওয়া হলে দাবিটি আরো বিশ্বাসযোগ্য হবে , যেমন এনম ঘোষণাগুলি বা একক ঘোষণায় একাধিক পরিবর্তনশীল ঘোষক। তারা না.

... আমার কাছে এই আরো জ্ঞান করে তোলে

সম্ভবত আমি এই গ্রহ থেকে নই, কিন্তু এটি আমার মনে হবে যে নিম্নলিখিতটি একটি সিনট্যাক্স ত্রুটি হওয়া উচিত:

int a[] = {1,2,}; //extra comma in the end

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

কেন এই অনুমতি দেওয়া হয়? এটি একটি মূঢ় নিরর্থক প্রশ্ন হতে পারে তবে আমি আপনাকে জিজ্ঞাসা করছি কেন আমি বুঝতে চাই। যদি এটি একটি সাধারণ ব্যাকরণ রুলের একটি উপ-কেস ছিল, তবে আমি বুঝতে পারব - তারা সাধারণ ব্যাকরণটিকে একটি সূচনাকারী তালিকার শেষে অনাদায়ী কমা বাতিল করতে আরো কঠিন করে তুলতে সিদ্ধান্ত নিল। কিন্তু না, অতিরিক্ত কমা স্পষ্টভাবে অনুমতি দেওয়া হয়। উদাহরণস্বরূপ, এটি একটি ফাংশন-কল যুক্তি তালিকা (যখন ফাংশনটি নেয় ... ) এর শেষে একটি অকার্যকর কমা করার অনুমতি দেয় না, যা স্বাভাবিক

সুতরাং, আবার, এই অমূল্য কমা স্পষ্টভাবে অনুমতি দেওয়া কোনো বিশেষ কারণ আছে?


আপনি নির্দিষ্ট দৈর্ঘ্য ব্যতীত একটি অ্যারে ব্যবহার করেন, তবে VC ++ 6.0 স্বয়ংক্রিয়ভাবে তার দৈর্ঘ্য সনাক্ত করতে পারে, তাই যদি আপনি "int a [] = {1,2,};" এর দৈর্ঘ্য 3 ব্যবহার করেন তবে শেষটি হ'ল টি চালু করা হয়েছে, আপনি "cout <ব্যবহার করতে পারেন


আমি অন্য একটি উত্তর, আমাদের প্রিয় ম্যাক্রোতে উল্লিখিত একটি ব্যবহার ক্ষেত্রে দেখতে পাইনি:

int a [] = {
#ifdef A
    1, //this can be last if B and C is undefined
#endif
#ifdef B
    2,
#endif
#ifdef C
    3,
#endif
};

সর্বশেষ হ্যান্ডেল ম্যাক্রো যোগ করা, বড় ব্যথা হতে হবে। সিনট্যাক্স এই ছোট পরিবর্তন সঙ্গে পরিচালনা করতে তুচ্ছ। এবং এটি মেশিন জেনারেট কোডের চেয়ে বেশি গুরুত্বপূর্ণ কারণ সাধারণত খুব সীমিত প্রিপোসারারের তুলনায় টুরিং সম্পূর্ণ ল্যাঙ্গুয়ে এটি করা অনেক সহজ।


আমি অবাক হয়ে অবাক হলাম যে এই সময় কেউ এ্যানোটেটেড সি ++ রেফারেন্স ম্যানুয়াল ( এআরএম ) উদ্ধৃত করেনি, এটি জোর করে খনি দিয়ে [dcl.init] সম্পর্কে নিম্নলিখিত বলে:

প্রাথমিককরণের জন্য স্পষ্টভাবে অনেকগুলি উল্লেখ রয়েছে, তবে প্রতিটিটি ব্যবহারের বিশেষ শৈলীকে ভালভাবে পরিবেশন করতে বলে। = {Initializer_list, opt} নোটেশনটি C থেকে উত্তরাধিকারসূত্রে প্রাপ্ত হয়েছিল এবং ডেটা স্ট্রাকচার এবং অ্যারের সূচনা করার জন্য ভালভাবে কাজ করে। [...]

যদিও এআরএমটি মূল অবশেষে লিখিত ছিল, তখন থেকেই ব্যাকরণ বিকশিত হয়েছে।

এবং আমরা সি -99 এর কেন্দ্রে যেতে পারি তা দেখার জন্য আমরা সি- তে যেতে পারি এবং এটি বলে:

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


একমাত্র ভাষা যেখানে এটি - অনুশীলনে * - অনুমতি দেওয়া হয় না জাভাস্ক্রিপ্ট, এবং এটি অসংখ্য সংখ্যক সমস্যা সৃষ্টি করে। উদাহরণস্বরূপ, যদি আপনি অ্যারের মাঝখান থেকে একটি লাইন অনুলিপি এবং আটকান, শেষে এটি পেস্ট করুন এবং কমা অপসারণ করতে ভুলে গেছেন তবে আপনার IE দর্শকদের জন্য আপনার সাইট সম্পূর্ণভাবে ভাঙ্গা হবে।

* তত্ত্ব অনুসারে এটি অনুমোদিত কিন্তু ইন্টারনেট এক্সপ্লোরার মান অনুসরণ করে না এবং এটি একটি ত্রুটি হিসাবে আচরণ করে


এটি একটি দীর্ঘ তালিকা চারপাশে উপাদান সরানো দ্বারা সৃষ্ট ভুল থেকে রক্ষা করার অনুমতি দেওয়া হয়।

উদাহরণস্বরূপ, আসুন আমরা অনুমান করি যে আমাদের এমন কোড রয়েছে।

#include <iostream>
#include <string>
#include <cstddef>
#define ARRAY_SIZE(array) (sizeof(array) / sizeof *(array))
int main() {
    std::string messages[] = {
        "",
        "Super User",
        "Server Fault"
    };
    size_t i;
    for (i = 0; i < ARRAY_SIZE(messages); i++) {
        std::cout << messages[i] << std::endl;
    }
}

এবং এটি দুর্দান্ত, কারণ এটি স্ট্যাক এক্সচেঞ্জ সাইটের মূল ট্রিলজি দেখায়।

Stack Overflow
Super User
Server Fault

কিন্তু এটি একটি সমস্যা আছে। আপনি দেখুন, এই ওয়েবসাইটে ফুটার সুপার ব্যবহারকারীর আগে সার্ভার ফল্ট দেখায়। কেউ নোটিশ আগে যে ভাল ফিক্স।

#include <iostream>
#include <string>
#include <cstddef>
#define ARRAY_SIZE(array) (sizeof(array) / sizeof *(array))
int main() {
    std::string messages[] = {
        "",
        "Server Fault"
        "Super User",
    };
    size_t i;
    for (i = 0; i < ARRAY_SIZE(messages); i++) {
        std::cout << messages[i] << std::endl;
    }
}

সব পরে, চারপাশে চলমান লাইন যে কঠিন হতে পারে না, এটা হতে পারে?

Stack Overflow
Server FaultSuper User

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

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


এটি কোড জেনারেটরগুলিকে সহজ করে তোলে যা অ্যারে বা সংখ্যাসূচকতাগুলিকে সহজ করে দেয়।

কল্পনা করুন:

std::cout << "enum Items {\n";
for(Items::iterator i(items.begin()), j(items.end); i != j; ++i)
    std::cout << *i << ",\n";
std::cout << "};\n";

হ্যাঁ, পূর্ববর্তী বা শেষ আইটেমের বিশেষ পরিচালনা করার দরকার নেই, যা পূর্ববর্তী কমাটি এড়াতে বাধা দেয়।

যদি কোড জেনারেটর পাইথনে লিখিত থাকে, উদাহরণস্বরূপ, str.join() ফাংশন ব্যবহার করে str.join() কমা স্পিট করা এড়ানো সহজ:

print("enum Items {")
print(",\n".join(items))
print("}")

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


এটি সোর্স কোড জেনারেট করা সহজ করে এবং পরবর্তীতে যে কোডটি সহজেই বাড়ানো যায় তা লিখতেও সক্ষম করে। একটি অতিরিক্ত এন্ট্রি যোগ করার প্রয়োজন কি বিবেচনা করুন:

int a[] = {
   1,
   2,
   3
};

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

এখন কোড উৎপাদনের কথা ভাবুন। কিছু ভালো (ছদ্ম-কোড):

output("int a[] = {");
for (int i = 0; i < items.length; i++) {
    output("%s, ", items[i]);
}
output("};");

আপনি যে বর্তমান আইটেমটি লিখছেন সেটি প্রথম বা শেষ কিনা তা সম্পর্কে চিন্তা করার দরকার নেই। অনেক সহজ।


কারণ তুচ্ছ: লাইন যোগ / অপসারণ সহজ।

নিম্নলিখিত কোড কল্পনা করুন:

int a[] = {
   1,
   2,
   //3, // - not needed any more
};

এখন, আপনি কখনও কখনও পিছনে কমা যোগ / অপসারণ ছাড়া তালিকায় আইটেম সহজে যোগ / অপসারণ করতে পারেন।

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


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

for_each(my_inits.begin(), my_inits.end(),
[](const std::string& value) { std::cout << value << ",\n"; });

প্রোগ্রামার জন্য সত্যিই কোন সুবিধা নেই।

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


বিকাশকারীর জন্য ব্যবহার সহজ, আমি মনে করি।

int a[] = {
            1,
            2,
            2,
            2,
            2,
            2, /*line I could comment out easily without having to remove the previous comma*/
          }

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


সকলেই সবকিছু যুক্ত / সরানোর / লাইন তৈরি করার সহজতার কথা বলছে, কিন্তু এই সিনট্যাক্সের আসল জায়গাটি যখন সোর্স ফাইলগুলিকে একত্রে মেশানো হয়। আপনি এই অ্যারে পেয়েছেন অনুমান করুন:

int ints[] = {
    3,
    9
};

এবং অনুমান করুন যে আপনি এই কোডটি একটি রিপোজিটোরিতে পরীক্ষা করেছেন।

তারপর আপনার বন্ধু এটি সম্পাদন, শেষ যোগ করা:

int ints[] = {
    3,
    9,
    12
};

এবং আপনি একযোগে এটি সম্পাদনা করে শুরু করেছেন:

int ints[] = {
    1,
    3,
    9
};

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

সুতরাং, আমার থাম্বের নিয়ম হল: তালিকাটি একাধিক লাইন স্প্যান্স করে যদি পূর্ববর্তী কমা ব্যবহার করে, তালিকাটি যদি একক লাইনে থাকে তবে এটি ব্যবহার করবেন না।





language-lawyer