2021年5月23日 星期日

寫C/C++測試題目時如何讀取測資

寫C/C++測試題目時如何讀取測資

tags: 部落格文章

以前寫測試題目的時候最麻煩的第一步就是如何讀測資了

方法有很多cin/cout是最簡單的,但是相對的會比較費時,建議是盡量避開全部都使用 printf 和 scanf。

再來第二個問題是,在本地測試的時候會把測資寫到檔案裡面讀取,但是上傳之後是直接從stdin輸入,導致上傳的時候還要修改一下,

這邊也一併提出解決辦法,整理一下我認為最佳的解法。

說明

先說明如何讀取的代碼

char buff[32];
while (scanf("%s", buff)!=EOF) {
    printf("%s\n", buff);
}

直接用一個while包起來,代碼從裡面開始寫就可以了。

再來是解決上傳修改代碼的問題使用這個函式,可以直接修改scanf讀取檔案,而不是從stdin讀取,這樣代碼就不用修改了

freopen("input.txt", "r", stdin);   // scanf從檔案讀取
freopen("output.txt", "w", stdout); // printf 輸出到檔案

因為函式會略微影響效能,應該有不少人是用define去包起來的

#define ONLINE_JUDGE

#ifndef ONLINE_JUDGE
    if(in) freopen("input.txt", "r", stdin);
    if(out) freopen("output.txt", "w", stdout);
#endif // ONLINE_JUDGE

如此一來只要註解掉第一行的 define 中間代碼就不會被執行了
不過這邊推薦一個更好的方式,用 inline 函式,效果跟 define 是一樣的

inline void debugMode() {
    if(in) freopen("input.txt", "r", stdin);
    if(out) freopen("output.txt", "w", stdout);
}

加上 inline 的意思是,如果函式符合一定的規則(簡單說就是足夠簡單),編譯器會自動把函式打掉,直接開到呼叫的地方。就等於沒有呼叫函式的意思了,所以速度會快一點。

如果有其他需要寫到函式建議都要加上 inline ,可以省下一點點時間。

完整的範例

#include <cstdio>
#include <cstdlib>

inline void debugMode(const char* in, const char* out) {
    if(in) freopen(in, "r", stdin);
    if(out) freopen(out, "w", stdout);
}

int main(int argc,char *argv[]) {
    debugMode("in.txt", NULL); // 輸出保持在終端機

    for (char buff[32]; scanf("%s", buff)!=EOF; ) {
        printf("%s\n", buff);
    }
}

參考

 

沒有留言:

張貼留言