هل يمكنني الحصول على بعض التعليقات على وظيفة STRCMP () التي قمت بتطبيقها في C؟

StackOverflow https://stackoverflow.com/questions/4008158

  •  25-09-2019
  •  | 
  •  

سؤال

أنا أتعلم C.

أجد أنني أتعلم البرمجة جيدًا عندما أجرب الأشياء وتلقيت ملاحظات من المبرمجين المعروفين باللغة.

قررت أن أكتب بلدي strcmp() وظيفة ، فقط لأنني اعتقدت أنني أستطيع :)

int strcompare(char *a, char *b) {
    while (*a == *b && *a != '\0') {
        a++;
        b++;
    }
    return *a - *b;
}

كنت أحاول تشغيله عن طريق زيادة المؤشر في حالة while ولكن لم يستطع معرفة كيفية القيام return. كنت ذاهب ل C النمط رمز ، من فعل أكبر قدر ممكن على سطر واحد :)

هل يمكنني الحصول على بعض التعليقات من مبرمجي C المعمول بها؟ هل يمكن تحسين هذا الرمز؟ هل لدي أي عادات سيئة؟

شكرًا.

هل كانت مفيدة؟

المحلول

  1. الوظيفة لا تغير محتوى a و b. ربما يجب أن تعلن أنه من خلال أخذ المؤشرات إلى const سلاسل.
  2. معظم أنماط C هي terser بكثير من أنماط العديد من اللغات الأخرى ، ولكن لا تحاول أن تكون ذكية للغاية. (في الكود الخاص بك ، مع العديد من الشروط و ظروف الحلقة ، لا أعتقد أن هناك طريقة لوضع زيادة هناك ، لذلك هذا ليس حتى مسألة الأسلوب ، ولكن من الصواب.)

نصائح أخرى

إذا كنت تريد أن تفعل كل شيء في البيان ، فيمكنك الكتابة

while (*a != '\0' && *a++ == *b++) {}

أنا شخصياً لست معجبًا كبيرًا بهذا النمط من البرمجة - يحتاج القراء إلى "فك" ترتيب العمليات عقلياً على أي حال ، عند محاولة فهمه (والعمل إذا كان الكود عربات التي تجرها الدواب أم لا). تعتبر أخطاء الذاكرة غدرا بشكل خاص في C ، حيث تكتب الذاكرة فوق بايت واحد إلى ما وراء أو قبل أن تتسبب في جميع أنواع الحوادث أو الأخطاء التي لا يمكن تفسيرها في وقت لاحق ، بعيدًا عن السبب الأصلي.

تؤكد الأساليب الحديثة للبرمجة C على الصواب والاتساق والانضباط أكثر من tersence. كانت ميزات التعبير terse ، مثل عمليات ما قبل وما بعدها ، وسيلة في الأصل لجعل المترجم لإنشاء رمز آلي أفضل ، ولكن يمكن للمحسّنات القيام بذلك بسهولة في هذه الأيام.

كما يكتب sbi ، أفضل const char * الحجج بدلا من عادي char * الحجج.

لا أعرف منذ ذلك الحين عند وضع أكبر قدر ممكن على الطريقة C ... أنا أفضل أن أربط (متورط) بيرل مع ذلك ..

من فضلك لا تفعل هذا. أفضل شيء القيام به هو أمر واحد لكل سطر. سوف تفهم لماذا عندما تحاول تصحيح رمزك :)

لتنفيذك: يبدو جيدًا جدًا بالنسبة لي ، لكنني سأضع في حالة عدم وجود *B " 0" ، لأنه لا يمكنك أن تعرف أن A دائمًا أكبر من B ... وإلا فإنك تخاطر بالقراءة في غير مخصصة ذاكرة...

قد تجد هذا مثير للاهتمام ، من eglibc-2.11.1. لا يختلف الأمر كثيرًا عن تنفيذك.

/* Compare S1 and S2, returning less than, equal to or
   greater than zero if S1 is lexicographically less than,
   equal to or greater than S2.  */
int
strcmp (p1, p2)
     const char *p1;
     const char *p2;
{
  register const unsigned char *s1 = (const unsigned char *) p1;
  register const unsigned char *s2 = (const unsigned char *) p2;
  unsigned reg_char c1, c2;

  do
    {
      c1 = (unsigned char) *s1++;
      c2 = (unsigned char) *s2++;
      if (c1 == '\0')
    return c1 - c2;
    }
  while (c1 == c2);

  return c1 - c2;
}

علة خفية جدا: strcmp يقارن بايت تفسر على أنها unsigned char, ، لكن وظيفتك تفسرها على أنها char (الذي تم توقيعه على معظم التطبيقات). سيؤدي ذلك إلى فرز الشخصيات غير ASCII قبل ASCII بدلاً من بعد.

ستفشل هذه الوظيفة إذا كانت حدود (chisiged) char تساوي أو أكبر من حدود int بسبب زيادة عدد صحيح.

على سبيل المثال ، إذا قمت بتجميعه على DSP الذي يحتوي على 16 بت مع حدود 0 ... 65536 و 16 بت int مع حدود -32768 ... 32767 ، ثم إذا حاولت مقارنة سلاسل مثل "/UA640" و "A" ستكون النتيجة سلبية ، وهذا غير صحيح.

هذه مشكلة غريبة وغريبة ولكنها تظهر عند كتابة التنفيذ الشامل.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top