LAB-11 從檔案讀入資料並排序後印出部份資料 
Due:  這題分三個階段 Due:
      (1)只寫研讀題目與相關範例的心得, Due 一週內! Due 後才交打五折!!
         以下算做 Lab-12, Lab-13; Due 過後繳交則分數逐週打九折!
      (2)Lab-12: 不可用struct, 即日起兩週內 (第三週仍可繳交, 但分數打九折)
      (3)Lab-13: 必須用struct做, Due : 比不使用 struct 的版本多一週 :-) 

Purpose: 
      (1)學習如何把資料按照某種順序 Sort (排序).
         順便學習如何寫入檔案與讀取檔案.
      (2)並從程式庫中的 qsort( ) 用法學習 call back function;
         (請用 gogle.com 查詢 "call back function" )
      (3)也學習使用 資料結構的基本 struct 來組織資料,
         以及站在巨人的肩膀上: 使用 C++ 的 STL 程式庫中的 sort;
      ** 常見排序法: Selection sort, Insertion sort, Bubble sort, Quick sort

說明:
 寫一個程式可以:
   從檔案 studat.txt 讀入一堆學生資料, 然後依照規定排序並輸出!
   在 studat.txt 裡面每列為一位學生資料,
   有學號, 姓名, 作業成績 h, 期中考成績 m, 小考成績 q, 期末考成績 f,
  你要: 
  (1)讀入資料並先算出每人的學期總成績 :
       學期總成績 = (h*0.2 + m*0.3 + q*0.1+f*0.4); (此項印到小數點後兩位)
     然後印出 學號, 姓名, 接著各次成績, 以及學期總成績  (以學號為序)
       印完學生資料後,  (因資料很多, 只印出前面6個, 以及最後面6個)
     必須再印出全部同學的 學期總成績之平均, 以及總成績的標準差;
  (2)把資料排序, 怎麼做自己決定, 但必須量測sorting時間, 且還要印出:
     照學期總成績由高排到低的前面6個, 以及最後面6個(學期總成績最低的)的資料!
  (3)再來, 印出照學號由小到大排序的前面6個, 以及最後面6個的資料!
     (extra credit: 每列最右邊多印名次)  
請注意:  
    這題分三個階段繳交: 
     (1)寫出這題的題目與相關範例的研究心得, 至少500字! 至多 1200字!
     (2)不可使用 struct 結構完成這習題,
        練習時間是這週和下週共兩週。
     (3)必須使用 struct 結構完成這習題, 練習時間是下週和下下週, 也是共兩週!

Hint: 
 (1) 資料請用作業區所給的 genscore.c 產生,  (也研究該程式 :-)
     讀取資料請參考 readtest.c  (當然也要研究該程式 :-)
     關於 sorting 請參看所給的其他四個 sorting 範例:
     bbsort.c, selsort.c, inssort.c, 和 myqsort.cpp
 (2) 習題程式請用所給的 hwk11.c 改寫 (可用C或C++);
     ^^^^^^^^^^^^^^^^^^^^^^^^^
 (3) 要使用何種 sorting 技巧隨你高興, 但都須量測出你 sorting 所花的時間。
     ** 關於 Sorting 方法, 除看範例外, 也可用 wikipedia 找各種 sorting,
     例如 bubble sort, Insertion sort, Selection sort 等!
      http://en.wikipedia.org/wiki/Bubble_sort
      http://en.wikipedia.org/wiki/Insertion_sort
      http://en.wikipedia.org/wiki/Selection_sort
 
  除了產生資料的 genscore.c 和 讀取資料範例 readtest.c,
   以及這習題雛形 hwk1213.c 外, 也請參考所給的 ..
  範例 bbsort.c, selsort.c, inssort.c, 以及 myqsort.cpp (C++程式)

***以上所有程式, 以及本檔案, 也可以在備用網站找到: 
   http://www.cs.nctu.edu.tw/~tsaiwn/introcs/03_Labs/Lab11/
 
 *** 一週後會公佈使用 struct 搭配 程式庫函數 qsort( ) 的參考答案
 *** 三週後會公佈沒有用 struct, 且自己寫 sort 函數之參考答案
 *** 四週後會公佈使用 struct 搭配 C++ STL 的 sort 之參考答案
        

__________________________________________________________
以下是由 genscore.c 生出之 studat.txt 的前面 3 lines

9938596     章LUf  76  74  79  98
9934067     趙NLv  72  64  61  94
9947865     魏NEu  86  98  58  90
__________________________________________________________

   01 //hwk1213.c --- sample program to read studat.txt
   02 //========== Originally by tsaiwn@csie.nctu.edu.tw
   03 //====== Modified by student_ID student_Name  _______________
   04 // You have to modify this program to do this Homework
   05 #include <stdio.h>
   06 #include <stdlib.h>
   07 #include <time.h>
   08 #include <math.h>
   09 char* fileName = "studat.txt";  // Data File
   10 long test( );
   11 void sort( ); // your sorting program according to the score
   12 void sort2Print( ); // your another sorting program (照學號)
   13 void print( ); // 用來印出資料, 但只印出一部份!
   14 int main( ) {
   15    long long tStart, tStop;  long i, k, n;
   16    double tRun;
   17    double sum, sumSquare, average, variance, std;
   18    test( );  // 這列以上不准改!
   19    // 打開檔案讀資料到記憶體, 也可寫成 function 在此 call 它 !
   20    // 一邊讀, 一邊算出每個人的學期總成績; 或讀完再算也可以!
   21    // ..注意, 還要算出全部同學的平均 和 標準差
   22    printf("Before sort...\n");
   23    print( ); // 叫用 print( ) 印出部份資料
   24    // todo..  print average, standard deviation
   25    tStart = clock( );
   26    sort( ); // 叫用 你的 sort 程式, 照總成績由高到低
   27    tStop = clock( );
   28    tRun = 1.0*(tStop - tStart)/CLOCKS_PER_SEC;
   29    printf("...Sorting done in %.5f seconds.\n", tRun);
   30    printf("After sort...\n");
   31    print( ); // 叫用 print( ) 印出部份資料
   32    // Extra credit: 要有名次, 同分者比期末考, 再同比期中考, ..
   33    printf("Now, sorting according to Student_ID ...");
   34    sort2Print( ); // 在裡面做照學號由小到大sort, 注意要測時間
   35    fprintf(stderr, "\nHit ENTER key...");
   36    getchar( );
   37    return 0;
   38 }
   39 void print( ) {  // 要用 Global 或是用傳參數的方式自行決定
   40    // 印出前面 6 筆
   41    printf( " ... " );  // 印出 " ..."
   42    // 印出最後 6 筆
   43 }
   44 void sort( ) { // 要用 Global 或是用傳參數的方式自行決定
   45    // insertion sort, selection sort, bubble sort, quick sort ... 
   46    int i, j, k, gg;  // 寫好後請把下列 comment 掉 //
   47    // todo ...
   48    for(i=1;i<=258;++i)for(k=1;k<= 999999;++k) gg= gg*time(0);
   49 }
   50 void sort2Print( ) { // 要照學號由小到大 !
   51    // Ascending order, 記得要量時間 
   52    int i, j, k, gg;  // 寫好後請把下列 comment 掉 
   53    // todo ...
   54    for(i=1;i<=123;++i)for(k=1;k<= 999999;++k) gg= gg*time(0);
   55    // todo ... sort 好之後把量測到的時間印出來
   56    printf("\n === Now already sorted in Student_ID"
   57          " at ascending order.\n");
   58    print( );  // call print( ) to print some data
   59 }
   60 /// do NOT modify the following code
   61 long test( ) {     // 這函數不准改 !
   62     long id; char name[9]; int s1, s2, s3, s4, kk;
   63     char buf[99];
   64     FILE* fp;
   65     fp = fopen(fileName, "rt");   // read, text
   66     if(fp==0) {  // Fail to open it
   67        fprintf(stderr, "File %s NOT found!\n", fileName);
   68        getchar( ); exit(38);  // force to exit with an error
   69     }
   70     fgets(buf, sizeof(buf), fp);  // stdin
   71     if(feof(fp) ) {
   72         fprintf(stderr, "EOF encounted.\n");
   73         return;
   74     }
   75     fprintf(stderr, "Line-1: %s\n", buf);
   76     fgets(buf, sizeof(buf), fp);  // stdin
   77     fprintf(stderr, "Line-2: %s\n", buf);
   78     s1=s2=s3=s4=0;
   79     kk = sscanf(buf,"%ld %s %d %d %d %d", 
   80        &id, name, &s1, &s2, &s3,&s4);
   81     printf("kk=%d\n", kk);
   82     if( kk != 4) printf(" something Wrong with data!\n");
   83     printf("id=%ld  name = %s\n", id, name);
   84     printf("score= %d %d %d %d\n", s1, s2, s3, s4);
   85     fprintf(stderr, " counting..."); fflush(stderr);
   86     kk = 2;  // already read 2 records
   87     while(! feof(fp) ) {   // 只要檔案還沒結束
   88        buf[0] = 0;
   89        fgets(buf, sizeof(buf), fp);
   90        if( feof(fp) ) {  // EOF 也可能有讀到不完整的 Line
   91           if(buf[0] == 0) break;  // 沒有讀到啦
   92        }
   93        ++kk;  // got one record
   94     }
   95     fprintf(stderr, " .. done.\nTotal %d records in file %s\n",
   96        kk, fileName);   // 印到 stderr (螢幕)
   97     fflush(stderr);
   98     fclose(fp); // close the file
   99     return kk;   // total  kk records in the file
  100 } // test(



You are the -th visitors to this page.