توليد هياكل البيانات عن طريق تحليل ملفات نصية عادي

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

  •  18-09-2019
  •  | 
  •  

سؤال

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

class Character
{
public:
    int x, y; // Character's location
    Character* teammate;
}

قمت بإعداد محللي للقراءة من ملف بنية البيانات مع بناء جملة مشابه ل C ++

Character Sidekick
{
    X = 12
    Y = 0
}

Character AwesomeDude
{
    X = 10
    Y = 50
    Teammate = Sidekick
}

سيؤدي هذا إلى إنشاء هياكل بياناتين ووضعها في الخريطة<std::string, Character*>, ، حيث السلسلة الرئيسية هي أي اسم أعطيته (في هذه الحالة الصاحب والمراعاة). عندما يرى محلل محللي مؤشرا إلى فئة، مثل مؤشر زميل الفريق، فإنه ذكي بما يكفي للبحث في الخريطة لجلب المؤشر إلى بنية البيانات هذا. المشكلة هي أنه لا يمكنني إعلان زميله في فريق Sidekick ليكون رائعا لأنه لم يتم وضعه في خريطة الشخصية بعد.

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

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

الطريقة التي تبدو وكأنها نهج أفضل؟ هل هناك خيار ثالث لم أفكر فيه؟ يبدو أنه يجب أن يكون هناك أي حل ذكي لهذه مراجع مؤشر أو ملزمة أو شيء ما ...: - / أفترض أن هذا هو شخصي إلى حد ما بناء على الميزات التي أريد أن أعطيها لنفسي، ولكن أي مدخل هو موضع ترحيب.

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

المحلول

عندما تواجه المرجع في المرة الأولى، ما عليك سوى تخزينه كمرجع. ثم، يمكنك وضع الحرف، أو المرجع، أو أيا كان في قائمة "المراجع التي تحتاج إلى حلها لاحقا".

عند الانتهاء من الملف، تشغيل من خلال أولئك الذين لديهم مراجع وحلها.

نصائح أخرى

حسنا، طلبت خيار ثالث. ليس لديك لاستخدام XML، ولكن إذا اتبعت الهيكل التالي، فسيكون من السهل جدا استخدام محلل ساكس لإنشاء بنية البيانات الخاصة بك.

على أي حال، بدلا من الرجوع إلى زميله في الفريق، يشير كل حرف إلى فريق (فريق أزرق في هذه الحالة). سيؤدي هذا إلى فصل المشكلة المرجعية الدائرية. فقط تأكد من سرد الفرق قبل الأحرف.

<team>Blue</team>

<character>
    <name>Sidekick</name>
    <X>12</X>
    <Y>0</Y>
    <teamref>Blue</teamref>
</character>

<character>
    <name>Sidekick</name>
    <X>10</X>
    <Y>50</Y>
    <teamref>Blue</teamref>
</character>

شخصيا، سأذهب مع ب). تقسيم التعليمات البرمجية الخاصة بك إلى فئات المحلل والمصادقة، تعمل كلاهما على نفس هيكل البيانات. سيؤدي المحلل المحلل وتحليل ملف، وملء بنية البيانات وتخزين أي مراجع كائن كأسماء نصية لهم، وترك المؤشر الحقيقي لاغيا في هيكلك الآن.

عند الانتهاء من تحميل الملفات، استخدم فئة Validator للتحقق من صحة وحل أي مراجع، تعبئة المؤشرات "الحقيقية". سوف ترغب في التفكير في كيفية تنظيم بياناتك لجعل هذه عمليات البحث لطيفة وسريعة.

سيقول بالضبط ما كنت على وشك الكتابة. فقط احتفظ بقائمة أو شيء ما مع المراجع التي لم يتم حلها.

ولا تنس رمي خطأ إذا كانت هناك مراجع غير مستحقة بمجرد الانتهاء من قراءة الملف = P

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

طبقة أخرى من غير مباشر .... إنها دائما تجعل البرمجة أسهل وأبطأ.

سيكون أحد الخيارات هو عكس الالتزام. الخريطة هي المسؤولة عن ملء المرجع

template<T> class SymbolMap // I never could rememeber C++ template syntax
{
   ...

   /// fill in target with thing name
   /// if no name yet, add it to the list of thing that will be name
   void Set(T& target, std::string name);

   /// define name as target
   /// go back and fill in anything that needs to be name
   void Define(T target, std::string name);

   /// make sure everything is resolved
   ~SymbolMap()
}

لن يتفاعل هذا جيدا مع دلالات القيمة / المتحركة ولكني أظن أنه لن يفعل الكثير.

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