সাইটের কোডারবাইটে 'গেটস (স্টিডিন)' দিয়ে কী চলছে?


144

কোডারবাইট একটি অনলাইন কোডিং চ্যালেঞ্জ সাইট (আমি এটি ঠিক 2 মিনিট আগে পেয়েছি)।

প্রথম C ++ চ্যালেঞ্জের সাথে আপনাকে স্বাগত জানানো একটি সি ++ কঙ্কাল রয়েছে যা আপনাকে সংশোধন করতে হবে:

#include <iostream>
#include <string>
using namespace std;

int FirstFactorial(int num) {

  // Code goes here
  return num;

}

int main() {

  // Keep this function call here
  cout << FirstFactorial(gets(stdin));
  return 0;

}

আপনি সামান্য সি সঙ্গে ++, প্রথম জিনিস পরিচিত থাকেন * যে আপনার চোখ পপ হল:

int FirstFactorial(int num);
cout << FirstFactorial(gets(stdin));

সুতরাং, ঠিক আছে, কোড কলগুলি getsযা সি ++ 11 সাল থেকে অবনতিযুক্ত এবং সি ++ 14 থেকে অপসারণ করা হয়েছে যা নিজের মধ্যে খারাপ।

তবে আমি বুঝতে পারি: getsটাইপ হয় char*(char*)। সুতরাং এটি কোনও FILE*পরামিতি গ্রহণ করা উচিত নয় এবং ফলাফলটি কোনও intপ্যারামিটারের জায়গায় ব্যবহারের জন্য কার্যকর হওয়া উচিত নয় , ... ... এটি কেবল কোনও সতর্কতা বা ত্রুটি ছাড়াই সংকলন করে না, এটি চালায় এবং প্রকৃতপক্ষে সঠিক ইনপুট মানটি পাস করে FirstFactorial

এই নির্দিষ্ট সাইটের বাইরে কোডটি সংকলিত হয় না (যেমন প্রত্যাশিত) তাই এখানে কী চলছে?


* আসলে প্রথমটি তবে এটি using namespace stdআমার সমস্যাটির সাথে এখানে অপ্রাসঙ্গিক।


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

1
@ ডেভিস্লোর না এটি "প্রার্থীর কার্যকারিতা কার্যক্ষম নয়: 'স্ট্রাক্ট _আইও_ফাইলে *' থেকে 'প্রথম
তর্কটির

3
@ ডেভিস্লোর হুঁ, এটি প্রাচীন সি-র ক্ষেত্রে সঠিক হতে পারে তবে সি ++ এর জন্য অবশ্যই না।
কোয়ান্টিন

@ কন্টিন ইয়ে এটি সংকলন করা উচিত নয়। উদ্দেশ্যমূলক চ্যালেঞ্জটি হ'ল, "এই ভাঙা কোডটি নিন, এটি করার কথা বলে আমার মনটি পড়ুন এবং এটি ঠিক করুন" তবে সেক্ষেত্রে একটি সত্য স্পেসিফিকেশন থাকা উচিত। পরীক্ষার ক্ষেত্রে।
ডেভিস্লোর

6
আমি আশ্চর্য হয়েছি যে কেউ এটি ব্যবহার করে নি, তবে gets(stdin )(অতিরিক্ত স্থান সহ) প্রত্যাশিত সি ++ ত্রুটি তৈরি করে।
রোমান ওদাইস্কি

উত্তর:


174

আমি কোডারবাইটের প্রতিষ্ঠাতা এবং এই gets(stdin)হ্যাকটি তৈরির লোক ।

এই পোস্টে দেওয়া মন্তব্যগুলি সঠিক যে এটি অনুসন্ধান ও প্রতিস্থাপনের একটি ফর্ম, সুতরাং আমি কেন দ্রুত এটি করেছি তা ব্যাখ্যা করতে দিন।

যেদিন আমি প্রথম সাইটটি তৈরি করেছি (২০১২ সালের দিকে), এটি কেবল জাভাস্ক্রিপ্ট সমর্থন করেছিল। ব্রাউজারে চলমান জাভাস্ক্রিপ্টে "ইনপুট পড়ার" কোনও উপায় ছিল না, এবং তাই এখানে একটি ফাংশন হবে foo(input)এবং আমি readline()নোড.জেএস থেকে ফাংশনটিকে এটির মতো কল করতে ব্যবহার করেছি foo(readline())। আমি ছোট ছিলাম এবং আরও ভাল জানতাম না, তাই আমি আক্ষরিকভাবে readline()রান-টাইমে ইনপুটটি দিয়ে প্রতিস্থাপন করেছি। সুতরাং foo(readline())হয়ে উঠেছে foo(2)বা foo("hello")যা জাভাস্ক্রিপ্ট জন্য সূক্ষ্ম কাজ।

2013/2014 এর আশেপাশে আমি আরও ভাষা যুক্ত করেছি এবং অনলাইনে কোড মূল্যায়নের জন্য তৃতীয় পক্ষের পরিষেবা ব্যবহার করেছি, তবে আমি যে পরিষেবাগুলি ব্যবহার করছিলাম সেগুলি দিয়ে স্টিডিন / স্টাডাউট করা খুব কঠিন ছিল, তাই আমি ভাষার জন্য একই নির্বোধ সন্ধান এবং প্রতিস্থাপনের সাথে আটকেছি পাইথন, রুবি এবং শেষ পর্যন্ত সি ++, সি # ইত্যাদি

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

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

আমি শীঘ্রই পুরো সম্পাদক পৃষ্ঠাটি ডিফল্ট কোডের সাথে আপডেট করব এবং stdinভাষাগুলি পড়ব । আশা করি এরপরে সি ++ প্রোগ্রামাররা আরও কোডারবাইট ব্যবহার করে উপভোগ করবেন :)


20
"[বি] এই ধারণাটি ছিল নতুন প্রোগ্রামারদের পক্ষে ইনপুট পড়ার বিষয়ে চিন্তা করা এবং সমস্যা সমাধানের জন্য কেবল অ্যালগরিদম লেখার দিকে মনোনিবেশ করা না -" এবং "সত্যিকারের সাদৃশ্যপূর্ণ এমন কিছু লেখার পরিবর্তে এটি আপনার কাছে ঘটেনি" "কোড, স্রেফ একটি আপ ফাংশন নাম বা একটি স্পষ্ট স্থানধারক spot জায়গায় রাখুন? সত্যই কৌতূহলী।
রাদার রেনডোমলেলে

25
আমি পোস্ট করার সময় আমি সত্যই আশা করিনি যে আমি নিজের থেকে আলাদা উত্তর বেছে নেব। এত বড় উপায়ে আমাকে ভুল প্রমাণ করার জন্য আপনাকে ধন্যবাদ। আপনার উত্তরটি দেখে সত্যিই আনন্দিত।
বলভ

4
খুব আকর্ষণীয়! আমি আপনাকে সুপারিশ করব, যদি আপনি এই হ্যাকটি রাখতে চান তবে আপনি ফাংশন কলটির মতো কিছু দিয়ে প্রতিস্থাপন করেন TAKE_INPUT, তারপরে #define TAKE_INPUT whatever_hereউপরে সন্নিবেশ করতে আপনার অনুসন্ধান-প্রতিস্থাপনটি ব্যবহার করুন ।
ড্রাকনিস

18
"আমি এক্স এর প্রতিষ্ঠাতা এবং সেই ব্যক্তি যে এটি তৈরি করেছে" দিয়ে শুরু করে আমাদের আরও উত্তরের প্রয়োজন ।
পাইপ

2
@ iheanyi কেউ একে নিখুঁত হওয়ার জন্য বলেনি। প্রকৃতপক্ষে, আমি নিশ্চিত যে প্রায় কোনও স্থানধারক যে কোনও নবজাতকের কাছে বৈধ কোডের মতো দেখায় তবে আসলে সংকলন করে না এমন কিছু থেকে ভাল হত ।
রাদার রেন্ডোমলেলে

112

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

প্রথমে আসল প্রকারটি পরীক্ষা করা যাক gets। এর জন্য আমার একটু কৌশল আছে:

template <class> struct Name;

int main() { 
    
    Name<decltype(gets)> n;
  
  // keep this function call here
  cout << FirstFactorial(gets(stdin));
  return 0;
    
}

এবং এটি দেখতে ... সাধারণ:

/tmp/613814454/Main.cpp:16:19: warning: 'gets' is deprecated [-Wdeprecated-declarations]
    Name<decltype(gets)> n;
                  ^
/usr/include/stdio.h:638:37: note: 'gets' has been explicitly marked deprecated here
extern char *gets (char *__s) __wur __attribute_deprecated__;
                                    ^
/usr/include/x86_64-linux-gnu/sys/cdefs.h:254:51: note: expanded from macro '__attribute_deprecated__'
# define __attribute_deprecated__ __attribute__ ((__deprecated__))
                                                  ^
/tmp/613814454/Main.cpp:16:26: error: implicit instantiation of undefined template 'Name<char *(char *)>'
    Name<decltype(gets)> n;
                         ^
/tmp/613814454/Main.cpp:12:25: note: template is declared here
template <class> struct Name;
                        ^
1 warning and 1 error generated.

getsঅবচয় হিসাবে চিহ্নিত হয়েছে এবং স্বাক্ষর রয়েছে char *(char *)। তবে কীভাবে FirstFactorial(gets(stdin));সংকলন হয়?

আসুন অন্য কিছু চেষ্টা করুন:

int main() { 
  Name<decltype(gets(stdin))> n;
  
  // keep this function call here
  cout << FirstFactorial(gets(stdin));
  return 0;
    
} 

যা আমাদের দেয়:

/tmp/286775780/Main.cpp:15:21: error: implicit instantiation of undefined template 'Name<int>'
  Name<decltype(8)> n;
                    ^

অবশেষে আমরা কিছু পাচ্ছেন: decltype(8)। সুতরাং gets(stdin)পুরোটি পাঠ্যগতভাবে ইনপুট ( 8) দ্বারা প্রতিস্থাপিত হয়েছিল ।

এবং জিনিসগুলি অস্থির হয়ে ওঠে। সংকলক ত্রুটি অবিরত:

/tmp/596773533/Main.cpp:18:26: error: no matching function for call to 'gets'
  cout << FirstFactorial(gets(stdin));
                         ^~~~
/usr/include/stdio.h:638:14: note: candidate function not viable: no known conversion from 'struct _IO_FILE *' to 'char *' for 1st argument
extern char *gets (char *__s) __wur __attribute_deprecated__;

সুতরাং এখন আমরা এর জন্য প্রত্যাশিত ত্রুটি পেয়েছি cout << FirstFactorial(gets(stdin));

আমি একটি ম্যাক্রো পরীক্ষা করেছি এবং যেহেতু #undef getsকিছুই করার মতো মনে হচ্ছে এটি ম্যাক্রো নয় বলে মনে হচ্ছে।

কিন্তু

std::integral_constant<int, gets(stdin)> n;

এটি সংকলন করে

কিন্তু

std::integral_constant<int, gets(stdin)> n;    // OK
std::integral_constant<int, gets(stdin)> n2;   // ERROR                                          wtf??

n2লাইনে প্রত্যাশিত ত্রুটিটি সহ নয় ।

এবং আবারও, প্রায় কোনও পরিবর্তনই mainলাইনটিকে cout << FirstFactorial(gets(stdin));প্রত্যাশিত ত্রুটিটি থেকে বের করে দেয়।

তবুও stdinআসলে খালি মনে হচ্ছে।

সুতরাং আমি কেবল উপসংহারে অনুমান করতে পারি এবং তাদের অনুমান করতে পারি যে তাদের কাছে একটি সামান্য প্রোগ্রাম রয়েছে যা উত্সটি বিশ্লেষণ করে এবং gets(stdin)পরীক্ষার কেস ইনপুট মানটি বাস্তবে সংকলকটিতে খাওয়ানোর আগে প্রতিস্থাপন করার চেষ্টা করে (খারাপভাবে) । কারও কাছে যদি আরও ভাল তত্ত্ব থাকে বা আসলে তারা কী করছে তা জানেন তবে শেয়ার করুন!

এটি অবশ্যই খুব খারাপ অনুশীলন। এটি গবেষণা করার সময় আমি জানতে পেরেছিলাম যে এখানে কমপক্ষে একটি প্রশ্ন রয়েছে ( উদাহরণস্বরূপ ) এবং কারণ লোকেরা বুঝতে পারে না যে সেখানে কোনও সাইট রয়েছে যারা এই কাজ করে তাদের উত্তর "হ'ল getsব্যবহার করুন ... পরিবর্তে" ব্যবহার করুন যা আসলেই একটি ভাল পরামর্শ তবে কেবল ওপিকে আরও বিভ্রান্ত করে যেহেতু স্টিডিনের কাছ থেকে কোনও বৈধ পঠনের কোনও প্রচেষ্টা এই সাইটে ব্যর্থ হবে।


TLDR

gets(stdin)অবৈধ সি ++। এই নির্দিষ্ট সাইটটি এটি ব্যবহার করে এমন একটি চালাকি ((কী কারণে আমি বুঝতে পারি না)। আপনি যদি সাইটে জমা দেওয়া চালিয়ে যেতে চান তবে (আমি এটির পক্ষেও সমর্থন দিচ্ছি না এবং এটি সমর্থনও করছি না) আপনাকে এই নির্মাণটি ব্যবহার করতে হবে যা অন্যথায় অর্থবোধ করে না, তবে সচেতন হন যে এটি ভঙ্গুর। প্রায় কোনও পরিবর্তনই mainত্রুটি ছুঁড়ে দেবে। এই সাইটের বাইরে সাধারণ ইনপুট পড়ার পদ্ধতি ব্যবহার করুন।


27
আমি সত্যই অবাক। কোডিং চ্যালেঞ্জ সাইটগুলি থেকে কেন শিখবেন না সে সম্পর্কে এই প্রশ্ন / এ হতে পারে একটি সাধারণ পোস্ট হতে পারে।
আইজেল

28
সত্যিই খারাপ কিছু ঘটছে এবং আমি মনে করি এটি সংকলকের বাইরে উত্স কোডের পাঠ্য প্রতিস্থাপনের স্তরে। এটি ব্যবহার করে দেখুন: std::cout << "gets(stdin)";এবং আউটপুটটি 8(বা আপনি 'ইনপুট' ক্ষেত্রে টাইপ করুন যাই হোক না কেন এটি ভাষার অপমানজনক অপব্যবহার
আইজেল

14
@ স্টোবার চারপাশে উদ্ধৃতিগুলি নোট করুন "gets(stdin)"। এটি এমন একটি স্ট্রিং আক্ষরিক যা প্রিপ্রসেসরও স্পর্শ করতে পারে না
আইজেল

2
জেমস কার্ককে উদ্ধৃত করার জন্য: "এটি হ'ল উদ্ভট।"
ApproachingDarknessFish

2
@ এলটারেজেল আপনার উচ্চ ঘোড়া থেকে নামুন। কোডিং চ্যালেঞ্জ সাইটগুলি থেকে শেখা দরকারী কিনা সে সম্পর্কে এটি কোনও বিবৃতি নয়। লোকেরা কীভাবে স্টাফ অনুশীলন করে তা আপনি কে স্থির করবেন?
ম্যাটসেম্যান

66

mainকোডারবাইট সম্পাদকটিতে নিম্নলিখিত সংযোজনের চেষ্টা করেছি :

std::cout << "gets(stdin)";

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

8

যেখানে মানটি 8সম্পাদকের অধীনে সুবিধাজনক 'ইনপুট' ক্ষেত্র থেকে সরাসরি নেওয়া হয় ।

যাদু কোড

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

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

আমি নিশ্চিত যে এটি কেবলমাত্র ব্যবহার করা এবং একটি প্রোগ্রামে কেবল ইনপুট স্ট্রিম করা এই কঠিন হতে পারে না std::cin


এবং এটি এমনকি অন্ধও "সন্ধান করুন এবং প্রতিস্থাপন করুন" না কারণ এটি কখনও কখনও এটি প্রতিস্থাপন করে it
বলভ

4
@ বলভ কি এটি gets(stdin)প্রতিস্থাপনের প্রথম ঘটনা হতে পারে ? আমি বোঝায় 'অন্ধ' এই অর্থে যে এটি ভাষার সিনট্যাক্স বা ব্যাকরণ সম্পর্কে অজানা বলে মনে হচ্ছে।
আইগেল

হ্যাঁ তুমিই ঠিক. এটি প্রথম ঘটনাটি প্রতিস্থাপন করে। আমি প্রধানের আগে একটি রাখার চেষ্টা করেছি এবং এটিই আমি পেয়েছি।
বলভ

1
আরও গবেষণা পরামর্শ দেয় যে সাইটটি এটি কেবল সি ++ - অজগর / রুবি নয় বরং সমস্ত ভাষার জন্য ব্যবহার করে এটি ফাংশন কল ("কাঁচা_পিনপুট ()" বা "এসটিডিআইএনজেটস") ব্যবহার করে যা স্ট্যান্ডিনের থেকে সাধারণত একটি স্ট্রিং ফেরত দেয় তবে শেষ হয় না পরিবর্তে স্ট্রিংয়ের একটি স্ট্রিং প্রতিস্থাপন। আমি অনুমান করি যে গেটলাইন ফাংশনের জন্য একটি রেজেক্স ম্যাচ সন্ধান করা খুব কঠিন ছিল, তাই তারা সি / সি ++ এর জন্য গেটস (স্টাডিন) নিয়ে গেল।
স্টোবর

4
@ স্টোবার ডাং, আপনি ঠিক বলেছেন আমি জাভাতেও এটি ঘটতে পারি তা নিশ্চিত করতে পারি, লাইনটি System.out.print(FirstFactorial(s.nextLine()9));অপরিজ্ঞাতকৃত 89হলেও মুদ্রণ করে s
আইগেল
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.