本文轉自互聯網,內容、排版有修正。ios
歡迎和你們交流技術相關問題:
郵箱: jiangxinnju@163.com
博客園地址: http://www.cnblogs.com/jiangxinnju
GitHub地址: https://github.com/jiangxincode
知乎地址: https://www.zhihu.com/people/jiangxinnjuc++
在ACM程序設計競賽中,一道題目的全部測試數據是放在一個文本文件中,選手將一道題目的程序提交給評判系統運行,程序從該文件中讀取測試數據,再把運行結果輸出到另外一個文本文件中。系統把輸出文件與標準答案比對,來評判程序編寫得正確與否。ACM現場賽採用的輸入輸出形式有(1)文件輸入、標準輸出;(2)文件輸入、文件輸出;(3)標準的輸入輸出。而Web形式的ACM程序設計在線評判系統通常採用標準的輸入輸出,但輸入結束有文件末尾標識(EOF),這能夠用於肯定輸入結束。git
示例:整數求和
http://acm.njupt.edu.cn/acmhome/problemdetail.do?&method=showdetail&id=1001github
C語法:數組
#include <stdio.h> int main() { int a,b; scanf("%d %d",&a, &b); printf("%d\n",a+b); }
注意:輸入前不要打印提示信息。輸出完畢後當即終止程序,不要等待用戶按鍵。函數
C++語法:測試
#include<iostream> using namespace std; int main() { int a ,b; cin>>a>>b; cout<<a+b<<endl; return 0; }
示例:A + B Problem (1)
http://acm.njupt.edu.cn/acmhome/problemdetail.do?&method=showdetail&id=1084spa
C語法:設計
#include <stdio.h> int main() { int a,b; while (scanf("%d %d",&a, &b) != EOF) printf("%d\n",a+b); }
說明:scanf函數返回值就是讀出的變量個數,如:scanf( 「%d %d」, &a, &b );若是隻有一個整數輸入,返回值是1,若是有兩個整數輸入,返回值是2,若是一個都沒有,則返回值是EOF。EOF是一個預約義的常量,等於-1code
C++語法:
#include<iostream> using namespace std; int main() { int a ,b; while (cin>>a>>b) cout<<a+b<<endl; return 0; }
cin是一個對象,表達式cin >> m >> n在讀入發生錯誤返回0,不然返回cin的地址。
示例:A + B Problem (2)
http://acm.njupt.edu.cn/acmhome/problemdetail.do?&method=showdetail&id=1085
C語法:
#include <stdio.h> int main() { int a,b; while(scanf("%d %d",&a, &b) &&(a||b)) printf("%d\n",a+b); }
C++語法:
#include<iostream> using namespace std; int main() { int a ,b; while(cin>>a>>b&&(a||b)) {cout<<a+b<<endl;} return 0; }
示例:A + B Problem (3)
http://acm.njupt.edu.cn/acmhome/problemdetail.do?&method=showdetail&id=1086
C語法:
#include<stdio.h> int main() { int a ,b,n; scanf("%d",&n); while(n--) { scanf("%d %d",&a, &b); printf("%d\n",a+b); } return 0; }
C++語法:
#include<iostream> using namespace std; int main() { int a ,b,n; cin>>n while(n--) { cin>>a>>b; cout<<a+b<<endl; } return 0; }
對字符串的輸入分三種狀況:
這種狀況,用scanf("%s",str)是再好不過的了,好比,測試數據中只有兩個字符串:abc def。要讀入abc與def,能夠這樣寫:
char str1[1000], str2[1000]; scanf("%s%s", str1, str2);
對於這種狀況,scanf("%s",str)無能爲力,由於scanf用空格、製表符及回車做爲字符串的分界符。對於一個含有空格、製表符及回車的字符串,若是用scanf("%s",str)來讀,將讀到若干個字符串,這個字符串被scanf分開了。能夠用另一個函數gets。gets函數用回車做爲字符串的分界符,好比,有如下的一個字符串:Hello world!
。要讀入這個字符串,這樣寫:
char str[1000]; gets(str);
這樣,str的內容就是"Hello world!"了。另外,gets返回NULL表示出錯或end of file。
在這種狀況下,若是沒有題目的說明,程序沒法知道哪裏是字符串的分界。那麼,用scanf("%c",&ch)來讀,一邊讀,一邊判斷分界條件是否知足,若是知足,則把當前讀到的東西存到一個字符串中。
在初次接觸ACM程序設計競賽時,可能認爲:樣例中都是輸入數據和輸入數據在一塊兒,輸出結果和輸出結果在一塊兒,可能會開個數組,把每組的結果存起來,等輸入完了再一塊兒輸出。當遇到不知有多少組測試數據的題,就難以處理了。其實在ACM程序設計競賽中,輸入數據和輸出數據是分別在兩個不一樣的文件中進行的,程序的輸入和輸出是相互獨立的,因此讀入一組數據就輸出一組結果,跟先讀入全部數據再輸出全部的結果,效果是徹底同樣的。所以,每當處理完一組測試數據,就應當按題目要求進行相應的輸出操做。而沒必要將全部結果儲存起來一塊兒輸出。在處理輸出時,通常要注意:每行輸出均以回車符結束,包括最後一行。
不少題目都要求在輸出數據的恰當位置加空行。一個空行就是一個單獨的"\n"。這裏,有的題目說:「After each test case, you should output one blank line」,而有的題目說:「Between each test case, you should ouput one blank line」。要注意After和Between的區別,由於若是多了一或少了空行,將致使Presentation Error甚至Wrong Answer。
(1)After
這種狀況最簡單,只須要輸出結果後,再加一個printf("\n")或puts("")就好了,就像這樣:
int i; for (i = 0; i < 10; i++) { printf("%d\n", a); printf("\n"); }
示例:A + B Problem (4)
http://acm.njupt.edu.cn/acmhome/problemdetail.do?&method=showdetail&id=1087
C語法:
#include<stdio.h> int main() { int n,sum,a; while(scanf("%d",&n) && n) { sum=0; while(n--) { scanf("%d",&a); sum+=a; } printf("%d\n",sum); printf("\n"); } return 0; }
C++語法:
#include<iostream> using namespace std; int main() { int n,sum,a; while(cin>>n&&n) { sum=0; while(n--) { cin>>a; sum+=a; } cout<<sum<<endl; cout<<endl; } return 0; }
(2)Between
Between和After不一樣的是,最後一組結果後面不該該再加單獨的"\n",應該像這樣:]
int i; for (i = 0; i < 10; i++) { printf("%d\n", a); if (i != 9) printf("\n"); }
因爲有時候咱們並不知道測試數據有幾組(好比測試數據是以end of file 結束的),用上面的方法就不行了,因而,能夠換一種寫法:
int a; bool bFirst = true; while (scanf("%d", &a) == 1) { if (!bFirst) puts(""); else bFirst = false; printf("%d\n", a); }
這樣,從第二組測試數據起,在輸出每組測試數據的結果以前就會輸出一個空行,和想要的效果是同樣的。
這種狀況與空行的狀況至關類似,處理方法也是同樣的,只不過把"\n"改爲相應的分隔符就好了。
有些題目要求輸出這樣的字符串:abc*****de****f
,其中「*」表明空格。
要求是這樣的:str1在前5個字符中左對齊,str2在第6到第10個字符中右對齊,str3在第11到第15個字符中右對齊。
可行的作法是,先初始化一個數組,用' '(空格)填充,再在相應的位置填相應的內容。用程序來表述:
01:char str[1000]; 02:char str1[] = "abc", str2[] = "de", str3[] = "f"; 03:memset(str, ' ', 1000 * sizeof(char)); 04:sprintf(str, "%s", str1); 05:str[strlen(str1)] = ' '; 06:sprintf(str + 5, "%5s", str2); 07:str[10] = ' '; 08:sprintf(str + 10, "%5s", str3); 09:str[15] = '\0'; 10:puts(str);
關鍵的部分:
(1)在調用sprintf後,要清除不恰當字符串結束符(第5,7行);
(2)在恰當的位置添加字符串結束符(第9行)。
首先要考慮的是數組是按行排列仍是按列排列,若是是按行排列,就應該這樣寫:
int i, j; 01: for (i = 0; i < nRow; i++) 02: { 03: for (j = 0; j < nCol; j++) { if (j > 0) printf(" "); printf("%d", a[j]); } puts(""); }
若是是按列,就要把1行和3行交換。
在一些模擬題中,題目要求輸出一幅畫,只不過這個畫是由字符組成的。對於這種狀況,能夠採用和帶格式的字符串輸出類似的方法,先開一個字符數組(在這裏,是二維數組),而後把數組當成屏幕輸出,屏幕的(i, j)點就是數組的(i, j)號元素。最後,輸出這個二維數組就好了。通常來講,能夠輸出一個二維字符數組的方法和輸出通常數組的方法是同樣的,用雙重循環來作。不過,能夠只用一個循環就能夠了,緣由是在數組每行的恰當位置(通常是末尾)加了一個'\0',那麼,數組的每一行就成了一個字符串,因而,輸出程序就變成了:
int i; char str[100][100]; ... for (i = 0; i < nRow; i++) puts(str);