Skip to content

Instantly share code, notes, and snippets.

@amoshyc
Last active August 29, 2015 14:08
Show Gist options
  • Save amoshyc/a6fda37bc010b66afe53 to your computer and use it in GitHub Desktop.
Save amoshyc/a6fda37bc010b66afe53 to your computer and use it in GitHub Desktop.
uva10008tutor_1.c
/*
uva 10008 這題應該不是目前學到的知識可以解的……
於是我出來幫助大家了
這份教學分為三個部分(整行讀入(這題不一定要用到)、資料儲存、排序),你必需知道什麼是函式才讀得懂以下內容。
*/
/*
第一部分:整行讀入。強列建議使用 fgets。
之前的教學有大約地寫出來,但有很多細節沒講。
請先閱讀以下關於 scanf 的細節:
※ Whitespace character:
the function will read and ignore any whitespace characters encountered
before the next non-whitespace character (whitespace characters include
spaces, newline and tab characters -- see isspace). A single whitespace
in the format string validates any quantity of whitespace characters
extracted from the stream (including none).
※ Non-whitespace character, except format specifier (%):
Any character that is not either a whitespace character (blank, newline or tab)
or part of a format specifier (which begin with a % character) causes the function
to read the next character from the stream, compare it to this non-whitespace
character and if it matches, it is discarded and the function continues with the
next character of format. If the character does not match, the function fails,
returning and leaving subsequent characters of the stream unread.
來源:http://www.cplusplus.com/reference/cstdio/scanf/
看完你應該知道為什麼我們不用 scanf("%s", ...) 就好了,因為這樣寫遇到空白就停了。
我之前有提到,整行輸入我們可以用 scanf("^[\n]", ...) 來讀入。
跟 scanf("%d", ...) 混用時必需極為小心。
考慮以下測資:
3
a b
b c
c d
電腦看到的事實上是
3\na b\nb c\nc d
用以下程式讀入時,會產生錯誤:*/
int N;
scanf("%d", &N);
while (N--) {
char input[3+1]; /*宣告一個保證可以存下最長長度的字串*/
scanf("%[^\n]", input);
}
/*因為 scanf("%d", &N) 會移留 \n unread。
所以當你用 scanf("%[^\n]", input) 時,會從 \n 開始讀,所以讀到「空字串」,而不是預期的 "a b"。
scanf("%[\n]", input) 也會移留 \n unread,所以同樣問題發生在第二次、第三次迴圈。
解決方法這樣寫:*/
int N;
scanf("%d\n", &N);
while (N--) {
char input[3+1];
scanf("%[^\n]\n", input);
}
/*這樣就會強迫 scanf 把 \n 吃掉。
另外,有一點必需注意! scanf("%[^\n]", ...) 這種寫法在 windows 下「手動輸入測資」時會發生問題,原因我也不曉得。
解決方法是利用測資檔案。(以下是在 win7 測試,我沒有 win8,不知是不是也一樣)
1. 在與你程式的執行檔同樣的目錄,建立一個文件 input.txt,裡面有測資內容。
2. 開啟 cmd.exe,然後 cd 到上一步驟的目錄
(你也可以開啟檔案瀏覽器(就是「我的電腦」),移動到該目錄,然後在上方的「地址列」,刪除所有文字,然後輸後 cmd,按 Enter)
然後執行:
(執行檔檔名) < input.txt
程式的輸出就會顯示出來。
舉例:
程式是:*/
#include <stdio.h>
#include <stdlib.h>
int main() {
int N;
scanf("%d\n", &N);
while (N--) {
char input[3+1];
scanf("%[^\n]\n", input);
printf("Read: %s\n", input);
}
return 0;
}
/*執行檔是
在 D:\temp 的 main.exe
在 D:\temp 下建立文件 input.txt,內容為
3
a b
b c
c d
然後
D:\temp>main.exe < input.txt
Read: a b
Read: b c
Read: c d
這樣就成功了。
另外你也可以用 fgets 來寫,fgets 讀入時會把 \n 吃掉,但得到的字串最後也有 \n,
一般情況下,我們是不需要這個 \n 的,所以我們可以把它換成 \0,我們把 \0 提前了,相當於刪掉字串的最後一個字元。
但有些測資的最後一行讀入後,最後並沒有 \n,
例如:
test
test
兩種測資,第二種沒有換行符號,讀入時,得到的字串也不會有。所以我們加入一個 if 來處理這個情況。
注意,fgets 在成功讀入時,會自動加一個 \0 到陣列(你丟的參數)裡,所以陣列的長度要比預期的加 2(\n,\0)
整個程式碼片斷:*/
int N;
scanf("%d\n", &N);
while (N--) {
char input[10+1]; /*宣告一個保證可以存下最長長度的字串*/
fgets(input, 11, stdin);
int len = strlen(input);
if (input[len-1] == '\n') {
input[len-1] = '\0';
len--; /*下次需要字串長度時可以直接用 len,不用再 strlen(input) 一次。*/
}
printf("%s\n", input);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment