本題是浙江理工大學ACM入隊200題第八套中的K題
我們先來看一下這題的題面.
題面
題目描述
任意輸入一個字符,判斷其ASCII是否是奇數,若是,輸出YES,否則,輸出NO;
例如,字符A的ASCII值是65,則輸出YES,若輸入字符B(ASCII值是66),則輸出NO
輸入
輸入為多組測驗資料,
輸入一個字符
輸出
如果其ASCII值為奇數,則輸出YES,否則,輸出NO
樣例輸入
A
樣例輸出
YES
題目分析
這題其實沒有任何難度,但是在acm群里問的還是挺多的,出問題的地方除了對換行的處理以外基本都是不知道在C中如何獲得一個字符的ASCII碼值.說到底是對char型別理解不深刻.
首先科普下什么是ASCII碼(以下內容來自維基百科):
在計算機中,所有的資料在存盤和運算時都要使用二進制數表示,例如,像a、b、c、d這樣的52個字母(包括大寫)以及0、1等數字還有一些常用的符號(例如*、#、@等)在計算機中存盤時也要使用二進制數來表示,而具體用哪些二進制數字表示哪個符號,這就是編碼,如果不同的計算機要想互相通信而不造成混亂,那么每臺計算機就必須使用相同的編碼規則,于是美國有關的標準化組織就推出了ASCII編碼,
ASCII是由美國國家標準學會(American National Standard Institute,ANSI)制定的,使用標準的單位元組字符編碼方案,用于基于文本的資料,方案起始于50年代后期,在1967年定案,它最初是美國的標準,供不同計算機在相互通信時需共同遵守的西文字符編碼標準,現已被國際標準化組織(International Organization for Standardization,ISO)定為國際標準(ISO/IEC 646),適用于所有拉丁字母,
我們知道,在C語言中存盤一個字符的時候,我們使用char型別.但是不知道大家還記不記得,我們討論數值型別的時候,我們也會說到char型別,說它是占用1個位元組的數值型.
那這不矛盾嗎?為啥同一個型別即是數值又是字符呢?
少年,你還是太年輕了,連波粒二象性都有了,區區一個char不能有"二象性"嘛?
在C中,如果你把char當成數值型使用(運算、用%d輸出等),那么它就表現為一個數值,而當你把它作為一個字符型來使用時(作為字串的一部分,用%c輸出等),他就表現為一個字符.
比如如下代碼:
char c = 65;
printf("%c\n", c); // 輸出字符a
printf("%d\n", c); // 輸出數值65(char沒有自己專用格式字符,這里勉強可以用%d)
c = 'a' + 3; // 此處'a'表現為一個整數,值為a的ASCII碼值(65),然后+3,結果為68,存入變數a中
printf("%d\n", c); // 輸出數值68
printf("%d\n", c); // 輸出字符d('d'的ASCII碼為67,所以前面的加法從字符的角度也可以理解成順著ASCII碼表往后第n個字符)
明白了char的這個特殊的"二象性",這題的代碼就很好寫了吧?沒錯,和對一個整數判斷奇偶數一模一樣,因為在取模時char表現為一個整數,而且就是這個字符的ASCII碼值.
常見錯誤
解決完char的問題之后,歡迎來到下一個亂葬崗.
很多朋友按照上面的思路寫完代碼,信心滿滿提交上去,迎頭一個WA,而且通過率還是0%.

不想丸辣!

(^Z是ctrl+Z,表示輸入結束,此時scanf會回傳EOF)
由于例外讀入的回車,導致一次輸入兩次輸出(這個問題在Java中似乎也有,在不使用Scanner物件包裝Systm.in的時候,也會例外讀入輸入結尾的換行)
那怎么解決捏?方法有很多,這邊不展開講了,就說一種最容易的.
在相信很多朋友都已經隱約感受到了,scanf的格式控制字符中,空格似乎不僅僅代表一個空格.事實上,在空格代表的是一個空白字符,空格屬于一個空白字符,啥也沒有也屬于一個空白字符,而換行,也屬于一個空白字符.所以我們可以通過使用" %c"來濾掉空格.
相信會用getchar函式的朋友這個時候要問了,不就是一個換行嘛?換行不就是\n嘛,一個字符,我直接用一個getchar把它讀了不就行了.
思路確實可行,本地跑也是完全沒有問題的,但是這樣提交上去依舊是WA.因為你把換行想簡單了.
實際上,換行不只有\n一種寫法,也可能是\r\n,具體不展開,總之在這題的評測機輸入中,你必須連續呼叫兩次getchar函式才可以讀掉換行,在評測機上AC.但是這會導致你本地跑不了(因為本地換行是\n,具體原因不解釋).所以為什么不在scanf里打一個空格捏?簡單又可行.
這個換行問題在后續還是會碰到的,特別是scanf和gets一起使用的時候.這邊建議有空學一學C++的cin物件,用cin物件即可完美解決換行的問題.不過記得還要學一下怎么關閉cin和scanf的同步,不然代碼的常數會比較大(人話:比較慢).
參考代碼
下面給出了我自己做這道題時候的完整代碼:
(僅作為參考,一定要自己寫一下奧,作弊沒意思,害人又害己)
#include <stdio.h>
int main()
{
char c;
while (~scanf(" %c", &c)) // 利用空格代表空白字符,去掉換行,同時保證沒有換行時代碼也是正確的.看不懂~(按位非)就寫scanf(" %c", &c) != EOF
{
if (c % 2) // 即奇數(養成習慣不要==1,因為負奇數,雖然這里不可能會是負數)
{
printf("YES\n");
}
else // 即偶數
{
printf("NO\n");
}
}
return 0;
}
"正是我們每天反復做的事情,最終造就了我們,優秀不是一種行為,而是一種習慣" ---亞里士多德
這篇題解就到這里了,各位朋友如果有問題歡迎到acm成員群中提問哦!
這里是浙江理工大學22屆ACM集訓隊的成員一枚鴨!
本文首發于博客園,作者:星雙子,除了我自己的轉載請注明原文鏈接:https://www.cnblogs.com/gemini-star/p/zstuACM200_8K.html
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/510910.html
標籤:其他
上一篇:代碼隨想錄第十三天 | 150. 逆波蘭運算式求值、239. 滑動視窗最大值、347.前 K 個高頻元素
下一篇:Petrozavodsk Winter Training Camp 2016: Moscow SU Trinity Contest
