নাল টার্মিনেটেড স্ট্রিংগুলির যৌক্তিকতা কী?


281

আমি সি এবং সি ++ কে যতটা ভালোবাসি, আমি নাল টার্মিনেটেড স্ট্রিংয়ের পছন্দগুলিতে আমার মাথাটি স্ক্র্যাচ করতে সাহায্য করতে পারি না:

  • দৈর্ঘ্যের উপসর্গযুক্ত (অর্থাত্ পাস্কাল) স্ট্রিংস সি এর আগে বিদ্যমান ছিল
  • দৈর্ঘ্যের উপসর্গযুক্ত স্ট্রিং ধ্রুবক সময় দৈর্ঘ্যের অনুসন্ধানের অনুমতি দিয়ে বেশ কয়েকটি অ্যালগরিদমকে দ্রুত তৈরি করে।
  • দৈর্ঘ্যের পূর্বনির্ধারিত স্ট্রিংগুলি বাফার ওভাররন ত্রুটিগুলি আরও বেশি করে তোলে।
  • এমনকি একটি 32 বিট মেশিনেও, আপনি যদি স্ট্রিংটি উপলব্ধ মেমরির আকার হিসাবে মঞ্জুর করেন তবে দৈর্ঘ্যের উপসর্গযুক্ত স্ট্রিংটি নাল টার্মিনেটেড স্ট্রিংয়ের চেয়ে কেবল তিন বাইট বিস্তৃত। 16 বিট মেশিনে এটি একটি একক বাইট। Bit৪ বিট মেশিনে, 4 জিবি একটি যুক্তিসঙ্গত স্ট্রিং দৈর্ঘ্যের সীমা, তবে আপনি যদি মেশিন শব্দের আকারে এটি প্রসারিত করতে চান তবে bit৪ বিট মেশিনে সাধারণত পর্যাপ্ত মেমরি থাকে অতিরিক্ত সাত বাইটকে নাল আর্গুমেন্ট তৈরি করে। আমি জানি আসল সি স্ট্যান্ডার্ডটি অত্যন্ত ক্ষীণ মেশিনের জন্য লেখা হয়েছিল (মেমরির ক্ষেত্রে), তবে দক্ষতার যুক্তি আমাকে এখানে বিক্রি করে না।
  • খুব সুন্দর প্রতিটি অন্যান্য ভাষা (যেমন পার্ল, পাস্কাল, পাইথন, জাভা, সি # ইত্যাদি) দৈর্ঘ্যের উপসর্গযুক্ত স্ট্রিং ব্যবহার করে। এই ভাষাগুলি সাধারণত স্ট্রিং ম্যানিপুলেশন বেঞ্চমার্কগুলিতে সিটিকে পরাজিত করে কারণ তারা স্ট্রিংগুলির সাথে আরও দক্ষ।
  • সি ++ এটি std::basic_stringটেমপ্লেটটি দিয়ে কিছুটা সংশোধন করেছে , তবে নাল টার্মিনেটেড স্ট্রিংগুলি প্রত্যাশী সরল চরিত্রের অ্যারেগুলি এখনও বিস্তৃত। এটিও অসম্পূর্ণ কারণ এটির জন্য হ্যাপ বরাদ্দ প্রয়োজন।
  • নাল টার্মিনেটেড স্ট্রিংগুলিতে একটি অক্ষর সংরক্ষণ করা উচিত (যথা, নাল), যা স্ট্রিংয়ে বিদ্যমান থাকতে পারে না, যখন দৈর্ঘ্যের উপসর্গযুক্ত স্ট্রিংগুলিতে এমবেডড নাল থাকতে পারে।

এর মধ্যে বেশ কয়েকটি বিষয় সি এর চেয়ে সাম্প্রতিককালে প্রকাশিত হয়েছে, সুতরাং সিগুলি সেগুলি না জানার জন্য এটি বোধগম্য হবে। তবে সি হওয়ার আগে বেশ কয়েকটি বেশ ভাল ছিল। কেন সুস্পষ্টতর উচ্চতর দৈর্ঘ্যের উপসর্গের পরিবর্তে নাল টার্মিনেটেড স্ট্রিংগুলি বেছে নেওয়া হবে?

সম্পাদনা : যেহেতু কিছু উপরে আমার দক্ষতার পয়েন্টে কিছু তথ্য চেয়েছিল (এবং আমি ইতিমধ্যে সরবরাহিত বিষয়গুলি পছন্দ করে না), সেগুলি কয়েকটি জিনিস থেকে শুরু করে:

  • নাল টার্মিনেটেড স্ট্রিং ব্যবহার করে কনক্যাটটির জন্য ও (এন + এম) সময়ের জটিলতা প্রয়োজন। দৈর্ঘ্যের উপসর্গের জন্য প্রায়শই কেবল ও (এম) প্রয়োজন হয়।
  • নাল টার্মিনেটেড স্ট্রিংগুলি ব্যবহার করে দৈর্ঘ্যের জন্য ও (এন) সময়ের জটিলতা প্রয়োজন। দৈর্ঘ্যের উপসর্গটি হ'ল ও (1)।
  • দৈর্ঘ্য এবং কনক্যাট এখন পর্যন্ত সবচেয়ে সাধারণ স্ট্রিং অপারেশন। এমন বেশ কয়েকটি মামলা রয়েছে যেখানে নাল টার্মিনেটেড স্ট্রিংগুলি আরও কার্যকর হতে পারে তবে এগুলি প্রায়শই কম ঘটে।

নীচের উত্তরগুলি থেকে, এগুলি এমন কয়েকটি ক্ষেত্রে রয়েছে যেখানে নাল টার্মিনেটেড স্ট্রিংগুলি আরও কার্যকর:

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

উপরের কোনওটি দৈর্ঘ্য এবং কনকটের মতো প্রায় সাধারণ নয়।

নীচে উত্তরগুলিতে আরও একটি জোর দেওয়া আছে:

  • আপনার স্ট্রিংয়ের শেষটি কেটে ফেলতে হবে

তবে এটি একটি ভুল - এটি নাল টার্মিনেটেড এবং দৈর্ঘ্যের উপসর্গযুক্ত স্ট্রিংগুলির জন্য একই সময়ের পরিমাণ। (নাল টার্মিনেটেড স্ট্রিংগুলি কেবল একটি নাল আটকে থাকে যেখানে আপনি নতুন প্রান্তটি চান, দৈর্ঘ্যের উপসর্গগুলি কেবল উপসর্গ থেকে বিয়োগ করে।)


110
আমি সবসময় ভেবেছিলাম এটি সমস্ত সি ++ প্রোগ্রামারদের নিজস্ব স্ট্রিং লাইব্রেরি লিখতে পারা যায়।
জুলিয়েট

31
যুক্তিযুক্ত ব্যাখ্যাগুলি আশা করার বিষয়ে এটি এখন What's আমি মনে করি আপনি x86 বা ডস এর জন্য যুক্তি শুনতে চান? আমি যতটা উদ্বিগ্ন, সবচেয়ে খারাপ প্রযুক্তি জিতেছে। প্রত্যেকবার. এবং সবচেয়ে খারাপ স্ট্রিং প্রতিনিধিত্ব।
জাল্ফ

4
আপনি কেন দৈর্ঘ্যের উপসর্গের স্ট্রিংগুলি সর্বোত্তম বলে দাবি করেন? সর্বোপরি সি জনপ্রিয় হয়ে ওঠে কারণ এটি নাল-টার্মিনেটেড স্ট্রিং ব্যবহার করে যা এটিকে অন্য ভাষা থেকে পৃথক করে দেয়।
ড্যানিয়েল সি। সোব্রাল

44
@ ড্যানিয়েল: সি জনপ্রিয় হয়ে ওঠে কারণ এটি ভন নিউমান মেশিনে কার্যকর প্রোগ্রামগুলির একটি সাধারণ, দক্ষ এবং পোর্টেবল উপস্থাপনা এবং কারণ এটি ইউনিক্সের জন্য ব্যবহৃত হয়েছিল। এটি অবশ্যই তা নয় কারণ এটি নাল টার্মিনেটেড স্ট্রিংগুলি ব্যবহার করার সিদ্ধান্ত নিয়েছে। যদি এটি একটি ভাল ডিজাইনের সিদ্ধান্ত হয়, লোকেরা এটি অনুলিপি করত, এবং তারা তা করে নি। তারা অবশ্যই সি থেকে অন্য সব কিছু অনুলিপি করেছেন
বিলি ওনিল

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

উত্তর:


195

থেকে ঘোড়ার মুখ

বিসিপিএল, বি, বা সি কেউই ভাষায় দৃ in়তার সাথে ডেটা সমর্থন করে না; প্রত্যেকটি স্ট্রিংগুলি বেশ কয়েকটি কনভেনশন দ্বারা পূর্ণসংখ্যার ভেক্টর এবং সাধারণ নিয়মের পরিপূরক হিসাবে স্ট্রিং করে। বিসিপিএল এবং বি উভয় ক্ষেত্রে একটি স্ট্রিং আক্ষরিক কক্ষগুলিতে প্যাক করা স্ট্রিংয়ের অক্ষরগুলির সাথে সূচনা করা স্থির ক্ষেত্রের ঠিকানাটি বোঝায়। বিসিপিএলে, প্রথম প্যাক করা বাইটে স্ট্রিংয়ের অক্ষরের সংখ্যা রয়েছে; বি তে, কোনও গণনা নেই এবং স্ট্রিংগুলি একটি বিশেষ চরিত্র দ্বারা শেষ করা হয়, যা বি বানান করে *e। এই পরিবর্তনটি একটি 8- বা 9-বিট স্লটে গণনাটি ধরে রেখে স্ট্রিংয়ের দৈর্ঘ্যের সীমাবদ্ধতা এড়ানোর জন্য আংশিকভাবে করা হয়েছিল এবং আংশিক কারণ গণনা বজায় রাখার কারণে আমাদের অভিজ্ঞতাতে টার্মিনেটর ব্যবহার করার চেয়ে কম সুবিধাজনক বলে মনে হয়েছিল।

ডেনিস এম রিচি, সি ভাষার বিকাশ


12
আরেকটি প্রাসঙ্গিক উক্তি: "... স্ট্রিংগুলির শব্দার্থক
শব্দগুলি

151

সি এর ভাষার অংশ হিসাবে স্ট্রিং নেই। সি-তে একটি 'স্ট্রিং' কেবলমাত্র একটি পয়েন্টার। সুতরাং আপনি ভুল প্রশ্ন জিজ্ঞাসা করছেন।

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

নীচে রাগিং স্কোয়ালের আলোকে:

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


29
char *temp = "foo bar";সি একটি বৈধ বিবৃতি ... আরে! এটি একটি স্ট্রিং না? এটা কি বাতিল?
ইয়ানিক রোচন

56
@ ইয়ানিক: শেষের দিকে নাল দিয়ে চরের অ্যারে তৈরি করতে সংকলককে বলার এটি কেবল একটি সহজ উপায়। এটি 'স্ট্রিং' নয়
রবার্ট এস সিয়াসসিও

28
@ ক্যালভেরা: তবে এটির অর্থ কেবল "এই স্ট্রিং সামগ্রী এবং একটি দুটি বাইট দৈর্ঘ্যের উপসর্গ সহ একটি মেমরি বাফার তৈরি করা" হতে পারে
বিলি ওনিল

14
@ বিলি: যেহেতু একটি 'স্ট্রিং' আসলে চরের কাছে কেবলমাত্র একটি পয়েন্টার, যা বাইটের সাথে পয়েন্টারের সমতুল্য, আপনি কীভাবে জানবেন যে আপনি যে বাফারটির সাথে व्यवहार করছেন তা আসলে একটি 'স্ট্রিং' হওয়ার উদ্দেশ্যে করা হয়েছে? এটি বোঝাতে আপনার চর / বাইট * ব্যতীত অন্য কোনও ধরণের প্রয়োজন হবে। সম্ভবত একটি কাঠামো?
রবার্ট এস সিয়াসসিও

27
আমি মনে করি @ ক্যালভেরা ঠিক আছে, সি এর স্ট্রিংগুলির জন্য কোনও ডেটা টাইপ নেই। ঠিক আছে, আপনি একটি স্ট্রিংয়ের মতো অক্ষরের অ্যারে বিবেচনা করতে পারেন, তবে এর অর্থ এটি সর্বদা একটি স্ট্রিং নয় (স্ট্রিংয়ের জন্য আমি একটি নির্দিষ্ট অর্থ সহ অক্ষরের ক্রম বলতে চাইছি)। একটি বাইনারি ফাইলটি হল অক্ষরের অ্যারে, কিন্তু এই অক্ষরগুলি মানুষের জন্য কিছু বোঝায় না।
ব্ল্যাকবিয়ার

106

প্রশ্নটিকে Length Prefixed Strings (LPS)বনাম zero terminated strings (SZ)জিনিস হিসাবে জিজ্ঞাসা করা হয় তবে বেশিরভাগ দৈর্ঘ্যের উপসর্গযুক্ত স্ট্রিংয়ের সুবিধা প্রকাশ করে। এটি অপ্রতিরোধ্য মনে হতে পারে তবে সত্য কথা বলতে আমাদের এলপিএসের অপূর্ণতা এবং এসজেডের সুবিধাগুলিও বিবেচনা করা উচিত।

আমি এটি যেভাবে বুঝতে পারি, প্রশ্নটি "জিরো টার্মিনেটেড স্ট্রিংসের সুবিধা কী কী?" জিজ্ঞাসা করার পক্ষপাতদুষ্ট উপায় হিসাবেও বোঝা যেতে পারে।

জিরো টার্মিনেটেড স্ট্রিংগুলির সুবিধা (আমি দেখতে পাচ্ছি):

  • খুব সহজ, ভাষার ক্ষেত্রে নতুন ধারণাগুলি প্রবর্তনের দরকার নেই, চর অ্যারে / চর পয়েন্টারগুলি করতে পারে।
  • মূল ভাষায় ডাবল কোটের মধ্যে কিছু কিছু অক্ষরে রূপান্তর করতে ন্যূনতম সিনট্যাক্সিক চিনি অন্তর্ভুক্ত করা হয় (সত্যই বাইটগুলির একটি গুচ্ছ)। কিছু ক্ষেত্রে এটি সম্পূর্ণরূপে পাঠ্যের সাথে সম্পর্কিত নয় এমন জিনিসগুলির সূচনা করতে ব্যবহার করা যেতে পারে। উদাহরণস্বরূপ xpm চিত্র ফাইল ফর্ম্যাটটি একটি বৈধ সি উত্স যা স্ট্রিং হিসাবে এনকোড করা চিত্রের ডেটা ধারণ করে।
  • যাইহোক, আপনি করতে পারেন একটি স্ট্রিং আক্ষরিক একটি শূন্য করা কম্পাইলার শুধু এছাড়াও আক্ষরিক শেষে অন্য এক যোগ হবে: "this\0is\0valid\0C"। এটা কি স্ট্রিং? বা চারটি স্ট্রিং? বা একগুচ্ছ বাইট ...
  • সমতল বাস্তবায়ন, কোনও গোপন ইন্ডিয়ারেশন, কোনও লুকানো পূর্ণসংখ্যা।
  • কোনও লুকানো মেমরির বরাদ্দ জড়িত নেই (ভাল, স্টার্ডআপের মতো কিছু কুখ্যাত অ-স্ট্যান্ডার্ড ফাংশন বরাদ্দ সম্পাদন করে তবে এটি বেশিরভাগ সমস্যার উত্স হয়)।
  • ছোট বা বড় হার্ডওয়ারের জন্য কোনও নির্দিষ্ট সমস্যা নেই (8 বিট মাইক্রোকন্ট্রোলারগুলিতে 32 বিটস উপসর্গ দৈর্ঘ্য পরিচালনা করার ভারটি কল্পনা করুন বা স্ট্রিংয়ের আকার 256 বাইটেরও কম সীমাবদ্ধ করার সীমাবদ্ধতা ছিল না, এটি আসলে আমার আগে টার্বো পাস্কাল এনেসের সমস্যা ছিল)।
  • স্ট্রিং ম্যানিপুলেশন বাস্তবায়ন হ'ল মুষ্টিমেয় খুব সাধারণ লাইব্রেরি ফাংশন
  • স্ট্রিংগুলির প্রধান ব্যবহারের জন্য দক্ষ: একটি পরিচিত শুরু থেকে ক্রমাগত পাঠ্য ধ্রুবক পাঠ্য (বেশিরভাগ ব্যবহারকারীর কাছে বার্তা)।
  • সমাপ্তি শূন্য এমনকি বাধ্যতামূলক নয়, বাইটগুলির একগুচ্ছের মতো চরগুলি চালনার জন্য প্রয়োজনীয় সমস্ত সরঞ্জাম উপলব্ধ। সি তে অ্যারে ইনিশিয়েশন করার সময়, আপনি এমনকি এনএইউএল টার্মিনেটর এড়াতে পারেন। ঠিক সঠিক আকার সেট করুন। char a[3] = "foo";বৈধ সি (সি ++ নয়) এবং এ-তে একটি চূড়ান্ত শূন্য রাখবে না।
  • স্ট্যান্ডিন, স্টডআউটের মতো কোনও অন্তর্নিহিত দৈর্ঘ্য নেই এমন "ফাইলগুলি" সহ "ইউনিক্স দর্শন" সমস্ত কিছু ফাইলের সাথে সামঞ্জস্যপূর্ণ। আপনার মনে রাখা উচিত যে ওপেন রিড এবং রাইটিং আদিমগুলি খুব নিম্ন স্তরে প্রয়োগ করা হয়। এগুলি লাইব্রেরি কল নয়, সিস্টেম কল। এবং একই এপিআই বাইনারি বা পাঠ্য ফাইলগুলির জন্য ব্যবহৃত হয়। ফাইল রিডিং আদিমরা একটি বাফার ঠিকানা এবং একটি আকার পায় এবং নতুন আকার ফিরে দেয়। এবং আপনি লেখার জন্য বাফার হিসাবে স্ট্রিং ব্যবহার করতে পারেন। অন্য ধরণের স্ট্রিং প্রতিনিধিত্ব ব্যবহার করলে বোঝা যায় যে আউটপুট দেওয়ার জন্য আপনি আক্ষরিক স্ট্রিংটি সহজেই বাফার হিসাবে ব্যবহার করতে পারবেন না, বা এটি ingালাইয়ের সময় আপনাকে এটি খুব অদ্ভুত আচরণ করতে হবে char*। অর্থাত্ স্ট্রিংয়ের ঠিকানাটি ফেরত পাঠানো নয়, পরিবর্তে আসল ডেটা ফেরত দেওয়া।
  • বাফারের অকেজো অনুলিপি ব্যতীত কোনও ফাইল থেকে পাঠ্য ডেটা ম্যানিপুলেট করা খুব সহজ, সঠিক জায়গাগুলিতে কেবল শূন্যগুলি সন্নিবেশ করান (ভাল, ডাবল কোটযুক্ত স্ট্রিং হিসাবে আধুনিক সি দিয়ে সত্যই নয়, এখন আর সাধারণত পরিবর্তনযোগ্য ডেটাতে রাখা হয় সেগমেন্ট)।
  • আকার যাইহোক আকারের কিছু পূর্বনির্ধারিত মানগুলি প্রান্তিককরণের সমস্যাগুলি বোঝায়। প্রাথমিক দৈর্ঘ্যটি প্রান্তিককরণ করা উচিত, তবে ডাতাস অক্ষরগুলির জন্য এটি করার কোনও কারণ নেই (এবং আবার স্ট্রিংগুলির প্রান্তিককরণ বাধ্যকরণের সাথে সমস্যাগুলি বোঝানো হবে যখন তাদেরকে একগুচ্ছ বাইট হিসাবে বিবেচনা করা হবে)।
  • ধ্রুবক আক্ষরিক স্ট্রিং (আকারের) জন্য দৈর্ঘ্য সংকলন সময়ে জানা যায়। সুতরাং কেন কেউ এটিকে প্রকৃত ডেটাতে প্রেরণে মেমরির মধ্যে রাখতে চাইবে?
  • সি এক উপায়ে (প্রায়) সকলের মতো করছে, স্ট্রিংগুলি চরের অ্যারে হিসাবে দেখা হয়। অ্যারের দৈর্ঘ্য সি দ্বারা পরিচালিত না হওয়ায় এটি যৌক্তিক দৈর্ঘ্যটি স্ট্রিংয়ের জন্য পরিচালিত হয় না। একমাত্র আশ্চর্যের বিষয় হল 0 টি আইটেমটি শেষে যুক্ত করা হয়েছিল, তবে ডাবল উদ্ধৃতিগুলির মধ্যে একটি স্ট্রিং টাইপ করার সময় এটি মূল ভাষার স্তরে রয়েছে। ব্যবহারকারীরা দৈর্ঘ্য পেরিয়ে স্ট্রিং ম্যানিপুলেশন ফাংশনগুলিকে পুরোপুরি কল করতে পারে বা তার পরিবর্তে সরল মেমকোপি ব্যবহার করতে পারে। এসজেড কেবল একটি সুবিধা। বেশিরভাগ অন্যান্য ভাষায় অ্যারের দৈর্ঘ্য পরিচালিত হয়, এটি স্ট্রিংগুলির জন্য একইরকম যৌক্তিক।
  • আধুনিক সময়ে যাইহোক 1 বাইট চরিত্রের সেটগুলি পর্যাপ্ত নয় এবং আপনাকে প্রায়শই এনকোডযুক্ত ইউনিকোড স্ট্রিংগুলির সাথে মোকাবিলা করতে হয় যেখানে অক্ষরের সংখ্যা বাইটের সংখ্যার থেকে খুব আলাদা। এর দ্বারা বোঝা যাচ্ছে যে ব্যবহারকারীরা সম্ভবত "কেবলমাত্র আকার" এর চেয়ে বেশি, তবে অন্যান্য তথ্যও চাইবেন। দৈর্ঘ্য বজায় রাখার জন্য এই অন্যান্য দরকারী দরকারী টুকরোগুলি সম্পর্কিত কিছুই ব্যবহার (বিশেষত কোনও প্রাকৃতিক জায়গা রাখার জন্য নয়)।

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

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

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

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

আমাকে কিছুটা হতাশ করার একমাত্র বিষয়টি হল স্ট্রিংগুলি utf-8 হওয়ার কথা, তবে দৈর্ঘ্য সম্ভবত এখনও বহু বাইট ব্যবহার করেও কমপক্ষে বাইটগুলি (কমপক্ষে এটি আমার সংকলক জিডিসিতে সত্য) ফিরিয়ে দেয়। এটি আমার কাছে অস্পষ্ট যে এটি সংকলক বাগ বা উদ্দেশ্য অনুসারে। (ঠিক আছে, সম্ভবত আমি কী ঘটেছে তা জানতে পেরেছি D ডি সংকলককে আপনার উত্সটি ইউটিএফ -8 ব্যবহার করার জন্য আপনাকে প্রথমে কিছু বোকা অর্ডার চিহ্ন লাগাতে হবে I আমি বোকা লিখি কারণ আমি জানি না যে সম্পাদক এটি করছেন না, বিশেষত ইউটিএফ- 8 এটি ASCII সামঞ্জস্যপূর্ণ বলে মনে করা হয়)।


7
... অবিরত ... আপনার বেশিরভাগ পয়েন্ট আমার কাছে মনে হয় কেবল সাধারণ ভুল, অর্থাত "" সবকিছুই একটি ফাইল "যুক্তি। ফাইলগুলি অনুক্রমিক অ্যাক্সেস, সি স্ট্রিংগুলি নয়। দৈর্ঘ্যের উপসর্গটি নূন্যতম সিনট্যাকটিক চিনি দিয়েও করা যেতে পারে। এখানে একমাত্র যুক্তিযুক্ত যুক্তি হ'ল ছোট (অর্থাত্ 8 বিট) হার্ডওয়্যারে 32 বিট উপসর্গ পরিচালনা করার চেষ্টা করা; আমি মনে করি যে দৈর্ঘ্যের আকার বাস্তবায়ন দ্বারা নির্ধারিত হয় কেবল এটির মাধ্যমে সমাধান করা যায়। সর্বোপরি, এটি কি std::basic_stringকরে।
বিলি ওনিল

3
@ বিলি ওনিল: সত্যিই আমার উত্তর দুটি পৃথক অংশ আছে। একটি 'কোর সি ল্যাঙ্গুয়েজ' এর অংশটি সম্পর্কে, অন্যটি স্ট্যান্ডার্ড লাইব্রেরিগুলি কী সরবরাহ করতে হবে সে সম্পর্কে। স্ট্রিং সমর্থন সম্পর্কে, মূল ভাষা থেকে কেবল একটি আইটেম রয়েছে: ডাবল উদ্ধৃতিটির অর্থ বাইটের সংযুক্ত গুচ্ছ। আমি সি আচরণে আপনার চেয়ে সত্যই খুশি নই। আমি জাদুকরভাবে অনুভব করি যে প্রতি ডাবল বন্ধের সাথে বাইট বদ্ধ ঘাটি শেষে শূন্যটি যথেষ্ট খারাপ। \0প্রোগ্রামাররা অন্তর্ভুক্তটির পরিবর্তে এটি চাইলে আমি পছন্দ করি এবং শেষ পর্যন্ত স্পষ্ট করে বলতে পারি। প্রস্তুতি দৈর্ঘ্য অনেক খারাপ।
ক্রিস

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

5
@ বিলি "আচ্ছা, অপারেটিং সিস্টেম প্রয়োগকারী সি প্রোগ্রামারদের ০.০% এর জন্য, জরিমানা।" অন্যান্য প্রোগ্রামাররা একটি ভাড়া নিতে পারে। সি একটি অপারেটিং সিস্টেম লেখার জন্য তৈরি হয়েছিল।
ড্যানিয়েল সি সোব্রাল

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

61

আমি মনে করি, এর historical তিহাসিক কারণ রয়েছে এবং এটি উইকিপিডিয়ায় খুঁজে পেয়েছে :

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


2
@ মন্টু হুঁ ... সামঞ্জস্যতা?
খচিক

19
@ মন্টু: কারণ এটি প্রচলিত সি এবং সি ++ কোডের স্মৃতিচিহ্নগুলি ভেঙে দেবে।
বিলি ওনিল

10
@ মন্টু: দৃষ্টান্তগুলি আসে এবং যায়, তবে লিগ্যাসি কোড চিরতরে। সি এর ভবিষ্যতের কোনও সংস্করণকে 0-সমাপ্ত স্ট্রিংগুলিকে সমর্থন অব্যাহত রাখতে হবে, অন্যথায় 30+ বছরের মূল্যবান লিগ্যাসি কোডটি আবার লিখতে হবে (যা ঘটছে না)। এবং যতক্ষণ না পুরানো উপায়টি পাওয়া যায়, ততক্ষণ পর্যন্ত লোকেরা এটি ব্যবহার করতে থাকবে, যেহেতু তারা তাদের সাথে পরিচিত।
জন বোড

8
@ মন্টু: বিশ্বাস করুন, মাঝেমাঝে আমি ইচ্ছা করি। তবে আমি এখনও পাস্কাল স্ট্রিংয়ের চেয়ে 0 টিমিনিটেড স্ট্রিং পছন্দ করব।
জন বোদে

2
উত্তরাধিকার সম্পর্কে কথা বলুন ... সি ++ স্ট্রিংগুলি এখন NUL- সমাপ্ত হতে বাধ্য করা হয়েছে।
জিম বাল্টার

32

Calavera হয় ডান , কিন্তু না মানুষ তার বিন্দু পেতে বলে মনে হচ্ছে না, আমি কিছু কোড উদাহরণ প্রদান করব।

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

সি এর stringমতো টাইপ থাকলে intবা এর মতো char, এটি এমন এক ধরণের যা কোনও রেজিস্টারে বা স্ট্যাকের সাথে খাপ খায় না এবং যে কোনও উপায়ে পরিচালনা করার জন্য মেমরির বরাদ্দ (তার সমস্ত সমর্থনকারী অবকাঠামো সহ) প্রয়োজন হবে। এর সবগুলি সি এর মূল তত্ত্বগুলির বিরুদ্ধে যায় go

সুতরাং, সি এর একটি স্ট্রিং হ'ল:

char s*;

সুতরাং, আসুন তাহলে ধরে নেওয়া যাক এটি দৈর্ঘ্য উপসর্গযুক্ত ছিল। দুটি স্ট্রিং যুক্ত করতে কোড লিখি:

char* concat(char* s1, char* s2)
{
    /* What? What is the type of the length of the string? */
    int l1 = *(int*) s1;
    /* How much? How much must I skip? */
    char *s1s = s1 + sizeof(int);
    int l2 = *(int*) s2;
    char *s2s = s2 + sizeof(int);
    int l3 = l1 + l2;
    char *s3 = (char*) malloc(l3 + sizeof(int));
    char *s3s = s3 + sizeof(int);
    memcpy(s3s, s1s, l1);
    memcpy(s3s + l1, s2s, l2);
    *(int*) s3 = l3;
    return s3;
}

অন্য বিকল্প স্ট্রিং সংজ্ঞায়িত করতে একটি কাঠামো ব্যবহার করা হবে:

struct {
  int len; /* cannot be left implementation-defined */
  char* buf;
}

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

মজার ব্যাপার হচ্ছে ... মত structs যে কি করতে সি থাকবেই! এগুলি কেবল আপনার ব্যবহারকারীর হ্যান্ডলিংয়ে বার্তা প্রদর্শন করার জন্য ব্যবহার করা হয় না।

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

এখন, সি যাইহোক মেমরি পরিচালনা করতে পারে এবং memলাইব্রেরির ফাংশনগুলি (ইন <string.h>, এমনকি!) পয়েন্টার এবং আকারের জোড়া হিসাবে মেমরি হ্যান্ডেল করতে আপনার প্রয়োজনীয় সমস্ত সরঞ্জাম সরবরাহ করে। সি তে তথাকথিত "স্ট্রিংস" কেবল একটি উদ্দেশ্যে তৈরি করা হয়েছিল: পাঠ্য টার্মিনালগুলির উদ্দেশ্যে উদ্দিষ্ট অপারেটিং সিস্টেম লেখার প্রসঙ্গে বার্তা প্রদর্শন করা। এবং, তার জন্য, নাল সমাপ্তি যথেষ্ট।


2
1. +1। ২. স্পষ্টতই যদি ভাষাটির ডিফল্ট আচরণ দৈর্ঘ্যের উপসর্গ ব্যবহার করে তৈরি করা হত তবে এটিকে আরও সহজ করার জন্য অন্যান্য জিনিসও থাকতে পারত। উদাহরণস্বরূপ, সেখানে আপনার সমস্ত ক্যাসেট strlenপরিবর্তে কল এবং বন্ধুদের দ্বারা লুকিয়ে রাখা হত। সমস্যাটি যেমন "এটি বাস্তবায়নের দিকে ছেড়ে দেয়", আপনি বলতে পারেন যে shortলক্ষ্য বাক্সে যা আছে তা উপসর্গটিই । তাহলে আপনার সমস্ত কাস্টিং এখনও কাজ করবে still ৩. আমি সারা দিন ধরে কনট্রিভড দৃশ্যের সাথে আসতে পারি যা এক বা অন্য সিস্টেমকে খারাপ দেখায়।
বিলি ওনিল

5
@ বিলি লাইব্রেরির জিনিসটি যথেষ্ট সত্য, এক্ষেত্রে সি ন্যূনতম বা কোনও লাইব্রেরি ব্যবহারের জন্য তৈরি করা হয়েছিল। উদাহরণস্বরূপ, প্রোটোটাইপগুলির ব্যবহার প্রথমদিকে সাধারণ ছিল না। উপসর্গটি বলা shortকার্যকরভাবে স্ট্রিংয়ের আকারকে সীমাবদ্ধ করে, যা মনে হয় তারা এমন একটি জিনিস যা তারা আগ্রহী ছিল না। নিজেই, 8-বিট বেসিক এবং পাস্কাল স্ট্রিং, ফিক্সড-সাইজের সিওবিএল স্ট্রিং এবং অনুরূপ জিনিসগুলির সাথে কাজ করে, দ্রুত সীমাহীন আকারের সি স্ট্রিংয়ের একটি বিশাল ফ্যান হয়ে ওঠে। আজকাল, 32-বিট আকারের যে কোনও ব্যবহারিক স্ট্রিং পরিচালনা করবে, তবে সেই বাইটগুলি প্রথম দিকে যুক্ত করা সমস্যাযুক্ত ছিল।
ড্যানিয়েল সি সোব্রাল

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

1
আমার দ্বারা +1 আরও একটি জিনিস আমি যুক্ত করতে চাই; স্ট্রাক্ট যেমন আপনি প্রস্তাব করেন এটি একটি বাস্তব stringধরণের দিকে গুরুত্বপূর্ণ পদক্ষেপটি মিস করে : এটি অক্ষর সম্পর্কে অবগত নয়। এটি "চর" এর একটি অ্যারে (মেশিনের লিঙ্গোর একটি "চর" হ'ল "শব্দ" এর মতোই একটি চরিত্র যা একটি বাক্যে মানুষ শব্দকে ডাকবে)। অক্ষরের একটি স্ট্রিং একটি উচ্চ-স্তরের ধারণা যা আপনি এনকোডিংয়ের ধারণাটি প্রবর্তন করলে একটি অ্যারের উপরে প্রয়োগ করা যেতে পারে char
ফ্রেরিচ রাবাবে

2
@ ড্যানিয়েলসি.সোব্রাল: এছাড়াও, আপনি যে কাঠামোর কথা উল্লেখ করেছেন তার জন্য দুটি বরাদ্দ লাগবে না। উভয় ক্ষেত্রেই এটি ব্যবহার আপনি স্ট্যাক এটা আছে হিসাবে (তাই শুধুমাত্র buf, বা ব্যবহারের বরাদ্দের প্রয়োজন) struct string {int len; char buf[]};এবং একটি নমনীয় অ্যারের সদস্য হিসেবে এক বরাদ্দ দিয়ে পুরো জিনিস বরাদ্দ, এবং একটি হিসাবে প্রায় এটা পাস string*। (বা struct string {int capacity; int len; char buf[]};
স্পষ্টত

20

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

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


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

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

13

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

আসুন সিউডো কোডে দেখতে দিন

function readString(string) // 1 parameter: 1 register or 1 stact entries
    pointer=addressOf(string) 
    while(string[pointer]!=CONTROL_CHAR) do
        read(string[pointer])
        increment pointer

মোট 1 টি রেজিস্টার ব্যবহার

কেস 2

 function readString(length,string) // 2 parameters: 2 register used or 2 stack entries
     pointer=addressOf(string) 
     while(length>0) do 
         read(string[pointer])
         increment pointer
         decrement length

মোট 2 টি রেজিস্টার ব্যবহৃত

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

যুক্তিযুক্ত কারণে আমি 2 টি সাধারণ স্ট্রিং অপারেশন বাস্তবায়ন করব

stringLength(string)
     pointer=addressOf(string)
     while(string[pointer]!=CONTROL_CHAR) do
         increment pointer
     return pointer-addressOf(string)

জটিলতা O (n) যেখানে বেশিরভাগ ক্ষেত্রে PASCAL স্ট্রিং O (1) হয় কারণ স্ট্রিংয়ের দৈর্ঘ্য স্ট্রিং কাঠামোর পূর্ব-পেন্ডিং থাকে (এর অর্থ এইও হবে যে এই অপারেশনটি প্রথম পর্যায়ে বহন করতে হবে)।

concatString(string1,string2)
     length1=stringLength(string1)
     length2=stringLength(string2)
     string3=allocate(string1+string2)
     pointer1=addressOf(string1)
     pointer3=addressOf(string3)
     while(string1[pointer1]!=CONTROL_CHAR) do
         string3[pointer3]=string1[pointer1]
         increment pointer3
         increment pointer1
     pointer2=addressOf(string2)
     while(string2[pointer2]!=CONTROL_CHAR) do
         string3[pointer3]=string2[pointer2]
         increment pointer3
         increment pointer1
     return string3

জটিলতা ও (এন) এবং স্ট্রিংয়ের দৈর্ঘ্যের প্রস্তুতি নেওয়া অপারেশনের জটিলতা পরিবর্তন করতে পারে না, আমি স্বীকার করি যে এটিতে 3 সময় কম সময় লাগবে।

অন্যদিকে, আপনি যদি পাস্কাল স্ট্রিংটি ব্যবহার করেন তবে অ্যাকাউন্ট নিবন্ধের দৈর্ঘ্য এবং বিট-এন্ডিয়ানস নেওয়ার জন্য আপনাকে আপনার এপিআইকে নতুন করে ডিজাইন করতে হবে, পাস্কাল স্ট্রিংটি 255 চর (0xFF) বিচ এর সুপরিচিত সীমাবদ্ধতা পেয়েছে কারণ দৈর্ঘ্যটি 1 বাইট (8 বিট) সংরক্ষণ করা হয়েছিল ), এবং এটি আপনি একটি দীর্ঘ স্ট্রিং চেয়েছিলেন (16 বেটস-> যে কোনও কিছু) আপনার কোডের এক স্তরতে আপনাকে আর্কিটেকচারটি গ্রহণ করতে হবে, এর অর্থ বেশিরভাগ ক্ষেত্রে বেমানান স্ট্রিং এপিআই যদি আপনি আরও দীর্ঘ স্ট্রিং চান তবে এটি হতে পারে।

উদাহরণ:

একটি 8 টি বিট কম্পিউটারে আপনার প্রিপেন্ডেড স্ট্রিং এপিআই দিয়ে একটি ফাইল লেখা হয়েছিল এবং তারপরে 32 বিট কম্পিউটারে পড়তে হবে, অলস প্রোগ্রামটি কী বোঝায় যে আপনার 4 বাইটস স্ট্রিংয়ের দৈর্ঘ্য, তারপরে সেই প্রচুর মেমরি বরাদ্দ করতে পারে তারপরে সেই বহু বাইট পড়ার চেষ্টা করুন। অন্য কেসটি হবে পিপিসি 32 বাইট স্ট্রিং রিড (ছোট এডিয়ান) একটি x86 (বড় এন্ডিয়ান) এর উপর, অবশ্যই যদি আপনি না জানেন যে অন্যটি লিখেছেন তবে সমস্যা হতে পারে। 1 বাইট দৈর্ঘ্য (0x00000001) হবে 16777216 (0x0100000) যা 1 বাইট স্ট্রিং পড়ার জন্য 16 এমবি MB অবশ্যই আপনি বলবেন যে লোকেদের একটি মানদণ্ডে একমত হওয়া উচিত তবে 16 বিট ইউনিকোডটিও খুব কম এবং বড় হয়ে উঠেছে।

অবশ্যই সি এর সমস্যাগুলিও খুব বেশি থাকবে তবে এখানে উত্থাপিত সমস্যাগুলির দ্বারা খুব সামান্যই প্রভাবিত হবে।


2
@ ডেমোউভুর: কনক্যাট: O(m+n)নাল্টারম স্ট্রিং সহ, O(n)অন্য কোথাও টিপিক্যাল। O(n)নাল্টারম স্ট্রিংগুলির দৈর্ঘ্য , O(1)অন্য কোথাও। যোগদান করুন: O(n^2)নাল্টার স্ট্রিং সহ, O(n)অন্য কোথাও। কিছু ক্ষেত্রে রয়েছে নাল টার্মিনেটেড স্ট্রিংগুলি আরও দক্ষ (যেমন পয়েন্টার কেসে কেবল যুক্ত করুন), তবে কনক্যাট এবং দৈর্ঘ্য সবচেয়ে সাধারণ ক্রিয়াকলাপ (ফর্ম্যাট, ফাইল আউটপুট, কনসোল প্রদর্শন ইত্যাদির জন্য কমপক্ষে দৈর্ঘ্য প্রয়োজন) । আপনি দৈর্ঘ্যকে প্রশমিত করতে ক্যাশে করলে O(n)আপনি কেবল আমার বক্তব্যটি লিখেছেন যে দৈর্ঘ্যটি স্ট্রিংয়ের সাথে সঞ্চয় করা উচিত।
বিলি ওনিল

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

1
@ ডিভিএইচ: আমি n ^ 2 বলিনি - আমি বলেছিলাম এম + এন - এটি এখনও রৈখিক, তবে সংক্ষিপ্তকরণটি করার জন্য আপনাকে মূল স্ট্রিংয়ের শেষের দিকে যেতে হবে, যেখানে দৈর্ঘ্যের উপসর্গের সাথে কোনও খোঁজ করা উচিত নয় দরকার. (লিনিয়ার সময় প্রয়োজন দৈর্ঘ্যের এটি সত্যই অন্য পরিণতি)
বিলি ওনিল

1
@ বিলি ওনিল: নিছক কৌতূহল থেকে আমি আমার বর্তমান সি প্রকল্পে (প্রায় 50000 কোডের লাইন) স্ট্রিং ম্যানিপুলেশন ফাংশন কলগুলির জন্য গ্রেপ করেছি। স্ট্রেন 101, স্টারপিপি এবং ভেরিয়েন্টস (স্ট্রেনকিপি, স্ট্রলসিপি): 85 (আমার কাছে বার্তা, অন্তর্নিহিত কপিগুলির জন্য কয়েকশ শাব্দিক স্ট্রিং রয়েছে), স্ট্রিম্প: 56, স্ট্র্যাচ্যাট: 13 (এবং 6 টি স্ট্রিংক্যাটকে কল করার জন্য শূন্য দৈর্ঘ্যের স্ট্রিংয়ের সংক্ষিপ্তকরণগুলি) । আমি সম্মত হচ্ছি যে একটি দৈর্ঘ্যের উপসর্গযুক্ত স্পিডআপ কলগুলি স্ট্র্লেনে কল করবে, তবে স্ট্রাইকপি বা স্ট্রিম্পে নয় (সম্ভবত যদি strcmp API সাধারণ উপসর্গ ব্যবহার না করে)। উপরের মন্তব্যগুলি সম্পর্কে সর্বাধিক আকর্ষণীয় বিষয় হ'ল স্ট্রাইক্যাটটি খুব বিরল।
ক্রিসস

1
@ সুপের্যাট: বাস্তবে নয়, কিছু বাস্তবায়ন দেখুন। সংক্ষিপ্ত স্ট্রিংগুলি একটি ছোট স্ট্যাক ভিত্তিক বাফার ব্যবহার করে (কোনও হিপ বরাদ্দ নেই) বড় হয়ে ওঠার পরে কেবলমাত্র সেগুলি ব্যবহার করে। তবে গ্রন্থাগার হিসাবে আপনার ধারণার একটি বাস্তব বাস্তবায়ন নির্দ্বিধায় করুন। সাধারণত সমস্যাগুলি কেবল তখনই প্রদর্শিত হয় যখন আমরা সামগ্রিক নকশায় নয়, বিশদটি পাই।
ক্রিশগুলি

9

বিভিন্ন উপায়ে সি আদিম ছিল। এবং আমি এটা পছন্দ করি.

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

নাল টার্মিনেটর সহজ এবং ভাষার দ্বারা কোনও বিশেষ সমর্থন প্রয়োজন।

পিছনে ফিরে তাকালেও এটিকে সুবিধাজনক মনে হয় না। তবে আমি 80 এর দশকে আবার সমাবেশের ভাষা ব্যবহার করেছি এবং এটি এটিকে খুব সুবিধাজনক বলে মনে হয়েছিল। আমি কেবলমাত্র মনে করি সফ্টওয়্যার ক্রমাগত বিকশিত হয় এবং প্ল্যাটফর্ম এবং সরঞ্জামগুলি ক্রমাগত আরও বেশি পরিশীলিত হয়।


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

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

10
হয় আপনি স্ট্রিংয়ের দৈর্ঘ্য সীমাবদ্ধ করুন বা আপনি বিষয়বস্তু সীমাবদ্ধ করুন (নাল অক্ষর নেই), বা আপনি 4 থেকে 8 বাইট গণনার অতিরিক্ত ওভারহেড গ্রহণ করেন। ফ্রি লাঞ্চ নেই। প্রতিষ্ঠার সময় নাল টার্মিনেটেড স্ট্রিংটি নির্ভুল অর্থে তৈরি হয়েছিল। সমাবেশে আমি মাঝে মাঝে একটি স্ট্রিংয়ের শেষ চিহ্ন চিহ্নিত করতে একটি অক্ষরের উপরের বিটটি ব্যবহার করে আরও একটি বাইট সঞ্চয় করি!
মার্ক র্যানসম

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

8

এক মুহুর্তের জন্য ধরে নেওয়া যে সি লম্বা দ্বারা উপসর্গ করে প্যাস্কাল স্ট্রিংগুলি প্রয়োগ করেছিল: একটি 7 টি দীর্ঘ লম্বা স্ট্রিং 3-চর স্ট্রিংয়ের মতো একই ডেটা টাইপ? যদি উত্তরটি হ্যাঁ হয়, তবে আমি পূর্ববর্তীটিকে পূর্ববর্তীটিকে নির্ধারণ করার সময় সংকলকটি কী ধরণের কোড তৈরি করবে? স্ট্রিংটি কেটে ফেলা উচিত, বা স্বয়ংক্রিয়ভাবে পুনরায় আকার দেওয়া উচিত? যদি পুনরায় আকার দেওয়া হয়, তবে সেই অপারেশনটি কী থ্রেডটিকে সুরক্ষিত করার জন্য কোনও লক দ্বারা সুরক্ষিত করা উচিত? সি পদ্ধতির পক্ষ এই সমস্ত ইস্যুটি পদক্ষেপ নিয়েছে, এটি পছন্দ করুন বা না :)


2
এর .. না এটা হয়নি। সি পন্থাটি 3 চার লম্বা স্ট্রিংকে মোটেও 7 টি চর লম্বা স্ট্রিং নির্ধারণের অনুমতি দেয় না।
বিলি ওনিল

@ বিলি ওনিল: কেন নয়? যতদূর আমি এই ক্ষেত্রে এটি বুঝতে পারি, সমস্ত স্ট্রিং একই ডেটা টাইপ (চর *), সুতরাং দৈর্ঘ্য কোনও বিষয় নয়। পাস্কালের মতো নয়। দৈর্ঘ্য-উপসর্গযুক্ত স্ট্রিংগুলির সমস্যা না হয়ে এটি প্যাসকের একটি সীমাবদ্ধতা ছিল।
অলিভার ম্যাসন

4
@ বিলি: আমি মনে করি আপনি কেবল ক্রিশ্চিয়ানের বিষয়টি পুনরুদ্ধার করেছেন। সি এগুলি নিয়ে তাদের সাথে মোটেও আচরণ না করে ডিল করে। আপনি এখনও সিটির শর্তে ভাবছেন আসলে একটি স্ট্রিংয়ের ধারণা রয়েছে। এটি কেবলমাত্র একটি পয়েন্টার, যাতে আপনি যা চান এটিকে এটি নির্ধারণ করতে পারেন।
রবার্ট এস সিয়াসসিও

2
এটি ** ম্যাট্রিক্সের মতো: "কোনও স্ট্রিং নেই"।
রবার্ট এস সিয়াসসিও

1
@ ক্যালভেরা: আমি দেখতে পাচ্ছি না যে কীভাবে এটি প্রমাণিত হয়। দৈর্ঘ্যের উপসর্গ দিয়ে আপনি একইভাবে এটি সমাধান করতে পারেন ... অর্থাত্ কোনও কার্যভার অনুমতি দেবেন না।
বিলি ওনিল

8

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

#define PREFIX_STR(s) ((prefix_str_t){ sizeof(s)-1, (s) })

typedef struct { int n; char * p; } prefix_str_t;

int main() {
    prefix_str_t string1, string2;

    string1 = PREFIX_STR("Hello!");
    string2 = PREFIX_STR("Allows \0 chars (even if printf directly doesn't)");

    printf("%d %s\n", string1.n, string1.p); /* prints: "6 Hello!" */
    printf("%d %s\n", string2.n, string2.p); /* prints: "48 Allows " */

    return 0;
}

এটি অবশ্য কোনও সমস্যা নিয়ে আসবে না কারণ আপনার নির্দিষ্টভাবে সেই স্ট্রিং পয়েন্টারটি কখন মুক্ত করতে হবে এবং এটি কখন স্থিতিশীলভাবে বরাদ্দ করা হয় (আক্ষরিক charঅ্যারে) you

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

অবশ্যই মনে হয় শূন্য-সমাপ্ত স্ট্রিংগুলির সাথে কাজ করা বাঞ্ছনীয় অনুশীলন ছিল, যেহেতু সাধারণভাবে স্ট্যান্ডার্ড লাইব্রেরি স্ট্রিং দৈর্ঘ্যকে তর্কের হিসাবে গ্রহণ করে না এবং যেহেতু দৈর্ঘ্যটি উত্তোলন তত সহজ সরল কোড নয় char * s = "abc", যেমনটি আমার উদাহরণ দেখায়।


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

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

2
এমনকি যদি আপনি একটি দৈর্ঘ্য সঞ্চয় করেন তবে আপনার এম্বেডড নাল দিয়ে স্ট্রিংগুলি কখনই মঞ্জুরি দেওয়া উচিত নয়। এটি বেসিক সাধারণ জ্ঞান। যদি আপনার ডেটাতে এটিতে শূন্যতা থাকতে পারে, আপনার স্ট্রিংগুলি প্রত্যাশিত ফাংশনগুলির সাথে এটি কখনও ব্যবহার করা উচিত নয়।
আর .. গিটহাব বন্ধ করুন ICE

1
@ সুপের্যাট: সুরক্ষার দিক থেকে আমি এই অপ্রয়োজনকে স্বাগত জানাই। অন্যথায় অজ্ঞ (বা ঘুম-বঞ্চিত) প্রোগ্রামারগণ বাইনারি ডেটা এবং স্ট্রিংগুলি একত্রিত করে এবং এমন জিনিসগুলিতে প্রেরণ করে যা [নাল-সমাপ্ত] স্ট্রিংগুলি প্রত্যাশা করে ...
আর .. গিথহাব থামিয়ে সহায়তা ICE

1
@ আর ..: নাল-টার্মিনেটেড স্ট্রিংগুলি আশা করে এমন পদ্ধতিগুলি সাধারণত একটি প্রত্যাশা করে char*, এমন অনেকগুলি পদ্ধতি যা নাল সমাপ্তির আশা করে না একটিও প্রত্যাশা করে char*। প্রকারগুলি পৃথক করার আরও গুরুত্বপূর্ণ সুবিধাটি ইউনিকোড আচরণের সাথে সম্পর্কিত। স্ট্রিংগুলি নির্দিষ্ট ধরণের অক্ষর ধারণ করে, বা সেগুলি না রাখার জন্য পরিচিত কিনা তার জন্য পতাকা বজায় রাখার জন্য এটি কার্যকর হতে পারে [উদাহরণস্বরূপ, মিলিয়ন-অক্ষর স্ট্রিংয়ের 999,990 তম কোড পয়েন্ট যা খুঁজে পাওয়া যায় না তা জানা যায় বেসিক বহুভাষিক বিমানের বাইরে যে কোনও অক্ষরই
দ্রুততরতার

6

"এমনকি একটি 32 বিট মেশিনে, আপনি যদি স্ট্রিংটি উপলব্ধ মেমরির আকার হিসাবে মঞ্জুর করেন তবে দৈর্ঘ্যের উপসর্গযুক্ত স্ট্রিংটি নাল টার্মিনেটেড স্ট্রিংয়ের চেয়ে মাত্র তিন বাইট প্রশস্ত হয়" "

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

ডিল করার জন্য অ্যালাইনমেন্টের সমস্যাও থাকতে পারে। ধরুন আমার কাছে "একক \ 0 সেকেন্ড \ 0 \ 0 চারটি \ 0five \ 0 \ 0 সপ্তম" এর মতো 7 টি স্ট্রিংযুক্ত মেমরির একটি ব্লক রয়েছে। দ্বিতীয় স্ট্রিংটি অফসেট 5 এ শুরু হবে The হার্ডওয়্যারটির প্রয়োজন হতে পারে যে 32-বিট পূর্ণ সংখ্যাকে 4 টির একাধিক একটি ঠিকানায় প্রান্তিককরণ করা উচিত, সুতরাং আপনাকে প্যাডিং যুক্ত করতে হবে, ওভারহেড আরও বাড়িয়ে তুলতে হবে। সি উপস্থাপনা তুলনায় খুব স্মৃতি-দক্ষ। (স্মৃতিশক্তি-দক্ষতা ভাল; উদাহরণস্বরূপ এটি ক্যাশে পারফরম্যান্সে সহায়তা করে))


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

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

প্রান্তিককরণটি নির্দিষ্ট করে মোকাবেলা করা যেতে পারে যে UCHAR_MAX এর বাইরে মানগুলি বাইট অ্যাক্সেস এবং বিট-শিফটিং ব্যবহার করে প্যাক করা এবং আনপ্যাক করা না থাকলে এমন আচরণ করা উচিত। উপযুক্ত নকশাকৃত স্ট্রিং টাইপ স্টোরের দক্ষতা জিরো-টার্মিনেটেড স্ট্রিংগুলির সাথে তুলনামূলকভাবে সরবরাহ করতে পারে, পাশাপাশি কোনও অতিরিক্ত মেমরির ওভারহেডের জন্য বাফারগুলিতে বাউন্ডস-চেক করার অনুমতি দেয় (বাফারটি "পূর্ণ" কিনা তা উপসর্গটিতে একটি বিট ব্যবহার করুন; যদি এটি হয় না এবং সর্বশেষ বাইটটি শূন্য নয়, সেই বাইটটি অবশিষ্ট স্থানটি উপস্থাপন করবে যদি বাফারটি পূর্ণ না হয় এবং শেষ বাইটটি শূন্য হয়, তবে শেষ 256 বাইট অব্যবহৃত হবে, তাই ...
সুপারক্যাট

... শূন্যের অতিরিক্ত মেমরির ব্যয় সহ যে কেউ সেই জায়গাতে অব্যবহৃত বাইটের সঠিক সংখ্যা সঞ্চয় করতে পারে)। উপসর্গগুলির সাথে কাজ করার ব্যয়টি স্ট্রিংয়ের দৈর্ঘ্যটি না পেরে fgets () এর মতো পদ্ধতি ব্যবহারের ক্ষমতা দ্বারা অফসেট হবে (যেহেতু বাফাররা জানতে পারে যে তারা কত বড় ছিল)।
সুপারক্যাট

4

নাল সমাপ্তি দ্রুত পয়েন্টার ভিত্তিক ক্রিয়াকলাপের অনুমতি দেয়।


5
তাই না? দৈর্ঘ্যের উপসর্গের সাথে কোন "দ্রুত পয়েন্টার অপারেশনগুলি" কাজ করে না? আরও গুরুত্বপূর্ণ, অন্যান্য ভাষাগুলি যে দৈর্ঘ্যের উপসর্গ ব্যবহার করে সেগুলি সি আর্ট স্ট্রিং ম্যানিপুলেশনের চেয়ে দ্রুত are
বিলি ওনিল

12
@ বিলি: দৈর্ঘ্য পূর্বনির্ধারিত স্ট্রিংগুলির সাহায্যে আপনি কেবল একটি স্ট্রিং পয়েন্টার নিতে এবং এর সাথে 4 টি যোগ করতে পারবেন না এবং এটি এখনও একটি বৈধ স্ট্রিং হিসাবে প্রত্যাশা করতে পারেন, কারণ এটির দৈর্ঘ্যের উপসর্গ নেই (যাইহোক বৈধ নয়)।
জর্জেন সিগওয়ার্ডসন

3
@ জেআর্যান্ডম_হ্যাকার: সম্ভাব্য ও (এন) এর পরিবর্তে অ্যাস্কিস্ট স্ট্রিং (ও (এম + এন) এর জন্য সংঘটন অনেক খারাপ, এবং এখানে তালিকাভুক্ত অন্যান্য ক্রিয়াকলাপগুলির তুলনায় কনক্যাট অনেক বেশি সাধারণ।
বিলি ওনিল

3
এক tiiny সামান্য অপারেশন যে নাল-সমাপ্ত স্ট্রিং সঙ্গে আরো ব্যয়বহুল হয়ে আছে: strlen। আমি বলব যে এটি কিছুটা ব্যর্থতা।
জাল্ফ

10
@ বিলি ওনিল: প্রত্যেকে প্রত্যেকেই রেজেক্সকে সমর্থন করে। তাতে কি ? তাদের জন্য তৈরি লাইব্রেরি ব্যবহার করুন Use সি সর্বোচ্চ দক্ষতা এবং ন্যূনতমতা সম্পর্কে, ব্যাটারি অন্তর্ভুক্ত নয়। সি সরঞ্জামগুলি আপনাকে স্ট্রোকগুলি খুব সহজেই ব্যবহার করে দৈর্ঘ্যের প্রিফিক্সড স্ট্রিং প্রয়োগ করতে দেয়। এবং কোনও কিছুই আপনাকে নিজের দৈর্ঘ্য এবং চর বাফার পরিচালনার মাধ্যমে স্ট্রিং ম্যানিপুলেশন প্রোগ্রামগুলি প্রয়োগ করতে বাধা দেয় না। যখন আমি দক্ষতা চাই এবং সি ব্যবহার করি তখন সাধারণত আমি যা করি, চার্ফ বাফার শেষে শূন্য আশা করে এমন কয়েকটি মুখ্য ফাংশন কল না করা কোনও সমস্যা নয়।
ক্রিস

4

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

যদি কেউ নির্বিচারে দৈর্ঘ্যের স্ট্রিংগুলি দক্ষতার সাথে সংরক্ষণ করার অনুমতি দিতে চেয়েছিল এবং 'চর' সর্বদা 8-বিট থাকে তবে কেউ - গতি এবং কোড আকারে কিছু ব্যয় করার জন্য - কোনও স্কিম সংখ্যার দ্বারা উপস্থাপিত একটি স্ট্রিং ছিল এনটি N / 2 বাইট দীর্ঘ হবে, একটি স্ট্রিংটির সাথে একটি বিজোড় মান N এবং একটি সমান মান এম (পিছনে পড়া) হতে পারে ((এন -1) + এম * চর_ম্যাক্স) / 2, ইত্যাদি হতে পারে এবং এটির কোনও বাফার প্রয়োজন স্ট্রিং ধরে রাখতে নির্দিষ্ট পরিমাণ জায়গার অফার করার দাবিতে অবশ্যই সেই স্থানের পূর্বের পর্যাপ্ত বাইটগুলি সর্বাধিক দৈর্ঘ্য পরিচালনা করতে হবে। 'চর' সর্বদা 8 বিট নয় তবে এই জাতীয় পরিকল্পনা জটিল হবে কারণ স্ট্রিংয়ের দৈর্ঘ্য ধরে রাখার জন্য প্রয়োজনীয় 'চর' সংখ্যা সিপিইউ আর্কিটেকচারের উপর নির্ভর করে পরিবর্তিত হতে পারে।


উপসর্গটি সহজেই বাস্তবায়ন-সংজ্ঞায়িত আকারের হতে পারে sizeof(char)
বিলি ওনেল

@ বিলিওনিল: sizeof(char)একটি। সর্বদা. উপসর্গটি একটি প্রয়োগ-সংজ্ঞায়িত আকার হতে পারে তবে এটি বিশ্রী হবে। আরও, "সঠিক" আকারটি কী হবে তা জানার কোনও আসল উপায় নেই। যদি একটিতে প্রচুর 4-বর্ণের স্ট্রিং থাকে তবে শূন্য-প্যাডিং 25% ওভারহেড চাপিয়ে দেয়, যখন একটি চার-বাইট দৈর্ঘ্যের উপসর্গ 100% ওভারহেড চাপিয়ে দেয়। তদ্ব্যতীত, চার-বাইট দৈর্ঘ্যের উপসর্গ প্যাকিং এবং আনপ্যাক করতে ব্যয় করা সময় শূন্য বাইটের জন্য 4-বাইট স্ট্রিংগুলির স্ক্যানিংয়ের ব্যয় ছাড়িয়ে যেতে পারে।
সুপারক্যাট

1
অই হ্যাঁ. তুমি ঠিক বলছো. উপসর্গটি সহজেই চর ছাড়া অন্য কিছু হতে পারে। লক্ষ্য প্ল্যাটফর্মের কাজগুলিতে প্রান্তিককরণের প্রয়োজনীয়তা তৈরি করতে পারে এমন কিছু ঠিক আছে। যদিও আমি সেখানে যাব না - আমি ইতিমধ্যে এটি মৃত্যুর পক্ষে যুক্তি দিয়েছি।
বিলি ওনিল

ধরুন স্ট্রিংগুলি দৈর্ঘ্য-উপসর্গযুক্ত ছিল, সম্ভবত সানেষ্ট জিনিসটি একটি size_tউপসর্গ হবে (মেমরির বর্জ্যটি ধিক্কার জানানো হবে , এটি স্যানেষ্ট হবে --- সম্ভবত কোনও স্মৃতিতে মাপসই হতে পারে এমন কোনও সম্ভাব্য দৈর্ঘ্যের স্ট্রিংকে অনুমতি দেয়)। প্রকৃতপক্ষে, এটি ডি কি ধরনের হয়; অ্যারেগুলি হয় struct { size_t length; T* ptr; }, এবং স্ট্রিংগুলি কেবল অ্যারে হয় immutable(char)
টিম Čএফ

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

2

সি স্টেমকে ঘিরে অনেকগুলি নকশার সিদ্ধান্তগুলি মূলত: এটি যখন বাস্তবায়িত হয়েছিল তখন প্যারামিটার পাসিং কিছুটা ব্যয়বহুল ছিল। উদাহরণস্বরূপ মধ্যে একটি পছন্দ দেওয়া

void add_element_to_next(arr, offset)
  char[] arr;
  int offset;
{
  arr[offset] += arr[offset+1];
}

char array[40];

void test()
{
  for (i=0; i<39; i++)
    add_element_to_next(array, i);
}

বনাম

void add_element_to_next(ptr)
  char *p;
{
  p[0]+=p[1];
}

char array[40];

void test()
{
  int i;
  for (i=0; i<39; i++)
    add_element_to_next(arr+i);
}

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

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

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

void strcat(unsigned char *dest, unsigned char *src)
{
  struct STRING_INFO d,s;
  str_size_t copy_length;

  get_string_info(&d, dest);
  get_string_info(&s, src);
  if (d.si_buff_size > d.si_length) // Destination is resizable buffer
  {
    copy_length = d.si_buff_size - d.si_length;
    if (s.src_length < copy_length)
      copy_length = s.src_length;
    memcpy(d.buff + d.si_length, s.buff, copy_length);
    d.si_length += copy_length;
    update_string_length(&d);
  }
}

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

/* Concatenate 10th through 24th characters from src to dest */

void catpart(unsigned char *dest, unsigned char *src)
{
  struct SUBSTRING_INFO *inf;
  src = temp_substring(&inf, src, 10, 24);
  strcat(dest, src);
}

নোট করুন যে টেম্পসুস্ট্রিং দ্বারা ফিরে আসা স্ট্রিংয়ের আজীবন সীমাবদ্ধ থাকবে sএবং srcযেগুলি কখনও কম ছিল (এই কারণেই পদ্ধতিটি infপাস করার প্রয়োজন হয় - যদি এটি স্থানীয় হয় তবে পদ্ধতিটি ফিরে আসার পরে এটি মারা যেত)।

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

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


এমন কোনও কিছুই নেই যা char* arrফর্ম struct { int length; char characters[ANYSIZE_ARRAY] };বা অনুরূপ কোনও কাঠামোর দিকে ইশারা করা থেকে বিরত থাকতে পারে যা এখনও একক পরামিতি হিসাবে পাসযোগ্য হবে।
বিলি ওনিল

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

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

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

1
'আমি মনে করি না "চর বাফারটি দৈর্ঘ্য সমেত একটি ইনট দিয়ে শুরু হয়" আরও যাদু ical - এটি হ'ল যদি আপনি str[n]সঠিক চরটি পড়তে চলেছেন । এগুলি বিভিন্ন ধরণের জিনিস যা নিয়ে আলোচনা করা লোকেরা সেগুলি ভাববে না।
জিম বাল্টার

2

এই ব্লগ পোস্টে জোয়েল স্পলস্কির মতে ,

এটি কারণ পিডিপি -7 মাইক্রোপ্রসেসর, যার উপর ইউএনআইএক্স এবং সি প্রোগ্রামিং ভাষা উদ্ভাবিত হয়েছিল, তার একটি এসকিজেড স্ট্রিং টাইপ ছিল। এএসসিআইজেড বলতে বোঝায় "শেষে জেড (শূন্য) সহ এএসসিআইআই।"

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


2
দেখুন, আমি জোলকে অনেক কিছুর জন্য সম্মান করি; তবে এটি এমন কিছু যেখানে তিনি অনুমান করছেন। হান্স প্যাস্যান্টের উত্তর সরাসরি সি এর উদ্ভাবকদের কাছ থেকে আসে।
বিলি ওনিল

1
হ্যাঁ, তবে স্পলস্কি যা বলছেন তা যদি সত্যিই সত্য হয় তবে তারা যে "সুবিধার্থে" তারা উল্লেখ করছিল এটির একটি অংশ হত। আমি এই উত্তর অন্তর্ভুক্ত কেন আংশিক।
বেঙ্ক

.ASCIZবাইটের ক্রম তৈরির জন্য আফাইক কেবল একটি সমাবেশকারী বিবৃতি ছিল, তারপরে অনুসরণ করবে 0। এর অর্থ হ'ল শূন্য সমাপ্ত স্ট্রিংটি তখনকার সময়ে একটি সুপ্রতিষ্ঠিত ধারণা ছিল। এর অর্থ এই নয় যে শূন্যের সমাপ্তিযুক্ত স্ট্রিংগুলি পিডিপি-* এর স্থাপত্যের সাথে সম্পর্কিত কিছু ছিল, আপনি ব্যতিত একটি লাইট MOVB(বাইট অনুলিপি) এবং BNE(শেষ বাইটটি অনুলিপিটি শূন্য না হলে শাখা ) লিখতে পারতেন except
অ্যাড্রিয়ান ডাব্লু

এটি ধরে নেওয়া যায় যে সি পুরানো, স্বাচ্ছন্দ্যময়, ক্ষীণ ভাষা।
শুদ্ধ

2

অগত্যা কোনও যুক্তি নয় , দৈর্ঘ্য-এনকোড করাতে একটি পাল্টা পয়েন্ট

  1. গতিশীল দৈর্ঘ্যের এনকোডিংয়ের কয়েকটি ফর্ম স্থির দৈর্ঘ্যের এনকোডিংয়ের চেয়ে মেমরির দিক থেকে সর্বোত্তম, এটি সমস্ত ব্যবহারের উপর নির্ভর করে। প্রমাণের জন্য কেবল ইউটিএফ -8 দেখুন। এটি একক অক্ষরকে এনকোড করার জন্য মূলত একটি এক্সটেনসিবল অক্ষর অ্যারে। এটি প্রতিটি বর্ধিত বাইটের জন্য একক বিট ব্যবহার করে। NUL সমাপ্তি 8 টি বিট ব্যবহার করে। দৈর্ঘ্য-উপসর্গটি আমি মনে করি 64৪ বিট ব্যবহার করে যুক্তিসঙ্গতভাবে অসীম দৈর্ঘ্য হিসাবে অভিহিত হতে পারে। আপনার অতিরিক্ত বিটের ক্ষেত্রে আপনি কত ঘন ঘন আঘাত করেন তা হ'ল সিদ্ধান্ত গ্রহণকারী। শুধুমাত্র 1 টি অত্যন্ত বড় স্ট্রিং? আপনি 8 বা 64 বিট ব্যবহার করছেন তবে কে যত্ন করে? অনেক ছোট স্ট্রিং (ইংরেজি শব্দের স্ট্রিংস)? তারপরে আপনার উপসর্গের ব্যয়গুলি একটি বড় শতাংশ।

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

  3. দৈর্ঘ্য-উপসর্গ optionচ্ছিক একটি বিক্রয় পয়েন্ট। অ্যালগরিদমের জন্য আমার সর্বদা সেই অতিরিক্ত তথ্যের প্রয়োজন হয় না তাই প্রতিটি স্ট্রিংয়ের জন্য এটি করার প্রয়োজন হয় আমার পূর্ববর্তী + গণনার সময়কে কখনই ও (এন) এর নিচে নামতে সক্ষম করে না। (অর্থাৎ হার্ডওয়্যার এলোমেলো সংখ্যার জেনারেটর 1-128। আমি একটি "অসীম স্ট্রিং" থেকে টানতে পারি। আসুন আমরা বলি এটি কেবল অক্ষরগুলি এত তাড়াতাড়ি জেনারেট করে So সুতরাং আমাদের স্ট্রিংয়ের দৈর্ঘ্য সর্বদা পরিবর্তিত হয় But তবে আমার ডেটা ব্যবহার সম্ভবত কীভাবে যত্নশীল হয় না) আমার কাছে অনেক এলোমেলো বাইট রয়েছে a এটি অনুরোধের পরে এটি পাওয়া মাত্র পরের উপলভ্য অব্যবহৃত বাইটটি চায় wants আমি ডিভাইসে অপেক্ষা করতে পারি But অকারণে গণনার অপচয়। একটি নাল চেক আরও দক্ষ more

  4. দৈর্ঘ্য-উপসর্গ বাফার ওভারফ্লো বিরুদ্ধে ভাল গার্ড? লাইব্রেরি ফাংশন এবং বাস্তবায়ন বুদ্ধিমান ব্যবহার। যদি আমি ত্রুটিযুক্ত ডেটা পাস করি? আমার বাফারটি দীর্ঘ 2 বাইট দীর্ঘ তবে আমি ফাংশনটি এটি 7 বলছি! উদাহরণস্বরূপ: যদি () এর তথ্য জানা তথ্যের উপরে ব্যবহারের উদ্দেশ্যে করা হত তবে এটির অভ্যন্তরীণ বাফার চেক থাকতে পারে যা পরীক্ষিত সংকলিত বাফার এবং ম্যালোক () পরীক্ষা করেছিলকল এবং এখনও অনুমান অনুসরণ করুন। যদি অজানা STFIN এর অজানা বাফারে পৌঁছানোর জন্য এটি একটি পাইপ হিসাবে ব্যবহার করার উদ্দেশ্যে বোঝানো হত তবে স্পষ্টভাবে কেউ বাফারের আকার জানতে পারবেন না যার অর্থ দৈর্ঘ্য আর্গটি অর্থহীন, আপনার এখানে ক্যানারি চেকের মতো আরও কিছু দরকার। এই বিষয়ে, আপনি কিছু স্ট্রিম এবং ইনপুটগুলি দৈর্ঘ্য-উপসর্গ করতে পারবেন না, আপনি পারবেন না। যার অর্থ দৈর্ঘ্যের চেকটি অ্যালগরিদমে তৈরি করতে হবে এবং টাইপিং সিস্টেমের যাদু অংশ নয়। টিএল; ডিআর নুল-টার্মিনেটেড কখনই অনিরাপদ হতে হবে না, এটি অপব্যবহারের মধ্য দিয়ে শেষ হয়েছে।

  5. পাল্টা পাল্টা পয়েন্ট: NUL- সমাপ্তি বাইনারি উপর বিরক্তিকর। আপনার হয় এখানে দৈর্ঘ্য-উপসর্গ করতে হবে বা কোনওভাবে NUL বাইট রুপান্তর করা দরকার: এস্কেপ-কোডস, রেঞ্জ রিম্যাপিং ইত্যাদি ... যার অবশ্যই অর্থ বেশি-মেমরি-ব্যবহার / হ্রাস-তথ্য / আরও-অপারেশন-প্রতি-বাইট। দৈর্ঘ্য-উপসর্গ বেশিরভাগ এখানে যুদ্ধে জয়লাভ করে। রূপান্তরটির একমাত্র বিপরীতটি হ'ল দৈর্ঘ্য-উপসর্গের স্ট্রিংগুলি coverাকতে কোনও অতিরিক্ত ফাংশন লিখতে হয় না। যার অর্থ আপনার আরও অনুকূলিত সাব-ও (এন) রুটিনগুলিতে আপনি এগুলিকে আরও কোড যুক্ত না করে স্বয়ংক্রিয়ভাবে তাদের ও (এন) সমতুল্য হিসাবে কাজ করতে পারেন। ডাউনসাইড অবশ্যই সময় / মেমরি / সংক্ষেপণ বর্জ্য যখন এন ইউ এল ভারী স্ট্রিংগুলিতে ব্যবহৃত হয়।আপনার লাইব্রেরির কত অংশ আপনি বাইনারি ডেটাতে অপারেট করার জন্য ডুপ্লিকেটিং শেষ করেন তার উপর নির্ভর করে এটি কেবল দৈর্ঘ্য-উপসর্গের স্ট্রিং দিয়ে কাজ করার জন্য বোধ করতে পারে। এটি বলেছে যে দৈর্ঘ্য-উপসর্গের স্ট্রিংয়ের মাধ্যমেও কেউ একই কাজ করতে পারে ... -1 দৈর্ঘ্যের অর্থ NUL- সমাপ্ত হতে পারে এবং আপনি দৈর্ঘ্য-সমাপ্তির অভ্যন্তরে NUL- টার্মিনেটেড স্ট্রিং ব্যবহার করতে পারেন।

  6. কনক্যাট: "ও (এন + এম) বনাম ও (এম)" আমি মিটাকে আপনার রেফারিংকে স্ট্রিংয়ের মোট দৈর্ঘ্য হিসাবে ধরে নিয়েছি তা কনকানটেটিং করার পরে কারণ তাদের উভয়কেই অপারেশন সংখ্যাটি ন্যূনতম করতে হবে (আপনি কেবল সামলাতে পারবেন না) -আপনার স্ট্রিং 1-এ, যদি আপনাকে পুনর্বিবেচনা করতে হয় তবে কী হবে?)। এবং আমি ধরে নিচ্ছি এন হ'ল একটি পৌরাণিক পরিমাণ অপারেশন যা আপনাকে আর প্রাক-গণনা করার কারণে করতে হবে না। যদি তাই হয় তবে উত্তরটি সহজ: প্রাক-গণনা। যদিআপনি জোর দিয়ে বলছেন যে আপনার কাছে সবসময় পর্যাপ্ত মেমরি থাকবে যাতে পুনর্বিবেচনার প্রয়োজন হয় না এবং এটিই বিগ-ও সংকেতের ভিত্তি হয় তবে উত্তরটি আরও সহজ: স্ট্রিং 1 এর শেষের জন্য বরাদ্দ মেমরির উপর বাইনারি অনুসন্ধান করুন, স্পষ্টতই এখানে একটি বিশাল স্ট্রোল 1 পরে অসীম শূন্যগুলির স্য্যাচ আমাদের রিলোক সম্পর্কে চিন্তা না করার জন্য। সেখানে, সহজেই লগ ইন করতে পেলাম (এন) এবং আমি সবেমাত্র চেষ্টা করেছি। যা যদি আপনি স্মরণ করেন লগ (এন) মূলত কেবলমাত্র সত্যিকারের কম্পিউটারে as৪ এর মতো বড় হয়, যা মূলত ও (+৪ + মি) বলার মতো, যা মূলত ও (এম) হয়। (এবং হ্যাঁ যে যুক্তিটি আজ-অবধি ব্যবহারযোগ্য বাস্তব ডেটা স্ট্রাকচারের রান-টাইম বিশ্লেষণে ব্যবহৃত হয়েছে It's এটি আমার মাথার উপরের অংশটি বন্ধ করে দেবে না))

  7. কনক্যাট () / লেন () আবার : ফলাফলগুলিকে স্মরণ করিয়ে দিন। সহজ। সম্ভব / প্রয়োজনীয় হলে সমস্ত গণনাগুলি প্রাক-গণিতে রূপান্তরিত করে। এটি একটি অ্যালগরিদমিক সিদ্ধান্ত। এটি ভাষার প্রয়োগের প্রতিবন্ধকতা নয়।

  8. স্ট্রিং প্রত্যয় পাস করা NUL সমাপ্তির সাথে সহজ / সম্ভব। দৈর্ঘ্য-উপসর্গটি কীভাবে প্রয়োগ করা হয় তার উপর নির্ভর করে এটি মূল স্ট্রিংয়ের উপর ধ্বংসাত্মক হতে পারে এবং কখনও কখনও এটি সম্ভবও হয় না। ও (1) এর পরিবর্তে অনুলিপি এবং ও (এন) পাস করার প্রয়োজন।

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

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

টিএল; ডিআর আপনি কি বাইনারি ডেটা ব্যবহার করছেন? যদি না হয়, তবে NUL- সমাপ্তি আরও অ্যালগরিদমিক স্বাধীনতার অনুমতি দেয়। যদি হ্যাঁ, তবে কোড পরিমাণ বনাম গতি / মেমরি / সংক্ষেপণ আপনার প্রধান উদ্বেগ। দুটি পদ্ধতির বা স্মৃতিচারণের মিশ্রণ সেরা হতে পারে।


9 কিন্ডা অফ বেস / ভুল প্রতিনিধিত্বমূলক ছিল। দৈর্ঘ্যের প্রি-ফিক্সে এই সমস্যা নেই। পৃথক ভেরিয়েবল হিসাবে দৈর্ঘ্য পাস হচ্ছে। আমরা প্রি-ফিক্স সম্পর্কে কথা বলছিলাম তবে আমি দূরে সরে গেলাম। এখনও চিন্তা করার জন্য একটি ভাল জিনিস তাই আমি এটি সেখানে রেখে দেব। : d
কালো

1

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

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

সুতরাং দেখে মনে হচ্ছে নাল-সমাপ্তি ব্যবহারের সিদ্ধান্তটি কেবল লোকেরা পছন্দ করে, ভাষার প্রয়োজনীয়তা নয়।


-3

জিসিসি নীচের কোডগুলি গ্রহণ করুন:

চর s [4] = "abcd";

এবং এটি ঠিক আছে যদি আমরা চরের অ্যারে হিসাবে স্ট্রিং না হয়ে চিকিত্সা করি। এটি হ'ল, আমরা এটিকে এস [0], এস [1], এস [2], এবং এস [3], বা এমনকি মেমকিপি (ডেস্ট, এস, 4) দিয়ে অ্যাক্সেস করতে পারি। তবে যখন আমরা পুটস (গুলি) দিয়ে চেষ্টা করি বা স্ট্রিপিপি (ডেস্ট, গুলি) এর সাথে আরও খারাপ করব তখন আমরা অগোছালো চরিত্রগুলি পেয়ে যাব।


@ অ্যাড্রিয়ান ডাব্লু। এটি বৈধ সি। সঠিক দৈর্ঘ্যের স্ট্রিংগুলি বিশেষ কেসযুক্ত এবং তাদের জন্য NUL বাদ দেওয়া হয়। এটি সাধারণত একটি বোকামি অনুশীলন তবে পপুলেটিং শিরোনামের স্ট্র্টগুলি যেমন ফোরসিসি "স্ট্রিং" ব্যবহার করে এমন ক্ষেত্রে কার্যকর হতে পারে।
কেভিন থিবেডো

তুমি ঠিক. এটি বৈধ সি, সংকলন করবে এবং বর্ণিত kkaaii হিসাবে আচরণ করবে। ডাউনভোটদের (আমার নয় ...) কারণ সম্ভবত এই উত্তরটি কোনওভাবেই ওপির প্রশ্নের উত্তর দেয় না।
অ্যাড্রিয়ান ডাব্লু
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.