Lab 2-1: Using cin/cout, fstream, 與 namespace

 
實習目標 1. 使用 ios, iostream, fstream 類別物件所提供的輸出入功能
2. 使用 C++ 標準輸出入函式庫中所提供物件的界面
3. 熟悉透過物件界面描述物件功能的抽象化描述物件的方法
 
步驟一 請找出上個星期實習課程所得到的程式, 修改其中的 printf() 敘述, 使用 cout, 以及 I/O manipulator 完成相同的 Console 輸出功能, 修改其中的 scanf() 敘述, 使用 cin 來完成相同的 Console 輸入功能, 請一步一步地編譯, 執行, 並檢查結果

如果你擔心一次通通改好再編譯, 執行會發生很多錯誤的話, (尤其是你現在還不太熟悉 cin 和 cout 的用法,) 你可以一點一點地修改, 修改一個敘述以後就立刻編譯, 執行, 檢查結果 (檢查結果是否正確的工作如果能夠交給 assert 敘述就好了, 想一想這該怎麼做? 助教會問你!!)

請注意 stdio 和 iostream 共用時應該要在 main() 函式一開始的時候呼叫 std::ios::sync_with_stdio() MSDN Lib , cplusplus reference , 以避免 iostream 和 stdio 各用各的緩衝區的問題, 最後的目標是完全用 iostream 函式庫來達成原來程式的功能 (這個函式只需要在 main() 開始執行時呼叫一次就夠了, 等到你通通改完以後在把他刪除)

另外, 你也許會有一個疑問, 就是為什麼不把 cin 和 cout 所有的用法都完整交代清楚以後再叫你練習, 這樣子不是有點浪費時間? OOXZX )*(&(*^%...

  1. 想要看完整的 cin 和 cout 的用法的同學請參考MSDN Library (或是 cplusplus), 例如你要查 cin 用法的話應該要查 MSDN:Input Streams (cplusplus cin ), 要查 cout 用法的話應該要查 MSDN:Output Streams (cplusplus cout)

  2. 看過以後你有可能會覺得更無助, 怎麼東西那麼多, 那麼複雜

  3. 我想在這裡也許你可以練習一下怎樣投射你以前已經累積的經驗吧!!

你在寫 C 程式的時候每次都有用到螢幕和鍵盤輸出入的功能, 你應該知道基本上能夠有什麼功能, cin 和 cout 一定都可以提供你想要的功能, 對照你到目前為止上課所看到的範例, 還有你在 MSDN Library (或是cplusplus reference) 裡所查到的資料, 你就可以迅速地開始使用 cin 和 cout 了, 至於其它 cin 和 cout 中你不曉得的功能的話, 不要太貪心嘛..., 暫時先忽略一些細節吧, 非用不可的時候你自然會去找到!!

步驟二

C++ 標準函式庫 fstream 中基本檔案存取功能的範例如下:

    #include <fstream>
    #include <string>
    using namespace std;

    ifstream in("Scopy.cpp");   // 開啟輸入檔案
    if (!in)    // 檢查檔案是否開啟成功 或使用 if (!in.is_open())
    {
        cerr << "fail in opening Scopy.cpp for reading";
        exit(1);
    }
    ofstream out("Scopy2.cpp"); // 開啟輸出檔案
    if (!out) 
    {
        cerr << "fail in opening Scopy2.cpp for writing";
        exit(1);
    }

    string s;
    while (getline(in, s)) // delimiter '\n' deleted automatically
        out << s << "\n";

上面這個範例做的事情是開啟 Scopy.cpp檔案為讀取串流 in, 開啟 Scopy2.cpp 檔案為輸出串流, 以 while 迴圈一列一列讀取 Scopy.cpp內的資料,寫到 Scopy2.cpp 裡; 也就完成了簡單的文字檔案拷貝的功能


C++ 語法裡面提供一種新的錯誤處理機制: 例外處理 (exception) - try, catch, throw, 請參考上課投影片, 改進使用 C 語法的 if 來處理錯誤, 使得程式的維護容易, 閱讀起來都簡潔得多, 目前我們先用你比較熟悉的方法, 以後我們再練習新的語法

請注意上面這段程式是運用 string::getline() 函式由檔案串流 in 中依序讀取 字串 到 s 這個 string 型態 (成員函式) 的變數(物件)中, 由於檔案和鍵盤在 iostream / fstream 函式庫中都看成是資料串流, 所以由檔案中讀取數字的方法和由鍵盤讀取數字的方法是一樣的, 例如:

  int x;
  double y;
  in >> x >> y;

繼續步驟一的修改, 程式中 ReadFile() 函式使用 stdio 中的檔案輸入函式, 請將其改為使用 ifstream 來完成相同的檔案輸入功能 , 例如:

你在 ReadFile(int *dataSize, int data[]) 函式中看到

gets(filename);

請註解掉, 換成

//gets(filename);
cin >> filename; // 由鍵盤讀取資料到 filename 字元陣列變數中

因為你用到 cin
所以在檔案最前面加上

#include <iostream>
using namespace std;

看到

FILE *fp;
fp = fopen(filename, "rt");

請註解掉, 換成

//FILE *fp;
//fp = fopen(filename, "rt");
ifstream infile(filename);

因為你用到 ifstream
所以在檔案最前面加上

#include <fstream>
using namespace std;

看到

fscanf(fp, "%d", dataSize);

請註解掉, 換成

//fscanf(fp, "%d", dataSize);
infile >> *dataSize;

...

 

使用 printf 時, 我們會用 printf("%4d\n", x);
來控制印出時只有四格, 換成 iostream 時
你須要使用

#include <iomanip>
using namespace std;

cout << setw(4) << x << "\n";

請參考 cpluscplus setw

步驟三 如果我現在有一個新的資料檔案 raw4.dat, 檔案內容的格式稍微修改如下:
99   number of data item
6    first item
7    second item
8       the score
9   ...
8
每一筆資料都在一列上, 但是後面有一些文字的註解, 在資料後會有至少一格的空白字元來區隔, 請修改 ReadFile(...) 函式來讀取新的資料檔案格式

提示: 試看看 infile >> data; infile.getline(buf, sizeof(buf)); 或是 infile >> data; infile.ignore(80, '\n'); // 跳過 80 個字元或是跳過到達 '\n' 前的所有字元 瞭解為什麼要這樣寫以後 (線上查一下 cpluscplus), 自己嘗試看看, 這段程式所使用到的變數要自己定義喔?!?!

步驟四

請再製作一個 WriteFile(...) 函式將剛才由 raw4.dat 檔案內讀到的資料, main() 裡面的 dataSize 變數和 data[100] 陣列變數, 依照舊的資料格式 (raw1.dat, raw2.dat, raw3.dat 的格式) 寫到 raw4a.dat 中

1. 在 io.cpp 裡定義一個 WriteFile 函式, 接受 int dataSize 和 int data[] 型態的兩個參數

2. 在 WriteFile 函式裡面
a. 開啟輸出的檔案串流 ofstream outfile("raw4a.dat");
b. 輸出 dataSize
outfile << dataSize << '\n';
c. 寫一個迴圈輸出 data[] 陣列裡每一個元素

步驟五 請助教檢查後, 將所完成的 專案 (只需保留 .cpp, .h, .sln 以及 .vcxproj 檔案即可; 刪除掉 .suo, .sdf, .filters, .users, debug\ 資料匣, 以及 ipch\ 資料匣下的所有內容) 以 zip/rar/7zip 程式將整個資料匣壓縮起來, 登入上傳網頁, 選擇 Lab2-1, 後面的實習課程可能需要使用這裡所完成的程式

C++ 物件導向程式設計課程 首頁

製作日期: 03/06/2013 by 丁培毅 (Pei-yih Ting)
E-mail: [email protected] TEL: 02 24622192x6615
海洋大學 電機資訊學院 資訊工程學系 Lagoon