2 条题解
-
4
本题在字符统计的基础上,需要统计汉字,而汉字属于所谓的宽字符.
要处理本题,我们只需要一个头文件
<wchar.h>和它提供的一些新方法.但在此之前,我们需要对本地化环境进行设置,以确保代码在被提交后,能正常的读入汉字.
我们使用头文件
#include <locale.h>并在
main()函数中使用setlocale()方法对本地化环境进行设置(题目的提示中要求本地化环境使用"C.UTF-8"):setlocale(LC_ALL, "C.UTF-8");宽字符的类型为
wchar_t,其中t是type(类型)的意思. 我们首先用其创建一个宽字符串:wchar_t a[1024] = {};宽字符数组的长度只要略大于最长长度(
1000)即可.接下来,我们进行代码主体部分的编写.
读取
题目要求我们读取一行字符串,并限定了其长度(),因此我们考虑使用
fgets的宽字符版本fgetws进行读取.和
fgets一样,fgetws也有三个参数,其结构如下:wchar_t *fgetws(wchar_t *ws, int n, FILE *stream);第一个参数
wchar_t *ws是我们希望往哪个宽字符串中读取数据,第二个参数int n是字符串的最大长度,第三个参数FILE *stream是从哪里读取.我们使用
fgetws进行读入:fgetws(a, 1001, stdin);其中,最长长度设置为
1001是保证在字符串长度为1000时,仍能正常以空字符'\0'结尾. 而stdin则是标准输入流,用于从键盘接收输入.至此,读取部分就结束了.
计数
我们使用四个互相区分的计数变量
int n1 = 0, n2 = 0, n3 = 0, n4 = 0;按照题目中的顺序,它们分别记录中文字符个数、英文字符个数、数字字符个数、其他字符个数.
为了获取读入字符串的长度,我们使用
<wchar.h>提供的另一个类似于strlen()的方法,即wcslen().for (int i = 0; i < wcslen(a); i ++) { }以上
for循环将在输入的宽字符串a中为我们逐位提取字符.在其内部,我们可以开始统计字符了:
首先是汉字,根据题目的提示,汉字的范围可以是
a[i] >= L'一' && a[i] <= L'龟',其中的L用在字符前,表示此字符是一个宽字符. 我们直接使用即可:if (a[i] >= L'一' && a[i] <= L'龟') { n1 ++; }其余字符同理,将其整合后得到:
if (a[i] >= L'一' && a[i] <= L'龟') { n1 ++; } else if ((a[i] >= L'a' && a[i] <= L'z') || (a[i] >= L'A' && a[i] <= L'Z')) { n2 ++; } else if (a[i] >= L'0' && a[i] <= L'9') { n3 ++; } else if (a[i] != L'\n') { n4 ++; }注:在判断其他字符时,为什么要判断
a[i] != L'\n'?这是因为我们不希望将换行符作为有效的能进入计数的字符. 而至于为何不使用换行符作为结尾的标志来提取字符(比如一个一个字符往下找,直到找到L'\n'后判断结束),这是因为我们不知道代码在进行测试时,读入的数据有没有换行符,这同样也是不使用空字符L'\0'作为结尾标志的原因(空字符前会包含字符串内的所有字符,包括那个不确定存不存在的换行符).这就是计数部分的核心代码了.
计数结束后,将其输出即可.
代码
以上就是本题实现的所有细节,完整代码如下(仅供参考,不要直接复制后提交):
#include <stdio.h> #include <locale.h> #include <wchar.h> wchar_t a[1024] = {}; int main() { setlocale(LC_ALL, "C.UTF-8"); fgetws(a, 1001, stdin); int n1 = 0, n2 = 0, n3 = 0, n4 = 0; for (int i = 0; i < wcslen(a); i ++) { if (a[i] >= L'一' && a[i] <= L'龟') { n1 ++; } else if ((a[i] >= L'a' && a[i] <= L'z') || (a[i] >= L'A' && a[i] <= L'Z')) { n2 ++; } else if (a[i] >= L'0' && a[i] <= L'9') { n3 ++; } else if (a[i] != L'\n') { n4 ++; } } printf("%d\n%d\n%d\n%d", n1, n2, n3, n4); return 0; } -
0
在 152520221 刘正潇 同学题解的基础之上进行一些补充:
1.有关读取:
部分同学可能会使用
wscanf(const wchar_t *format, ...)(scanf的变形,适用于宽字符),这种方式会导致部分测试点无法通过,因为测试数据可能包含空格,wscanf在读取字符串时以空格为结束标志,含有空格的字符串将无法完全读入。2.关于for循环:
152520221 刘正潇 同学使用
wcslen()函数读取字符串长度实现循环退出,除此方法以外,判断当前元素是否为'\0'(字符串结尾标识,此处也解释了为什么要定义大于样本数据的数组)实现循环的退出也是可行的,因为在接下来的判断中我们会排除'\n',对计数无影响for (int a=0;i[a]!='\0';a++)3.关于判断类型:
部分同学可能想使用
isdigit()和isalpha()判断数字和字母,此方法不可行,其无法正确判断宽字符(详情自行查阅编码表和函数判断原理),应类比汉字的判断使用区间判定参考代码
注意,本代码仅作参考,强烈不建议复制屎山!!
#include<stdio.h> #include<wchar.h> #include<locale.h> int main() { setlocale(LC_ALL,"C.UTF-8"); int chinese=0,english=0,digit=0,other=0; wchar_t i[1001]; fgetws(i,1001,stdin); for (int a=0;i[a]!='\0';a++) { if (i[a]>=L'a'&&i[a]<=L'z'||i[a]>=L'A'&&i[a]<=L'Z') { english++; } else if (i[a]<=L'9'&&i[a]>=L'0') { digit++; } else if (i[a]>=L'一'&&i[a]<=L'鿿') { chinese++;} else if (i[a]!=L'\n') { other++; } } printf("%d\n%d\n%d\n%d\n",chinese,english,digit,other); return 0; }
- 1
信息
- ID
- 103
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 9
- 标签
- (无)
- 递交数
- 1747
- 已通过
- 132
- 上传者