অক্ষর অ্যারেগুলি স্ট্রিং হিসাবে কীভাবে ব্যবহার করা উচিত?


10

আমি বুঝতে পারি যে সি তে স্ট্রিংগুলি কেবল চরিত্রের অ্যারে। সুতরাং আমি নিম্নলিখিত কোডটি চেষ্টা করেছিলাম, তবে এটি অদ্ভুত ফলাফল দেয় যেমন জঞ্জাল আউটপুট বা প্রোগ্রাম ক্র্যাশগুলি:

#include <stdio.h>

int main (void)
{
  char str [5] = "hello";
  puts(str);
}

কেন এই কাজ করে না?

এটি পরিষ্কারভাবে সংকলন করে gcc -std=c17 -pedantic-errors -Wall -Wextra


দ্রষ্টব্য: এই পোস্টটি কোনও স্ট্রিং ঘোষণার সময় কোনও NUL টার্মিনেটরের জন্য ঘর বরাদ্দ করতে ব্যর্থতা থেকে উদ্ভূত সমস্যার জন্য ক্যানোনিকাল এফএকিউ হিসাবে ব্যবহৃত হতে বোঝানো হয়েছিল।

উত্তর:


12

এসি স্ট্রিং একটি অক্ষর অ্যারে যা নাল টার্মিনেটর দিয়ে শেষ হয় ।

সমস্ত অক্ষরের একটি সারণী মান আছে। নাল টার্মিনেটর হল প্রতীক মান 0(শূন্য)। এটি একটি স্ট্রিংয়ের শেষ চিহ্নিত করতে ব্যবহৃত হয়। স্ট্রিংয়ের আকার কোথাও সংরক্ষণ করা হয়নি বলে এটি প্রয়োজনীয়।

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

char str[6] = "hello";

বা সমতুল্যভাবে, আপনি 5 টি অক্ষরের সাথে 1 টি নাল টার্মিনেটরের জন্য স্ব-ডকুমেন্টিং কোড লিখতে পারেন:

char str[5+1] = "hello";

রান-টাইমে স্ট্রিংয়ের জন্য গতিশীলভাবে মেমরি বরাদ্দ করার সময়, আপনাকে নাল টার্মিনেটরের জন্যও জায়গা বরাদ্দ করতে হবে:

char input[n] = ... ;
...
char* str = malloc(strlen(input) + 1);

আপনি যদি কোনও স্ট্রিংয়ের শেষে নাল টার্মিনেটর সংযোজন করেন না, তবে স্ট্রিংয়ের প্রত্যাশিত লাইব্রেরি ফাংশনগুলি সঠিকভাবে কাজ করবে না এবং আপনি "অপরিজ্ঞাত আচরণ" বাগ যেমন জঞ্জাল আউটপুট বা প্রোগ্রাম ক্র্যাশ পাবেন।

সবচেয়ে সাধারণ উপায় সি নাল টারমিনেটর চরিত্র লিখতে একটি তথাকথিত "অকট্যাল পালাবার ক্রম" ব্যবহার, ভালো তাকিয়ে হল: '\0'। এটি লেখার 100% সমতুল্য 0, তবে \শূন্যটি স্পষ্টভাবে নাল টার্মিনেটর হিসাবে বোঝানো হয়েছে তা জানাতে স্ব-ডকুমেন্টিং কোড হিসাবে কাজ করে। কোডগুলি যেমন if(str[i] == '\0')নির্দিষ্ট অক্ষরটি নাল টার্মিনেটর কিনা তা পরীক্ষা করবে।

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

"hello"আপনার কোডে একটি বলা হয় স্ট্রিং আক্ষরিক । এটি কেবল পঠনযোগ্য স্ট্রিং হিসাবে বিবেচিত হবে। ""সিনট্যাক্স মানে যে কম্পাইলার আক্ষরিক স্বয়ংক্রিয়ভাবে স্ট্রিংয়ের শেষ প্রান্ত একটি নাল টারমিনেটর যোগ হবে। সুতরাং আপনি প্রিন্ট করলে আপনি sizeof("hello")5 পাবেন না, কারণ আপনি নাল টার্মিনেটর সহ অ্যারের আকার পাবেন।


এটি জিসিসি দিয়ে পরিষ্কারভাবে সংকলন করে

প্রকৃতপক্ষে, একটি সতর্কতাও নয়। এটি সি ভাষার এমন একটি সূক্ষ্ম বিশদ / ত্রুটির কারণে যা অক্ষরের অ্যারেগুলিকে একটি স্ট্রিং আক্ষরিক দিয়ে আরম্ভ করতে দেয় যা অ্যারেতে জায়গা রয়েছে ঠিক তেমন অক্ষর ধারণ করে এবং নীরবে নাল টার্মিনেটর বাতিল করে দেয় (C17 6.7.9 / 15)। ভাষাটি ইচ্ছাকৃতভাবে historical তিহাসিক কারণে এই জাতীয় আচরণ করছে, বিশদগুলির জন্য স্ট্রিং ইনিশিয়ালাইজেশনের জন্য বেমানান জিসিসি ডায়াগোনস্টিক দেখুন। এছাড়াও নোট করুন যে সি ++ এখানে আলাদা এবং এই কৌশল / ত্রুটি ব্যবহার করার অনুমতি দেয় না।


1
আপনার কেসটি উল্লেখ করা উচিত char str[] = "hello";
জ্যাবারওয়কি

@ জ্যাবারওয়ার্কি এটি একটি সম্প্রদায় উইকি, সম্পাদনা ও অবদান রাখতে নির্দ্বিধায়
লুন্ডিন

1
... এবং সম্ভবত char *str = "hello";... str[0] = foo;সমস্যা।
জ্যাবারওয়কি

সম্ভবত sizeofকোনও ফাংশন প্যারামিটারে এটির ব্যবহারের প্রবণতাটি প্রসারিত করুন , বিশেষত যখন অ্যারে হিসাবে সংজ্ঞায়িত করা হয়।
আবহাওয়া ভেন

: @WeatherVane এখানে আরেকটি প্রায়শই জিজ্ঞাসিত প্রশ্নাবলী দ্বারা আচ্ছাদিত করা উচিত stackoverflow.com/questions/492384/...
Lundin

4

সি স্ট্যান্ডার্ড থেকে (7.1.1 শর্তাবলী সংজ্ঞা)

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

এই ঘোষণাপত্রে

char str [5] = "hello";

স্ট্রিং আক্ষরিক "hello"মত অভ্যন্তরীণ উপস্থাপনা আছে

{ 'h', 'e', 'l', 'l', 'o', '\0' }

সুতরাং এটির সমাপ্ত শূন্য সহ 6 টি অক্ষর রয়েছে। এর উপাদানগুলি অক্ষর অ্যারে শুরু করতে ব্যবহৃত হয় strযা কেবল 5 টি অক্ষরের জন্য স্থান সংরক্ষণ করে।

সি স্ট্যান্ডার্ড (সি ++ স্ট্যান্ডার্ডের বিপরীতে) একটি স্ট্রিং আক্ষরিকের সমাপ্তি শূন্যটি আরম্ভকারী হিসাবে ব্যবহার না করা হলে একটি অক্ষর অ্যারের যেমন একটি আরম্ভের অনুমতি দেয়।

তবে ফলস্বরূপ অক্ষর অ্যারেতে strএকটি স্ট্রিং থাকে না।

আপনি যদি চান যে অ্যারেটিতে একটি স্ট্রিং থাকে যা আপনি লিখতে পারেন

char str [6] = "hello";

বা শুধু

char str [] = "hello";

শেষের ক্ষেত্রে অক্ষরের অ্যারের আকারটি স্ট্রিং লিটারেলের প্রারম্ভকারীর সংখ্যা থেকে নির্ধারিত হয় যা 6 এর সমান।


0

সব পারি স্ট্রিং একটি বিবেচনা করা অক্ষরের অ্যারে ( হ্যাঁ ), সব করতে চরিত্র অ্যারে বিবেচনা করা স্ট্রিং ( কোন )।

কেন না? এবং কেন এটি গুরুত্বপূর্ণ?

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

যখন কোনও অক্ষর অ্যারে একই অক্ষর ধারণ করতে পারে তবে এটি কেবল অক্ষরের একটি অ্যারে না হয় যদি না শেষ অক্ষরটি নুল-টার্মিনেটিং অক্ষর অনুসরণ না করে । সেই নুল-টার্মিনেটিং চরিত্রটি হ'ল অক্ষরের অ্যারেটিকে স্ট্রিং হিসাবে বিবেচনা করতে (যেমন পরিচালনা করা) অনুমতি দেয়।

সি এর সমস্ত ফাংশন যা আর্গুমেন্ট হিসাবে একটি স্ট্রিং প্রত্যাশা করে অক্ষরের অনুক্রমটি বাতিল-সমাপ্ত হওয়ার প্রত্যাশা করে । কেন?

এটি সমস্ত স্ট্রিং ফাংশনগুলি যেভাবে কাজ করে তা করতে হবে। যেহেতু দৈর্ঘ্য একটি অ্যারের অংশ হিসাবে অন্তর্ভুক্ত করা হয়নি, স্ট্রিং-ফাংশন, নাল-চরিত্রের (যেমন '\0'- দশমিকের সমতুল্য 0) সন্ধান না পাওয়া পর্যন্ত অ্যারেতে স্ক্যান করুন । দেখুন হওয়া ASCII টেবিল এবং বর্ণনা । তথাপি কিনা আপনি ব্যবহার করছেন strcpy, strchr, strcspn, ইত্যাদি .. সকল স্ট্রিং ফাংশন উপর নির্ভর nul-সসীম চরিত্র উপস্থিত হচ্ছে নির্ধারণ করতে যেখানে যে পংক্তি শেষ হয়।

দুটি অনুরূপ ক্রিয়াকলাপের তুলনা নুল-সমাপ্তি চরিত্রের string.hগুরুত্বকে জোর দেবে । উদাহরণস্বরূপ নিন:

    char *strcpy(char *dest, const char *src);

strcpyফাংশন কেবল কপি থেকে বাইট srcথেকে destপর্যন্ত nul-সসীম চরিত্র পাওয়া যায় বলার strcpyযেখানে অক্ষর অনুলিপি থামাতে। এখন অনুরূপ ফাংশন নিন memcpy:

    void *memcpy(void *dest, const void *src, size_t n);

ফাংশনটি একই ক্রিয়াকলাপ সম্পাদন করে তবে srcপ্যারামিটারটিকে স্ট্রিং হিসাবে বিবেচনা করে না বা প্রয়োজন হয় না । যেহেতু নুল-টার্মিনেটিং চরিত্রটি না পাওয়া পর্যন্ত memcpyকেবল srcঅনুলিপি করে বাইটগুলি অনুলিপি করতে পারে destনা , তৃতীয় প্যারামিটার হিসাবে অনুলিপি করার জন্য এটি স্পষ্ট সংখ্যক বাইটের প্রয়োজন। এই তৃতীয় প্যারামিটার একই আকারের তথ্য সরবরাহ করে কেবল কোনও নুল-টার্মিনেটিং চরিত্র না পাওয়া পর্যন্ত সামনে স্ক্যান করে সহজেই উত্পন্ন করতে সক্ষম হয় ।memcpystrcpy

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

যে কেন একটি আশা ফাংশন nul-সমাপ্ত স্ট্রিং একটি প্রেরণ করা আবশ্যক nul-সমাপ্ত STRING এবং কেন এটা গুরুত্বপূর্ণ


0

Intuitively ...

ভেরিয়েবল হিসাবে একটি অ্যারের (জিনিসগুলি ধারণ করে) এবং একটি স্ট্রিংকে একটি ভেরিয়েবলের (ভেরিয়েবলের মধ্যে স্থাপন করা যেতে পারে) ভাবেন।

তারা অবশ্যই একই জিনিস নয়। আপনার ক্ষেত্রে চলকটি স্ট্রিং ধরে রাখতে খুব ছোট, সুতরাং স্ট্রিংটি কেটে যায়। (সি এর "উদ্ধৃতিযুক্ত স্ট্রিং" এর শেষে একটি নিখুঁত নাল অক্ষর রয়েছে))

তবে স্ট্রিংয়ের চেয়ে অনেক বড় অ্যারেতে একটি স্ট্রিং সঞ্চয় করা সম্ভব ।

নোট করুন যে সাধারণ অ্যাসাইনমেন্ট এবং তুলনা অপারেটর ( = == <ইত্যাদি) আপনার প্রত্যাশার মতো কাজ করে না। তবে strxyzফাংশনগুলির পরিবারটি খুব কাছাকাছি চলে আসে, আপনি যখন জানেন যে আপনি কী করছেন। দেখুন সি প্রায়শই জিজ্ঞাসিত প্রশ্নাবলী উপর স্ট্রিং এবং অ্যারে

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