سؤال

لقد حصلت للتو على Delphi 2009 وقد قرأت سابقًا بعض المقالات حول التعديلات التي قد تكون ضرورية بسبب التحول إلى سلاسل Unicode.في الغالب، يُذكر أن sizeof(char) لم يعد مضمونًا أن يكون 1 بعد الآن.ولكن لماذا يكون هذا مثيرًا للاهتمام فيما يتعلق بالتلاعب بالسلسلة؟

على سبيل المثال، إذا استخدمت AnsiString:='Test' وفعلت الشيء نفسه باستخدام String (وهو Unicode الآن)، فسوف أحصل على Length() = 4 وهو الصحيح في كلتا الحالتين.بدون اختبارها، أنا متأكد من أن جميع وظائف معالجة السلسلة الأخرى تتصرف بنفس الطريقة وتقرر داخليًا ما إذا كانت الوسيطة عبارة عن سلسلة Unicode أو أي شيء آخر.

لماذا يكون الحجم الفعلي للحرف محل اهتمام بالنسبة لي إذا قمت بمعالجة السلسلة؟(بالطبع إذا كنت أستخدم السلاسل كسلاسل وليس لتخزين أي بيانات أخرى)

شكرا على اي مساعدة!هولجر

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

المحلول

مع يونيكود SizeOf(SomeChar) <> الطول(SomeChar).في الأساس طول أ خيط أقل من مجموع حجمه شارس.طالما أنك لا تفترض حجم (شار) = 1, ، أو SizeOf(SomeString[x]) = 1 (بما أن كلاهما خطأ شنيع الآن) أو حاول التبادل بايتمع شارs، فلا ينبغي أن تواجه أي مشكلة.في أي مكان تقوم فيه بشيء حشو إبداعي بايتفي شارق أو خيطs، فإنك سوف تحتاج إلى استخدام AnsiString.

(SizeOf(SomeString) لا يزال 4 بغض النظر عن الطول لأنه في الأساس مؤشر مع بعض سحر المترجم.)

نصائح أخرى

غالبًا ما يقوم الأشخاص بالتحويل ضمنيًا من الأحرف إلى البايتات في كود دلفي القديم دون التفكير في الأمر حقًا.على سبيل المثال، عند الكتابة إلى دفق.عندما تكتب سلسلة إلى دفق، يجب عليك تحديد عدد البايتات التي تكتبها، ولكن غالبًا ما يقوم الأشخاص بتمرير عدد الأحرف بدلاً من ذلك.يرى هذه المشاركة من كريس بنسن لمثال آخر.

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

لم أجرب دلفي 2009، لكني أستخدم fpc والذي يتحول أيضًا إلى unicode ببطء.أنا متأكد بنسبة 95% من أن كل شيء أدناه ينطبق أيضًا على Delphi 2009

في fpc (عند دعم Unicode)، سيكون الأمر كذلك أن وظائف مثل "الطول" تأخذ صفحة الرموز في الاعتبار.وبالتالي سيعيد طول السلسلة كما يراها "الإنسان".إذا كان هناك - على سبيل المثال - حرفين صينيين، وكلاهما يأخذ بايتين من الذاكرة في Unicode، فسيرجع الطول 2، نظرًا لوجود حرفين في السلسلة.لكن السلسلة ستأخذ 4 بايت من الذاكرة.(+ذاكرة العدد المرجعي والرقم 0 البادئ، لكن هذا جانبًا)

ما لا يمكنك فعله بعد الآن هو هذا:

var p : pchar;
begin
  p := s[1];
  for i := 0 to length(string)-1 do
    begin
    write(p);
    inc(p);
    end;      
end;

لأن هذا الكود - في مثال الحرفين الصينيين - سيكتب الحرفين الخطأ.وهما البايتتان اللتان تشكلان جزءًا من الحرف "الحقيقي" الأول.

باختصار:لم يعد الطول () يُرجع مقدار البايتات المخصصة للسلسلة بعد الآن، بل يُرجع عدد الأحرف.(قبل التبديل إلى Unicode، كانت هاتان القيمتان متساويتان لبعضهما البعض)

الحجم الفعلي للحرف لا يهم، إلا إذا كنت تقوم بالمعالجة على مستوى البايت.

(بالطبع إذا كنت أستخدم السلاسل كسلاسل وليس لتخزين أي بيانات أخرى)

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

دعونا لا ننسى أن هناك أوقاتًا لا يكون فيها هذا التحويل مرغوبًا حقًا.قل لتخزين GUID في سجل على سبيل المثال.يمكن أن يحتوي الدليل فقط على أحرف سداسية عشرية بالإضافة إلى - والأقواس... مما يجعلها تشغل مساحة مضاعفة يمكن أن يكون له تأثير كبير على التعليمات البرمجية الموجودة.من المؤكد أن الحل البسيط هو تغييرها إلى AnsiString، والتعامل مع تحذيرات المترجم إذا قمت بأي معالجة للسلسلة عليها.

يمكن أن تكون مشكلة إذا قمت بإجراء مكالمات Windows API.أو إذا كان لديك رمز قديم يفعل ذلك شركة أو ديسمبر ل شارع[0] لتغيير طوله.

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