题目传送门: TOJ 1812

题目是一个字符串处理问题,就是统计一个文章中出现频率最高的词汇。

看了别人的代码,感觉其中scanf过滤字符串的方法非常巧,在字符串处理问题中应会非常有用,mark之。

Code

TOJ 1812
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
//By Brickgao
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <map>
using namespace std;

map<string, int> rec;
typedef map<string, int>::iterator it_t;
char *tmp1 = "%[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz]";
char *tmp2 = "%[^ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz]";
char s[1024];

int main()
{
while(!feof(stdin))
{
while(scanf(tmp1, s) > 0)
{
for(int p = 0; s[p]; p++) s[p] = tolower(s[p]);
++rec[s];
}
while(scanf(tmp2, s) > 0);
}
int ans = 0;
for(it_t i = rec.begin(); i != rec.end(); i++)
ans = max(ans, i -> second);
printf("%d occurrences\n", ans);
for(it_t i = rec.begin(); i != rec.end(); i++)
if(i -> second == ans)
puts(i -> first.c_str());
return 0;
}

###解释

关于scanf的这个用法的解释(摘自:http://caterpillar.onlyfun.net/Gossip/CGossip/PrintfScanf.html)

scanf()還可以指定可接受的字元集合,例如若只想接受1到5的字元,則可以如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdio.h>

int main(void) {
char str[50];

printf("請輸入1到5的字元:");
scanf("%[1-5]", str);
printf("輸入的字元為 %s\n", str);

fflush(stdin); // 清除輸入緩衝區

printf("請輸入XYZ任一字元:");
scanf("%[XYZ]", str);
printf("輸入的字元為 %s\n", str);

return 0;
}

str為C語言中的字串(字元陣列),scanf()函式連續讀入符合集合的字元並放到字元陣列中,直到讀到不符合的字元為止,剩下的字元仍會存在輸入緩衝區中,可以直接使用fflush(stdin)清除輸入緩衝區,以利進行下一次重新輸入,scanf()函式若接受字元,則傳回所接受的字元數,否則直接略過輸入而傳回0,在您學會流程控制語法之後,可以據以判斷該作什麼處理(像是使用if來針對不接受輸入時的處理)。

執行結果如下:

1
2
3
4
請輸入1到5的字元:146731
輸入的字元為 14
請輸入XYZ任一字元:XYZXDX
輸入的字元為 XYZX

您可以使用%[0-9]指定取得0至9的字元,使用%[A-z]指定取得ASCII表中的A到z的字元,如果要排除的話,則使用^,例如%[^ABC]會取得ABC字元以外的所有字元。