স্টারকেসক্যাম্প অ্যালগরিদম ত্রুটিযুক্ত?


34

আমি পুনরায় বাস্তবায়ন করার চেষ্টা করছি strcasecmp ফাংশনটি এবং আমি লক্ষ্য করেছি যে তুলনা প্রক্রিয়ায় কোনটি অসঙ্গতি বলে মনে হচ্ছে।

থেকে man strcmp

Strcmp () ফাংশন দুটি স্ট্রিং এস 1 এবং এস 2 এর সাথে তুলনা করে। লোকেলটি অ্যাকাউন্টে নেওয়া হয় না (স্থানীয়-সচেতন তুলনার জন্য, স্ট্রোকল (3) দেখুন)। এটি সংখ্যার চেয়ে কম, সমান বা শূন্যের চেয়ে বৃহত্তর যদি পূর্ণ হয়, যথাক্রমে, কম হয়, মিল হয়, বা এস 2 এর চেয়ে বড় হয়।

থেকে man strcasecmp

স্টারকেসক্যাম্প () ফাংশন অক্ষরের ক্ষেত্রে উপেক্ষা করে স্ট্রিং এস 1 এবং এস 2 এর বাই বাই বাই তুলনা সম্পাদন করে। এটি সংখ্যার চেয়ে কম, সমান বা শূন্যের চেয়ে বৃহত্তর যদি পূর্ণ হয়, যথাক্রমে, কম হয়, মিল হয়, বা এস 2 এর চেয়ে বড় হয়।

int strcmp(const char *s1, const char *s2);
int strcasecmp(const char *s1, const char *s2);

প্রদত্ত, এই তথ্যটি, আমি নিম্নলিখিত কোডের ফলাফল বুঝতে পারি না:

#include <stdio.h>
#include <string.h>

int main()
{
    // ASCII values
    // 'A' = 65
    // '_' = 95
    // 'a' = 97

    printf("%i\n", strcmp("A", "_"));
    printf("%i\n", strcmp("a", "_"));
    printf("%i\n", strcasecmp("A", "_"));
    printf("%i\n", strcasecmp("a", "_"));
    return 0;
}

Ouput:

-1  # "A" is less than "_"
1   # "a" is more than "_"
2   # "A" is more than "_" with strcasecmp ???
2   # "a" is more than "_" with strcasecmp

এটি উপস্থিত অক্ষরটি যদি s1একটি অক্ষর হয় তবে উপস্থিত অক্ষরটি নির্বিশেষে এটি সর্বদা ছোট হাতের অক্ষরে রূপান্তরিত হয় appearss2 একটি অক্ষর বা নয়।

কেউ কি এই আচরণ ব্যাখ্যা করতে পারেন? প্রথম এবং তৃতীয় লাইনটি এক হওয়া উচিত নয়?

তুমাকে অগ্রিম ধন্যবাদ!

PS:
আমি gcc 9.2.0মাঞ্জারো ব্যবহার করছি ।
এছাড়াও, আমি যখন -fno-builtinপতাকাটি সংকলন করি তখন পরিবর্তে পাই:

-30
2
2
2

আমি অনুমান করি কারণ এটি প্রোগ্রামটি সিসির অপ্টিমাইজড ফাংশনগুলি ব্যবহার করে না, তবে প্রশ্নটি রয়ে গেছে।


2
আপনার সেট আরেকটি পরীক্ষা ক্ষেত্রে যোগ করুন printf("%i\n", strcasecmp("a", "_"));এই সম্ভবতঃ হিসাবে একই ফলাফলের থাকা উচিত printf("%i\n", strcasecmp("A", "_"));কিন্তু তার মানে তাদের এক এই দুটি কেস-অবশ কল তার কেস সংবেদনশীল সহযোগীর সঙ্গে মতানৈক্য যাচ্ছে।
anton.burger

দেখে মনে হচ্ছে যে strcasecmpআপনি উল্লেখ করছেন তার বিবরণটি সঠিক নয়। Upvated উত্তরে আরও বিশদ।
জ্যাবারওয়াকি

9
এটি একমাত্র জিনিস যা বোধগম্য হয়। এমন একটি ফাংশন যা বলে যে A < _ && a > _ && A == aঅনেক সমস্যার কারণ হতে পারে।
ইকগামি

একদিকে: "আমি সিতে স্ট্র্যাসেক্যাম্প ফাংশনটি পুনরায় প্রয়োগ করার চেষ্টা করছি" -> কোডটি প্রদর্শিত না হলেও, "যেমন" তুলনা করতে ভুলবেন না unsigned char। C17 / 18 "স্ট্রিং হ্যান্ডলিং <স্ট্রিং।>" -> "এই উপক্লাজের সমস্ত ফাংশনের জন্য, প্রতিটি অক্ষরকে ব্যাখ্যা করা হবে যেমন এটির ধরন রয়েছে unsigned char"। charমানগুলি ASCII ব্যাপ্তি 0-127 এর বাইরে গেলে এটি একটি পার্থক্য তৈরি করে ।
chux -

1
বিল্ট-ইনগুলি এবং ছাড়াই আউটপুটগুলির পার্থক্য সম্পর্কে: উভয়ই একই কথা বলে, কারণ তাদের ফলাফলগুলি অভিন্ন <0 এবং> 0 হয় এবং আপনার কাছে == 0 এর উদাহরণ নেই। তবে আপনি দেখতে পাচ্ছেন অ্যালগোরিদমগুলি জ্বলজ্বল করে: ফিরে আসা মানগুলির মধ্যে কয়েকটি হ'ল প্রথম অ-সম-চরিত্রের পার্থক্য।
ব্যস্তবী

উত্তর:


31

আচরণটি সঠিক।

প্রতি POSIX str\[n\]casecmp()স্পেসিফিকেশন :

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

যে অংশ নোটস লিনাক্স মানুষ পৃষ্ঠার অধ্যায় :

POSIX.1-2-2008 স্ট্যান্ডার্ড এই ফাংশন সম্পর্কে বলে:

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

কেন?

যেমন @ হ্যানস অলসন তাঁর উত্তরে উল্লেখ করেছেন যে কেবলমাত্র চিঠির মধ্যে কেস-সংবেদনশীল তুলনা করা এবং অন্যান্য সমস্ত তুলনা তাদের "প্রাকৃতিক" ফলাফল হিসাবে করা যেমন strcmp()বাছাইয়ের কাজ ভাঙবে।

যদি 'A' == 'a'(কেস-সংবেদনশীল তুলনার সংজ্ঞা) তবে '_' > 'A'এবং '_' < 'a'(এএসসিআইআই চরিত্রের সেটটিতে "প্রাকৃতিক" ফলাফল) উভয়ই সত্য হতে পারে না।


কেবলমাত্র বর্ণগুলির মধ্যে কেস-সংবেদনশীল তুলনা করলে ফলাফল হয় না '_' > 'A' && '_' < 'a'; সেরা উদাহরণ মত মনে হচ্ছে না।
উইন্ডোজ উইন্ড উইন্ডস উইন্ডো

1
@ এস্টারয়েডস উইথওওয়িংস এগুলি প্রশ্নে ব্যবহৃত অক্ষর। যদি 'a' == 'A' সংজ্ঞা দ্বারা , আপনি যদি এর "স্বাভাবিক" মানের মধ্যে একটি তুলনা না 'a', 'A'এবং '_', আপনি করতে পারবেন না মধ্যে একটি কেস-অবশ তুলনা না 'A'এবং 'a'সমতা পেতে এবং সামঞ্জস্যপূর্ণ সাজানোর ফলাফল পেতে।
অ্যান্ড্রু হেনেল

আমি এটিকে বিতর্ক করছি না, তবে আপনি যে নির্দিষ্ট পাল্টা উদাহরণ দিয়েছেন তা প্রাসঙ্গিক বলে মনে হচ্ছে না।
উইন্ডোজ উইথ উইন্ডোজ

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

ঠিক আছে, তারপরে আমি এর উত্তরে এটি প্রমাণ করার পরামর্শ দিচ্ছি কারণ এই মুহূর্তে এটি কেবল উল্লেখ করতে লাফ দেয় যে " '_' > 'A' এবং '_' < 'a'উভয়ই সত্য হতে পারে না" কেন আমাদের কখনও চিন্তা করা উচিত ছিল না যে এটি হবে। (এটি উত্তরদাতাদের পক্ষে কাজ, লক্ষ লক্ষ পাঠকের একের জন্য নয়))
উইন্টার উইং উইংস উইথ উইং

21

অন্যান্য লিঙ্কগুলি, http://man7.org/linux/man-pages/man3/strcasecmp.3p.html স্ট্র্যাপস্যাম্পের জন্য বলে যে লোয়ার-কেসে রূপান্তর করা সঠিক আচরণ (কমপক্ষে পসিক্স লোকালে)।

এই আচরণের কারণটি হ'ল আপনি যদি স্ট্রকেস অ্যারেটিকে বাছাই করার জন্য স্টারকেসক্যাম্প ব্যবহার করেন তবে যুক্তিসঙ্গত ফলাফল পাওয়া দরকার।

অন্যথায় আপনি উদাহরণস্বরূপ "A", "সি", "_", "বি" কে বাছাই করার চেষ্টা করলে, ফলাফলটি তুলনার ক্রমের উপর নির্ভর করে।


3
অন্যথায় আপনি উদাহরণস্বরূপ "A", "সি", "_", "বি" কে বাছাই করার চেষ্টা করলে, ফলাফলটি তুলনার ক্রমের উপর নির্ভর করে। ভাল যুক্তি. পসিক্স আচরণটি নির্দিষ্ট করার কারণ সম্ভবত।
অ্যান্ড্রু হেনেল

6
আরও দৃ concrete ়ভাবে, বাছাইয়ের জন্য আপনার মোট অর্ডার দরকার , যা আপনি যদি প্রশ্নের তুলনায় তুলনাটি সংজ্ঞায়িত করেন তবে তা হবে না (যেহেতু এটি ট্রানজিটিভ হবে না)।
ডিউক্লিং

8

এটি উপস্থিত হয় যে, এস 1 এর বর্তমান অক্ষরটি যদি একটি চিঠি হয় তবে এস 2-র বর্তমান চরিত্রটি কোনও চিঠি কিনা তা নির্বিশেষে এটি সর্বদা ছোট হাতের অক্ষরে রূপান্তরিত হয়।

এটি সঠিক - এবং এটি strcasecmp()ফাংশনটি করা উচিত ! এটি স্ট্যান্ডার্ডের POSIXঅংশের চেয়ে একটি ফাংশন Cতবে " ওপেন গ্রুপ বেস স্পেসিফিকেশন, ইস্যু 6 " থেকে:

পসিক্স লোকালে, স্টারকেসক্যাম্প () এবং স্ট্রেনকেসেস্প () স্ট্রিংগুলি লোয়ারকেসে রূপান্তরিত হয়েছে এবং তারপরে একটি বাইট তুলনা সম্পাদন করা হবে। ফলাফলগুলি অন্য লোকালগুলিতে অনির্ধারিত।

ঘটনাচক্রে, এই আচরণটি _stricmp()ফাংশনটির ক্ষেত্রেও প্রাসঙ্গিক (যেমন ভিজ্যুয়াল স্টুডিও / এমএসসিভিতে ব্যবহৃত হয়):

_Stricmp ফাংশনটি প্রতিটি অক্ষরকে ছোট হাতের মধ্যে রূপান্তর করার পরে স্ট্রিং 1 এবং স্ট্রিং 2 এর সাথে সাধারণত তুলনা করে এবং তাদের সম্পর্কের ইঙ্গিত করে এমন একটি মান প্রদান করে।


2

জন্য হওয়া ASCII দশমিক কোড Aহয় 65জন্য _হয় 95এবং জন্য aহয় 97, তাই strcmp()তা করছেন কি এটা করতে অনুমান আছে। অভিধানের কথা বলতে গেলে _তার aচেয়ে ছোট এবং এর চেয়েও বড় A

strcasecmp()* Aহিসাবে বিবেচিত হবে a, এবং যেহেতু aবড় _আউটপুটটিও সঠিক।

* POSIX.1-2-2008 স্ট্যান্ডার্ডটি এই ফাংশনগুলির সম্পর্কে (স্টারকেসক্যাম্প () এবং স্ট্রেনকেসেস্প ()) বলে:

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

সূত্র: http://man7.org/linux/man-pages/man3/strcasecmp.3.html


3
ওপি এর বিন্দু যে A"বড়" চেয়ে _যখন তুলনা কেস-insensitively, এবং বিস্ময়ের কেন ফলাফলের যখন তুলনা কেস-সংবেদনশীলভাবে হিসাবে একই নয়।
anton.burger

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

@ এরিকপোস্টপিসিল এই ফাংশনগুলির বিষয়ে স্ট্রোকসেস্প () এবং স্ট্রেনক্যাসেম্প্প ()) পসিক্স ১.২-২০০৮ স্ট্যান্ডার্ড বলছে: যখন ব্যবহৃত লোকেলের এলসি_সিটিওয়াইপি বিভাগটি পসিক্স স্থানীয় থেকে হয়, তখন এই ফাংশনগুলি এমন আচরণ করবে যেমন স্ট্রিংগুলিতে রূপান্তরিত হয়েছে had ছোট হাতের অক্ষর এবং তারপরে একটি বাইট তুলনা সঞ্চালিত। অন্যথায়, ফলাফল অনির্ধারিত।
anastaciu
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.