1. 主页
  2. 文档
  3. Level2题解(1-10)
  4. 第8课 字符数组应用

第8课 字符数组应用

字符

c++ 中单引号来表明一个字符, 其数值大小就是该字符对应的ASCII码.

定义:

char a;
char a = 'a';

例题:

P5733 【深基6.例1】自动修正

  • 题目描述

大家都知道一些办公软件有自动将字母转换为大写的功能。输入一个长度不超过 100 且不包括空格的字符串。要求将该字符串中的所有小写字母变成大写字母并输出。

  • 输入格式

  • 输出格式

  • 输入输出样例
    • 输入 #1复制Luogu4!
    • 输出 #1复制LUOGU4!
  • 参考答案
#include <iostream>
using namespace std;

char a;

int main()
{
 while(cin >> a) {
  if(a >= 'a' && a <= 'z')
   a = a - 'a' + 'A';
  cout << a;
 }

 return 0;
}

字符数组

字符数组是存放字符型数据的数组.

定义和初始化:

char ch[100] = {‘a’, ‘b’, ‘c’,};

字符串

定义: 用双引号”” 括起来的0个或者多个字符组成的序列. 如”hello”

串长: 串中字符的个数。

空串: 零个字符的串, 串长为0。

字符串定义和初始化

  • char a[20] = {“hello”};
  • char a[20] = “hello”;
  • char a[20] = {‘h’, ‘e’,’l’, ‘l’, ‘o’, ‘\0’};

下面赋值行吗?

  • char a[20]; a=”hello”; XXX错误,a数数组名是字符常量.

//定义之后初始化

char a[20];
a[0]='a';  a[1]='b';  a[2]='c'; a[3]='r';

思考:

‘a’ 和 “a”的区别?

字符串结束的标志

字符串结束的标志 ‘\0’

例如上面的字符串”hello”, 5个字符但是需要6个字符空间来存储.

此图像的alt属性为空;文件名为sf08-1024x230.png

通常我们关心的不是字符数组的大小,而是字符串的有效长度,所谓有效长度,是指字符串字符的个数。

字符串的输入输出

  • 不含空格
char a[100];
scanf("%s", a);
cin >> a;
  • 含空格输入
char a[100];
fgets(a, sizeof(a), stdin);
cin.getline(a, 100);
  • 字符读入
char a[20];
a[i] = getchar();
a[i] = cin.get();
  • 字符串输出
char a[20];
printf("%s", a);
cout << a;

例题:

字P5015 标题统计

  • 题目描述

凯凯刚写了一篇美妙的作文,请问这篇作文的标题中有多少个字符?注意:标题中可能包含大、小写英文字母、数字字符、空格和换行符。统计标题字符数时,空格和换行符不计算在内。

  • 输入格式

输入文件只有一行,一个字符串 s。

  • 输出格式

输出文件只有一行,包含一个整数,即作文标题的字符数(不含空格和换行符)。

  • 输入输出样例2343Ca 454
    • 输出 #2复制
    • 输入 #2复制
    • 输出 #1复制
    • 输入 #1复制
  • 说明/提示标题中共有 3 个字符,这 3 个字符都是数字字符。标题中共有 5 个字符,包括 1 个大写英文字母, 1 个小写英文字母和 2 个数字字符, 还有 1 个空格。由于空格不计入结果中,故标题的有效字符数为 4 个。
    • 【输入输出样例 2 说明
    • 输入输出样例 1 说明
  • 【数据规模与约定】

规定 |s| 表示字符串 s 的长度(即字符串中的字符和空格数)。

对于 40% 的数据,1≤∣s∣≤5,保证输入为数字字符及行末换行符。

对于 80% 的数据,1≤∣s∣≤5,输入只可能包含大、小写英文字母、数字字符及行末换行符。

对于 100% 的数据,1≤∣s∣≤5,输入可能包含大、小写英文字母、数字字符、空格和行末换行符。

  • 参考代码
#include <bits/stdc++.h>
using namespace std;

int ans;
char a;

int main()
{
 while((a=getchar())!= '\n') {
  if(a >= 'a' && a <= 'z')
   ans++;
  else if(a >= 'A' && a <= 'Z')
   ans++;
  else if(a >= '0' && a <= '9')
   ans++;
 }

 printf("%d", ans);
 return 0;
}

P1125 笨小猴

  • 题目描述

笨小猴的词汇量很小,所以每次做英语选择题的时候都很头疼。但是他找到了一种方法,经试验证明,用这种方法去选择选项的时候选对的几率非常大!

这种方法的具体描述如下:假设maxn是单词中出现次数最多的字母的出现次数,minn是单词中出现次数最少的字母的出现次数,如果maxn-minn是一个质数,那么笨小猴就认为这是个Lucky Word,这样的单词很可能就是正确的答案。

  • 输入格式

一个单词,其中只可能出现小写字母,并且长度小于100100。

  • 输出格式

共两行,第一行是一个字符串,假设输入的的单词是Lucky Word,那么输出“Lucky Word”,否则输出“No Answer”;

第二行是一个整数,如果输入单词是Lucky Word,输出maxn-minn的值,否则输出00。

  • 输入输出样例
  • 输入 #1复制

error

  • 输出 #1复制
Lucky Word
2
  • 输入 #2复制

olympic

  • 输出 #2复制
No Answer
0
  • 说明/提示

【输入输出样例1解释】

单词error中出现最多的字母r出现了3次,出现次数最少的字母出现了1次,3-1=2,2是质数。

【输入输出样例2解释】

单词olympic中出现最多的字母i出现了1次,出现次数最少的字母出现了1次,1-1=0,0不是质数。

  • 分析
  1. 质数判断
  2. 字母出现次数统计
#include <bits/stdc++.h>
using namespace std;

char word[108];
int a[26];
int maxn = 1, minn = 1, n;

bool isprime(int n)
{
 if(n < 2)
  return false;

 for(int i=2; i*i <=n; i++) {
  if(n % i == 0)
   return false;
 }

 return true;
}

int main()
{
 int i;

 scanf("%s", word);
 int len = strlen(word);

 for(i = 0; i < len; i++) {
  a[word[i] - 'a']++;
 }

 sort(a, a+26);

 i = 0;
 while(a[i] == 0) {
  i++;
 }

 minn = a[i];
 maxn = a[25];

 n = maxn - minn;

 if(isprime(n)) {
  printf("Lucky Word\n%d", n);
 } else {
  printf("No Answer\n%d", 0);
 }

 return 0;
}


常用字符串函数介绍

  • strcpy函数

char *strcpy(char *dest, const char *src)

把 src 所指向的字符串复制到 dest。

  • strncpy函数

char *strncpy(char *dest, const char *src, size_t n)

  • strcat函数

char *strcat(char *dest, const char *src)

把 src 所指向的字符串追加到 dest 所指向的字符串的结尾。

  • strlen函数

size_t strlen(const char *str)

计算字符串 str 的长度,直到空结束字符,但不包括空结束字符。

  • strcmp函数

int strcmp(const char *str1, const char *str2)

把 str1 所指向的字符串和 str2 所指向的字符串进行比较。

如果返回值 < 0,则表示 str1 小于 str2。

如果返回值 > 0,则表示 str1 大于 str2。

如果返回值 = 0,则表示 str1 等于 str2。

  • strncmp函数

int strncmp(const char *str1, const char *str2, size_t n)

把 str1 和 str2 进行比较,最多比较前 n 个字节。返回值同strcmp

  • strchr 函数

char *strchr(const char *str, int c)

在参数 str 所指向的字符串中搜索第一次出现字符 c(一个无符号字符)的位置。

  • strstr函数

char *strstr(const char *haystack, const char *needle)

stdlib 库中的函数

  • double atof(const char *str)

把参数 str 所指向的字符串转换为一个浮点数(类型为 double 型)。

  • int atoi(const char *str)

把参数 str 所指向的字符串转换为一个整数(类型为 int 型)。

  • long int atol(const char *str)

把参数 str 所指向的字符串转换为一个长整数(类型为 long int 型)。

  • double strtod(const char *str, char **endptr)

把参数 str 所指向的字符串转换为一个浮点数(类型为 double 型)。

  • long int strtol(const char *str, char **endptr, int base)
  • 把参数 str 所指向的字符串转换为一个长整数(类型为 long int 型)。

str — 要转换为长整数的字符串。

endptr — 对类型为 char* 的对象的引用,其值由函数设置为

str – 中数值后的下一个字符。

base — 基数,必须介于 2 和 36(包含)之间,或者是特殊值 0。

sscanf 和 sprintf

sscanf:

  • int sscanf(const char *s, const char *format,..);
  • int scanf(const char *format,…);

sscanf与scanf等价,所不同的是,前者的输入字符来源于字符串s,而scanf以stdin作为输入源。

sprintf():

  • int sprintf(char *buffer, const char *format [, argument] … );
  • int printf(const char *format [, argument] … );

printf 和 sprintf 都使用格式化字符串来指定串的格式. sprintf是打印到字符串里.

例题:

P1957 口算练习题

  • 题目描述

王老师正在教简单算术运算。细心的王老师收集了i道学生经常做错的口算题,并且想整理编写成一份练习。编排这些题目是一件繁琐的事情,为此他想用计算机程序来提高工作效率。王老师希望尽量减少输入的工作量,比如5+8的算式最好只要输入5和8,输出的结果要尽量详细以方便后期排版的使用,比如对于上述输入进行处理后输出 5+8=13 以及该算式的总长度6。王老师把这个光荣的任务交给你,请你帮他编程实现以上功能。

  • 输入格式

第一行为数值i

接着的i行为需要输入的算式,每行可能有三个数据或两个数据。

若该行为三个数据则第一个数据表示运算类型,a表示加法运算,b表示减法运算,c表示乘法运算,接着的两个数据表示参加运算的运算数。

若该行为两个数据,则表示本题的运算类型与上一题的运算类型相同,而这两个数据为运算数。

  • 输出格式

输出2*i行。对于每个输入的算式,输出完整的运算式及结果,第二行输出该运算式的总长度

  • 输入输出样例

输入 #1复制

4
a 64 46
275 125
c 11 99
b 46 64
  • 输出 #1复制
64+46=110
9
275+125=400
11
11*99=1089
10
46-64=-18
9
  • 说明/提示

数据规模与约定

0<i<=50

运算数为非负整数且小于10000

对于50%的数据,输入的算式都有三个数据,第一个算式一定有三个数据。

  • 参考代码
#include <iostream> //cin & cout 用iostream
#include <cstring> //memset & strlen 用cstring
#include <cstdio> //sscanf & sprintf 用cstdio
using namespace std;

char f;
int n, x, y;
char s[1000], ans[1000];

int main(){
 scanf("%d", &n);
 cin.getline(s, sizeof(s));
 for(int i = 0; i < n; i++) {
  cin.getline(s, sizeof(s));

  if(s[0] >= 'a' && s[0] <= 'c') {
   sscanf(s+1,"%d %d",&x, &y);
   f = s[0];
  } else {
   sscanf(s,"%d %d",&x, &y);
  }

  if(f =='a') {
   sprintf(ans, "%d+%d=%d", x, y, x+y);
  } else if(f == 'b') {
   sprintf(ans, "%d-%d=%d", x, y, x-y);
  } else {
   sprintf(ans, "%d*%d=%d", x, y, x*y);
  }

  printf("%s\n%d\n", ans, strlen(ans));

 }
 return 0;
}


作业

  • P5733 【深基6.例1】自动修正
  • P1914 小书童——凯撒密码
  • P1125 笨小猴
  • P1957 口算练习题
  • P5015 标题统计
  • P1308 统计单词数
  • P1765 手机
  • P1553 数字反转(升级版)
  • P1603 斯诺登的密码
  • P1598 垂直柱状图