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