سؤال

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

رمز التحليل الذي كتبته هو:

if (songSource.canRead()) {  //checks to see if file is valid to read
    readIn= new Scanner(songSource);
    while (readIn.hasNextLine()) {
 do {
     readToken= readIn.nextLine();

             if (readToken.startsWith("ARTIST=\"")) {
  artist= readToken.split("\"")[1];
      } 
      if (readToken.startsWith("TITLE=\"")) {
  title= readToken.split("\"")[1];
      } 
      if (readToken.startsWith("LYRICS=\"")) {
  lyrics= readToken.split("\"")[1];
      } else {
  lyrics+= "\n"+readToken;
      }//end individual song if block
 } while (!readToken.startsWith("\"")); //end inner while loop

    songList.add(new Song(artist, title, lyrics));

    }//end while not EOF 
} //end if file can be read 

كنت أتحدث مع مقدمة إلى خوارزميات أستاذ حول الكود لهذا المشروع ، وذكر أنه يجب أن أحاول أن أكون أكثر دفاعية في الكود الخاص بي للسماح بالتناقضات في البيانات التي يوفرها أشخاص آخرين. في الأصل كنت أستخدم If/Else Colls بين الفنان والعنوان وكلمات الأغاني ، وعلى اقتراحه ، قمت بتغيير التسلسل إذا كانت عبارات. على الرغم من أنني أستطيع أن أرى وجهة نظره ، باستخدام مثال الرمز هذا ، كيف يمكنني أن أكون أكثر دفاعية حول السماح بتناقضات الإدخال؟

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

المحلول

أنت تفترض أن المدخلات مثالية. إذا نظرت إلى الطريقة التي يتم بها إعداد تطبيقك حاليًا ، استنادًا إلى قراءة سريعة لخوارزميةك ، فإن البيانات ستبدو هكذا

ARTIST="John"
TITLE="HELLO WORLD"
LYRICS="Sing Song All night long"
"

لكن النظر في القضية

ARTIST="John"
TITLE="HELLO WORLD"
LYRICS="Sing Song All night long"
"
ARTIST="Peter"
LYRICS="Sing Song All night long"
"

بناءً على الخوارزمية الخاصة بك ، لديك الآن أغنيتين تميزان

songList = { Song("JOHN", "HELLO WORLD", "Sing Song All night long"),
             Song("Peter", "HELLO WORLD", "Sing Song All night long") }

مع الخوارزمية الحالية ، يتم كشف الفنان والعنوان وسيظهران في الأغنية الثانية على الرغم من أنهما لم يتم تعريفهما. تحتاج إلى إعادة ضبط المتغيرات الثلاثة.

في آخر ، أنت فقط تلقائي الخط الكامل في كلمات. ماذا لو كنت قد قمت بالفعل بسحب الأغاني ، فأنت الآن تتجاوز ذلك. حالة اختبار

 ARTIST="John"
 LYRICS="Sing Song All night long"
 TILET="HELLO WORLD"
 "

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

كما أنك تفكر فقط في EOF بعد قراءة الفنان. ماذا لو حدث EOF أثناء قراءة الفنان ، ولم ينتهي الملف ". ستحصل على استثناء هناك. ()

نصائح أخرى

أود استبدال EG:

artist= readToken.split("\"")[1];

مع

String[] parts = readToken.split("\"");
if(parts.length >= 2) artist = parts[1];
else continue;

تشمل التعديلات الأخرى:

  1. أعد ضبط المتغيرات المحلية (حتى لا تحصل على الفنان الخطأ عن طريق الخطأ لأغنية ، إذا لم يتم توفير أي فنان لبعض الأغاني بعد الأول)
  2. قرر ماذا تفعل إذا كانت بعض البيانات مفقودة - هل ما زلت ترغب في إضافة الأغنية إلى قائمة الأغاني؟

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

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

لذا ، إليك بعض الأسئلة الأساسية لطرحها على نفسك:
1. هل كل سطر مضمون لاحتواء كل حقل؟
2. هل ترتيب الحقول مضمون؟

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

أرى بعض الأشياء المفقودة هنا جيسون.

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

أيضا ، ماذا يحدث إذا كان العنوان ، الفنان ، وما إلى ذلك لديه اقتباس فيه؟ كيف يتم التعامل مع ذلك؟ ماذا عن كلمات الأغاني التي يبدو أنها خطوط متعددة أليس كذلك؟

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

فيما يلي بعض المشكلات التي يمكن معالجتها:

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

  • يفترض الرمز الخاص بك أن الكلمات الرئيسية موجودة في جميع الكتب. يمكن لشخص ما استخدام الحالة الصغيرة أو المختلطة.

  • يفترض الرمز الخاص بك أن الخط الذي لا يبدأ keyword=\" هو استمرار كلمات الأغنية. ولكن ماذا لو دخل المستخدم ARTOST="Sting"؟ أو ماذا لو حاول المستخدم استخدام سطرين لاسم الفنان؟

أخيرًا ، لست مقتنعًا بأن استبدال "آخر إذا" مع "إذا" في هذه الحالة لديها أحدثت أي فرق في متانة الكود.

تعامل مع الاستثناءات (أعتقد أن الماسح الضوئي يمكن أن يرمي inputMismatchException لشخصية غير صالحة).

يبدو مثل do { } while (...) يمكن حلقة ما لا نهاية إذا كان الملف غير مشكل ، ويتم الوصول إلى نهاية الملف.

لا شيء يمنع artist أو title من أن تكون فارغة.

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