» נושאי לימוד
» נושאי לימוד
יום שני 29 באפריל 2024
מקטעי קוד מעניינים
דף ראשי  מתקדמים  Stream Tokenizer  תוכנית הדגמה  מקטעי קוד מעניינים גרסה להדפסה

מקטעי קוד מעניינים

התוכנית בשלמותה כלולה במתודה main() , שהתחלתה מוצגת במקטע הבא. מקטע זה יוצר מופע ומאתחל אובייקט של זרם קובץ פלט.

 

  public static void main(String[] args)
  {
    System.out.println(
                    "Start the program and write a file");
    try{
    FileOutputStream outFile = 
                          new FileOutputStream("junk.txt");
 המקטע הבא מציג את ההתחלה של לולאת for  שכותבת את ערכי התו בין 32 ל- 126 (כולל) בתוך הקובץ.

 

    for(int cnt = 32; cnt < 127; cnt++){

 

 

המקטע הבא מציג את הכנסתו של תו רווח כל תו שביעי, כתוצאה מכך התקבל סוג הפלט הבא שבו זרם הקלט פורק לקבוצות המורכבות משבעה תווים בכל קבוצה. הסיבה שהקבוצה הראשונה אינה מכילה שבעה תווים היא שלתווים הנמצאים ממש לפני האות הגדולה "A" התייחסו כתווים רגילים והם לא נשלטו על-ידי תו הרווח.

 returnValue=62 ttype=62 char = >
 returnValue=63 ttype=63 char =
?
 returnValue=64 ttype=64 char =
@
 TT_WORD ABCDE ttype=-3
 TT_WORD FGHIJKL ttype=-3
 TT_WORD MNOPQRS ttype=-3
TT_WORD TUVWXYZ ttype=-3

 

      if(cnt%7 == 0){
        outFile.write(' ');//every seventh char is space
      }//end if

 

מכיוון שהקובץ מכיל את רצף ה ASCII  בשלמותו, הוא יכיל את הערך של תו המירכאות הכפולות ("). אם הוא מופיע לבד, ה parser  יחשיב את התו הזה כהתחלה של מחרוזת עם מירכאות וימשיך לחפש את תו המירכאות התואם עד שיגיע לסוף המסמך.

בכדי להימנע מבעיה זו, וגם כדי להמחיש את השימוש במחרוזת עם מירכאות, הוכנס תו מירכאות שני במקום שנמצא בדיוק לפני התו &. זה גרם שהתווים שבין שתי המירכאות הכפולות יתפרשו כמחרוזת עם מירכאות המניבה את הפלט הבא:

                                                                                                                   Quoted string= #$% ttype=34 char = "

 

      if(cnt == '&') outFile.write('\"');

 

גם הגרש או המירכאה הבודדת הוא תוחם של ברירת מחדל עבור מחרוזות עם מירכאות.

מאותה הסיבה שהוזכרה קודם, גרש בודד הוכנס אל הקובץ בדיוק לפני התו כוכבית. זה הניב את הפלט הבא:

Quoted string=() ttype=39 char = '

 

 

      if(cnt == '*') outFile.write('\'');

 

 

 

לבסוף, אנחנו רואים את השלמתה של לולאת ה for ואת הכתיבה של ערך הבית הסדרתי לקובץ. מקטע זה סוגר את זרם קובץ הפלט. 

 

      outFile.write((char)cnt);//write the byte
    }//end for loop
    outFile.close();

 

 

 

 

המקטע הבא יוצר מופע לאובייקט של FileInputStream המקושר לקובץ בדיקה ועוטף (wraps) את אובייקט זרם הקלט הזה באובייקט של Reader. לאחר מכן הוא יוצר מופע לאובייקט של Stream tokenizer ועוטף אותו מסביב לאובייקט של Reader .

בשלב זה  אנו יכולים להפעיל את המתודה nextToken() על האובייקט של Stream Tokenizer בכדי לקבל את האסימון הבא מה FileInpuStream.  

 

    FileInputStream inFile = 
                           new FileInputStream("junk.txt");
    Reader rdr = new BufferedReader(
                            new InputStreamReader(inFile));
    StreamTokenizer strTok = new StreamTokenizer(rdr);

 

מספר המקטעים הבאים משנים את טבלת הפירוק ביחס לערכי הברירת מחדל שלה.

גרמתי לכך שאל התו / יתייחסו כתו רגיל מה שלא היה המצב בברירת מחדל. זה מניב את הפלט הבא, שהוא פלט טיפוסי לתו רגיל:

                                                                                                                     returnValue=47 ttype=47 char = /

 

    strTok.ordinaryChar('/');//forward slash

 

 

 

המקטע הבא משתמש בשתי קריאות שונות לאותה המתודה כדי לגרום שלתווים s,j,k,l יתייחסו כתווי רווח. זה מניב את הפלט הבא בו הרצף הנורמלי של התווים בזרם מפורק לאסימונים בהתאם לאותם תווים הנמצאים בו.

שים לב לפירוק בין ה i ל m  (חסר jkl), וכמו כן בין ה r  ל t (חסר s).

  TT_WORD a ttype=-3 

  TT_WORD bcdefgh ttype=-3 
TT_WORD i ttype=-3 
TT_WORD mno ttype=-3 
TT_WORD pqr ttype=-3 
                       TT_WORD tuv ttype=-3 
 

    strTok.whitespaceChars('s','s');
    strTok.whitespaceChars('j','l');


 

 

 

במצב ברירת המחדל התווים ; > = הם תווים רגילים. המקטע הבא גורם שיתייחסו אליהם כתווי מילה המניבים את הפלט הבא כששלושת התווים האלה מצטרפים יחד ובונים מילה.

returnValue=58 ttype=58 char = :
TT_WORD ;<= ttype=-3
returnValue=62 ttype=62 char = >

 

    strTok.wordChars(';','=');

 

 

 

זה משלים את השינויים בטבלת הפירוק. כל שנשאר לעשות הוא:

·   להיכנס ללולאה

·   להפעיל את ()nextToken בכל איטרציה של הלולאה

·  ולהמשיך לעשות looping  עד סוף המסמך.

המקטע הבא מראה את הלולאה, יחד עם מבנה switch המנתחת את ערך ההחזרה

 מ nextToken() כדי לקבוע את סוג האסימון, וכדי להציג מידע על האסימון המבוסס על החלטה זו. מבנה ה switch מלווה במספר הצהרות נוספות, המשתמשות בערך ה ttype בכדי להציג מידע נוסף על האסימון.

שים לב שבגלל התנאי בלולאת ה while, אמור תמיד להיות בלתי אפשרי להתאים את הערך של TT_EOF במבנה ה switch. הכנסתי שם את זה בכל אופן כדי להציג דבר בשלמותו. העדפתי לשמור את הקוד בשלמותו ולהדגיש חלק מההיבטים המעניינים שלו ב bold, מאשר לפרק אותו למקטעים קטנים יותר.

אם ערך ההחזרה מהמתודה תואם קבוע-מחלקה כל שהוא של המחלקה Stream Tokenizer, הוא לא תו רגיל. באחד מהמקרים האלה, מוצג הערך של sval כשהוא מכיל מילה, ובמקרה אחר מוצג הערך nval כשהוא מכיל מספר.

בנוסף לכך, שניים מהמקרים בודקים גרש בודד ומירכאות כפולות, ומציגים את הערך של sval  המכיל את גוף  המחרוזת עם המירכאות במקרה זה.

הביטוי של ברירת המחדל (default clause) במבנה ה switch מופעל כשערך ההחזרה הוא תו רגיל. הקוד שלאחר מבנה ה switch בא להמחיש שהערך של ttype  יכול לשמש לאותה המטרה בעיקרון.

 

    int returnValue = strTok.nextToken();//priming read
    while(returnValue != StreamTokenizer.TT_EOF){
      //Terminate the loop on end of file
      switch(returnValue){//determine the type of token
        case StreamTokenizer.TT_EOF ://shouldn't be here 
          System.out.print("TT_EOF ");break;
        case StreamTokenizer.TT_EOL ://end of line
          System.out.print("TT_EOL ");break;
        case StreamTokenizer.TT_NUMBER ://a number 
          System.out.print("TT_NUMBER " + strTok.nval);
          break;
        case StreamTokenizer.TT_WORD ://a word
          System.out.print("TT_WORD " + strTok.sval);break;
        case '\"' ://a double quote
          System.out.print("Quoted string=" + strTok.sval);
          break;
        case '\'' ://a single quote
          System.out.print("Quoted string=" + strTok.sval);
          break;
        default:System.out.print(//none of the above
                             "returnValue=" + returnValue);
      }//end switch
      
      //Use ttype variable to display additional info.
      System.out.print(" ttype=" + strTok.ttype + " ");  
      if(strTok.ttype >= 0)//neg is eof, eol, number, word 
        //display the character
        System.out.println("char = " + (char)strTok.ttype);
      else System.out.println();//new line on eol, etc.
      
      returnValue = strTok.nextToken();//get next token
    }//end while loop
    inFile.close();//close the file
    System.out.println(); //new line

 

חלק מהפלט שנוצר מהמקטע הזה מובא להלן. חלקים של פלט זה הוצגו גם קודם יחד עם הקוד שהכין את טבלת הפירוק ליצירת סוג התנהגות ספציפי. את הפלט שנשאר ניתן לראות בתוכנית השלמה המפורטת בשלב יותר מאוחר של השיעור.

returnValue=33 ttype=33 char = !
Quoted string= #$% ttype=34 char = "
returnValue=38 ttype=38 char = &
Quoted string=() ttype=39 char = '
returnValue=42 ttype=42 char = *
returnValue=43 ttype=43 char = +
returnValue=44 ttype=44 char = ,
TT_NUMBER -0.0 ttype=-2
returnValue=47 ttype=47 char = /
TT_NUMBER 0.0 ttype=-2
TT_NUMBER 1234567.0 ttype=-2
TT_NUMBER 89.0 ttype=-2
returnValue=58 ttype=58 char = :
TT_WORD ;<= ttype=-3
returnValue=62 ttype=62 char = >
returnValue=63 ttype=63 char = ?
returnValue=64 ttype=64 char = @
TT_WORD ABCDE ttype=-3
TT_WORD FGHIJKL ttype=-3
TT_WORD MNOPQRS ttype=-3
TT_WORD TUVWXYZ ttype=-3
returnValue=91 ttype=91 char = [
returnValue=92 ttype=92 char = \

 

המקטע הסופי פשוט קורא ומציג את הקובץ שוב באופן רצוף למקרה שיש לך שאלה כל שהיא לגבי התכנים האמיתיים של הקובץ . אתה יכול לראות את הפלט שהניב המקטע הזה בחלק הבא.

    System.out.println("Display file data");
    //Open the file again for simple read and display
    inFile = new FileInputStream("junk.txt");
    int data;
    int cnt = 0;
    while( (data = inFile.read()) != -1){
      System.out.print("" + data + " ");
      System.out.print((char)data + "   ");
      if(cnt++ == 4){//new line every fifth read
        System.out.println();//new line
        cnt = 0;//reinitialize the counter
      }//end if
    }//end while
    inFile.close();//close file again

 

 

 

 

 

 

 

 

 

 

 

 

את הקוד שהודגש במקטעים שלעיל ניתן לראות בפירוט המלא של התוכנית שמופיע להלן בחלק הבא.

 

 29-11-03 / 17:19  נוצר ע"י רונית רייכמן  בתאריך 
 תוכנית הדגמה - הקודםהבא - רישום תוכנית 
תגובות הקוראים    תגובות  -  0
דרכונט
מהי מערכת הדרכונט?
אינך מחובר, להתחברות:
דוא"ל
ססמא
נושאי לימוד
חיפוש  |  לא פועל
משלנו  |  לא פועל
גולשים מקוונים: 2