PAT甲级 字符串处理题_C++题解

字符串处理题

目录

  • 《算法笔记》 重点摘要
  • 1001 A+B Format (20)
  • 1005 Spell It Right (20)
  • 1108 Finding Average (20)
  • 1132 Cut Integer (20)
  • 1140 Look-and-say Sequence

《算法笔记》 3.6 字符串处理 重点摘要

  1. 注意分析输入输出格式
  2. 注意细节和边界情况

1001 A+B Format (20)

#include<iostream>
using namespace std;
int main()
{
	int a, b, sum;
	cin >> a >> b;
	sum = a + b > 0 ? a + b : -(a + b); 
	if (a + b < 0) cout << "-";
	string s = to_string(sum);
	if (s.length() > 3){
		for (int i = s.length()-3; i > 0; i = i - 3) s.insert(i, ",");
		cout << s << endl;
	}
	else cout << sum << endl;
	return 0;
}
  • string.insert (pos, str); 在 pos 位置插入 str

1005 Spell It Right (20)

#include<iostream>
using namespace std;
int main()
{
	string words[10] = {"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"};
	string N;
	cin >> N;
	int sum = 0;
	for (int i = 0; i < N.length(); i++) sum += stoi(N.substr(i,1));
	string s = to_string(sum);
	cout << words[stoi(s.substr(0,1))];
	for (int i = 1; i < s.length(); i++) cout << " " << words[stoi(s.substr(i,1))];
	return 0;
}
  • string 转 int: stoi()
    • s[i] 是char,不符合参数要求,用 s.substr(i,1) 返回子串即可
  • int 转 string: to_string()

1108 Finding Average (20)

题目思路

  • 将输入先接收到字符串中
  • 依序检查是否有非数字,注意负号和小数点合法,其他非数字出现即不合法
  • 均为数字后,检查是否有小数点
    • 无小数点则为整数
    • 有小数点要分别检查是否有多个小数点(s.find_first_of('.') != s.find_last_of('.'))和小数位数是否超过2(s.length()-s.find('.') > 3)
  • 以上去掉格式不合法数字后,转化为double型,看是否在[-1000,1000]范围内,不在亦不合法
  • 输出时注意区分 0、1(number单数) 及其他
#include<iostream>
using namespace std;
int main()
{
	int n, num = 0;
	cin >> n;
	string s;
	double data, sum = 0;
	for (int i = 0; i < n; i++){
		bool islegal = true;
		cin >> s;
		for (int j = 0; j < s.length(); j++){
			if ((s[j]>'9' || s[j]<'0') && s[j]!='-' && s[j]!='.'){
				cout << "ERROR: " << s << " is not a legal number\n";
				islegal = false;
				break;
			}
		}
		if (islegal){
			if (s.find('.') != string::npos){
				if(s.find_first_of('.') != s.find_last_of('.') || s.length()-s.find('.') > 3){
					cout << "ERROR: " << s << " is not a legal number\n";
					continue;
				}
			}
			data = stod(s);
			if (data >= -1000 && data <= 1000){
				sum += data;
				num++;
			}
			else cout << "ERROR: " << s << " is not a legal number\n";
		}
	}
	if (!num) cout << "The average of 0 numbers is Undefined";
	else if (num == 1) printf("The average of 1 number is %.2f", num, sum);
	else printf("The average of %d numbers is %.2f", num, sum/num);
	return 0;
}

二刷(参考柳婼小姐姐的代码

#include<iostream>
#include<cstring>
using namespace std;
int main(){
	int n, k = 0;
	scanf("%d", &n);
	char s[50], t[50];
	double num, sum = 0.0;
	for (int i = 0; i < n; i++){
		scanf("%s", s);
		sscanf(s, "%lf", &num);
		sprintf(t, "%.2f", num);
		bool islegal = true;
		for (int j = 0; j < strlen(s); j++)
			if (s[j] != t[j]) islegal = false;
		if (islegal && num >= -1000 && num <= 1000){
			k++;
			sum += num;
		}
		else printf("ERROR: %s is not a legal number\n", s);
	}
	if (!k) printf("The average of 0 numbers is Undefined\n");
	else if (k == 1) printf("The average of 1 number is %.2f\n", sum);
	else printf("The average of %d numbers is %.2f\n", k, sum / k);
	return 0;
} 
  • sscanf() – 从一个字符串中读进与指定格式相符的数据
  • sprintf() – 字符串格式化命令,主要功能是把格式化的数据写入某个字符串中

1132 Cut Integer (20)

#include<iostream>
using namespace std;
int main()
{
	int n, z;
	scanf("%d", &n);
	for (int i = 0; i < n; i++){
		scanf("%d", &z);
		string s = to_string(z);
		int len = s.length();
		int a = stoi(s.substr(0,len/2));
		int b = stoi(s.substr(len/2));
		printf("%s", !b || z % (a * b) ? "No\n" : "Yes\n");
	}
	return 0;
}
  • 注意 b 可能为 0 导致 a*b 为 0 发生取余 0 情况导致浮点错误
  • string.substr(pos) 可表示pos到end的子串

    string substr (size_t pos = 0, size_t len = npos) const;

浮点错误

  • 是否可能出现了一个数除以0的情况
  • 是否可能出现了一个数取余0的情况
  • 是否发生了数据溢出而导致的除以0或者取余0的情况

1140 Look-and-say Sequence

题目思路

  • 依序遍历当前字符串,若s[j] == s[j+1],将记录s[j]数量的sum++;若不等,则说明s[j]为一串相同数字的末尾,此时将s[j]的内容和其个数sum压入新串next
  • 注意遍历到串尾时,继续检查j+1会越界,由于每个s[j]的内容其实在上一次循环已经被检查过,且上一次循环记录的sum是此次循环对应值,可直接将串尾内容及sum压入next串
#include<iostream>
using namespace std;
int main()
{
	int D, N;
	cin >> D >> N;
	string s = to_string(D);
	for (int i = 1; i < N; i++){
		string next;
		int sum = 1;
		for (int j = 0; j < s.length(); j++){
			if (j == s.length()-1){
				next.append(s.substr(j,1));
				next.append(to_string(sum));
				break;
			}
			if (s[j] == s[j+1]) sum++;
			else{
				next.append(s.substr(j,1));
				next.append(to_string(sum));
				sum = 1;
			}
		}
		s = next;
	}
	cout << s << endl;
	return 0;
} 

二刷(参考柳婼小姐姐的代码

  • 遍历 s ,令 j 从当前位置 i 开始检查 s[j] 是否等于 s[i]
  • 当 j 检查到与 s[i] 不同或到串尾时会停在第一个不与 s[i] 相同的点 或是 串尾+1,那么 j-i 即为与 s[i] 相同的个数。
  • 将 s[i] 和个数 j-i 压入新串
  • 令 i=j,即从与上一个 s[i] 不同点处继续检查。
#include<iostream>
using namespace std;
int main()
{
	string s;
        int n, j;
	cin >> s >> n;
	for (int k = 1; k < n; k++){
		string t;
		for (int i = 0; i < s.length(); i = j){
			for (j = i; j < s.length() && s[j] == s[i]; j++);
			t += s[i] + to_string(j - i);
		}
		s = t;
	}
	cout << s;
	return 0;
}
posted @ 2019-09-06 13:09  鲸90830  阅读(486)  评论(0编辑  收藏  举报