刷OJ時輸入輸出與字符串


輸入輸出與測試方法

對於剛開始接觸OJ(Online Judge)的同學估計對於OJ的輸入輸出存在疑惑,OJ的輸入輸出基本都是使用標准輸入輸出(也稱標准I/O,即直接讀鍵盤、寫屏幕)。
OJ的判題方式則是使用輸入輸出重定向到文件

./test < data_in > data_out

可執行文件test中使用標准輸入輸出,data_in是輸入文件,data_out是輸出文件,最后將test的輸出data_out與答案文件比對判斷程序是否運行正確。
我們在測試自己的程序時,可以在代碼里加入重定向語句來方便測試,但是必須注意:自我測試完畢之后刪除重定向語句,再提交代碼。
代碼里重定向方法:

#define LOCAL //在提交代碼時注釋掉

#include<stdio.h>

int main(){
#ifdef LOCAL
    freopen("data.in", "r", stdin);//將data.in改為輸入文件路徑
    freopen("data.out", "w", stdout);//將data.out改為輸出文件路徑
#endif

    return 0;
}

隨后,正常使用C/C++的標准輸入,都會定向到上述兩個文件中,以便於自測代碼。

字符串

C語言中的字符串就是字符數組,處處受限。例如,如何編寫一個函數,把兩個字符串拼接成一個長字符串?
這個任務看上去簡單,實際上卻暗藏陷阱:新字符串的存儲空間從哪里來?
不能在函數中定義一個數組然后返回它的地址,因為函數返回后其中局部變量的地址便失效了。因此“字符串拼接”函數必須申請新的內存空間以存放結果,用完之后還要將申請的空間“退回去”,這會很麻煩。另外,字符串數組本身並不保存字符串長度,每次需要時都要用strlen函數重算一次。如果字符串很長,則strlen函數的開銷將不容忽視。
為了避免不必要的strlen調用,可以在某個變量中保存字符串的長度,但這樣一來,程序會變得更加復雜,難以調試。總而言之,C語言處理字符串並不方便。
C++提供了一個新的string類型,用來替代C語言中的字符數組。用戶仍然可以繼續用字符數組當字符串用,但是如果希望程序更加簡單、自然,string類型往往是更好的選擇。例如,C++的cin/cout可以直接讀寫string類型,卻不能讀寫字符數組;string類型還可以像整數那樣“相加”,而在C語言里只能使用strcat函數。
C++在string頭文件里定義了string類型,直接支持流式讀寫。
string有很多方便的函數和運算符,但速度有些慢。考慮這樣一個題目:輸入數據的每行包含若干個(至少一個)以空格隔開的整數,輸出每行中所有整數之和。如果只能使用字符與字符數組,一般有兩種方案:一是使用getchar( )邊讀邊算,代碼較短,但容易寫錯,並且相對較難理解;二是每次讀取一行,然后再掃描該行的字符,同時計算結果。如果使用C++,代碼可以很簡單。

#include<iostream>
#include<string>
#include<sstream>

using namespace std;

int main() {
    string line;

    while(getline(cin, line)) {
        int sum = 0, x;
        stringstream ss(line);

        while(ss >> x) sum += x;

        cout << sum << "\n";
    }

    return 0;
}

string類在string頭文件中,而stringstream在sstream頭文件中。首先用getline函數讀一行數據(相當於C語言中的fgets,但由於使用string類,無須指定字符串的最大長度),然后用這一行創建一個“字符串流”——ss。接下來只需像讀取cin那樣讀取ss即可。
可以把string作為流進行讀寫,定義在sstream頭文件中。
對於字符串的操作請盡量使用C++提供的string方法!
思考:如果輸入數據不是以空格進行分隔的,是特殊字符如*、|等怎么處理?

只需掃描整個字符串,將特殊字符全部替換成空格即可

注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com