C/C++字符串

一.C风格的字符串
1.

char a[6] = { 'h','e','l','l','o','\0' };
printf("%s", a);//hello
#include<iostream>
#include<string>
using namespace std;
int main() {
	char a[6] = { 'h','e','l','l','o','\0' };
	char b[5]= { 'h','e','l','l','o'};//空间至少大一位留出'\0'位置
	char c[6]= { 'h','e','l','l','o' };
	char d[] = "hello";
	char e[6] = "hello";
	char f[5] = "hello";//error

	int lena = strlen(a);
	int lenb = strlen(b);
	int lenc = strlen(c);
	int lend = strlen(d);
	int lene = strlen(e);

	printf("%d,%d,%d,%d,%d", lena, lenb,lenc,lend,lene);//5,37,5,5,5
}
int main() {
	char a[] = "hello";
	printf("%s", a);//hello
	printf("%c", a[1]);//e
}

4.strcpy复制

int main() {
	char a[] = "hello";
	char b[] = "jack";
	strcpy(a, b);//b复制给a,a变为jack,b不变
	printf("%s", a);//jack
}

5.strcat连接

int main() {
	char a[10] = "hello";//注意连接时a缓冲区会不会溢出,幷留出'/0'位置
	char b[] = "jack";
	strcat(a, b);//b连接到a末尾
	printf("%s", a);//hellojack
}

6.strcmp(s1,s2),s1大返回大于0,s1小返回小于0。逐个比较第一个不相等字符的ASCII码,全相等返回0

int main() {
	char a[] = "hello";
	char b[] = "hoogle";
	cout<<strcmp(a, b);//e<o,结果小于0,输出:-1
	cout<<strcmp(b, a);//o>e,,结果大于0,输出:1
	char c[] = "hello";
	cout << strcmp(a, c);//0
}

7.strchr(s,ch)在字符串s中查找ch,返回ch第一次出现及其后面的字符
也可以通过指针接收,与字符串的差值是ch在字符串s中第一次出现的数组下标

int main() {
	char a[] = "hoogle";
	char* b = strchr(a, 'o');
	cout << b;//oogle
	cout << b - a;//1
}

8.输入

int main() {
	char a[10];
	scanf("%s", &a);//hello
	printf("%s", a);//hello
	cout << a;//hello
}

二.C++的string类
1.输出
.c_str()

#include<iostream>
#include<string>
using namespace std;
int main() {
	char a[] = "hello";
	string b = "hello";
	printf("%s", a);//hello
	printf("%s", b);//乱码
	printf("%s", b.c_str());//hello
	cout << b;//hello
}

2.拼接
确保字符串连接时等号两侧都要有string
to_string()将数字常量转换为字符串

#include<iostream>
#include<string>
using namespace std;
int main() {
	string a;
	//a = "qw" + 'w';
	//printf("%s", a.c_str());//乱码

	//确保字符串连接时等号两侧都要有string
	a = a + "qw" + 'w';
	printf("%s", a.c_str());//qww

	//to_string()将数字常量转换为字符串
	int b = 3;
	a = a + to_string(b);
	printf("%s", a.c_str());//qww3
}

3.输入,不能直接使用scanf

#include<iostream>
#include<string>
using namespace std;
int main() {
	string a;
	scanf("%s", &a);//error

	//可使用其他多种方式完成输入,例如
	a.resize(10);
	scanf("%s", &a[0]);//hello
	printf("%s", a.c_str());//hello
	
	printf("%d", a.size());//10
}

4.复制,互不影响

#include<iostream>
#include<string>
using namespace std;
int main() {
	string a;
	string b;
	a = "hello";
	b = a;
	a = "jack";
	cout << a;//jack
	cout << b;//hello
}

[练习1] 有理数四则运算
编写程序,计算2个有理数的和、差、积、商。

输入描述:输入在一行中按照“a1/b1 a2/b2”的格式给出两个分数形式的有理数,其中分子和分母全是整型范围内的整数,负号只可能出现在分子前,分母不为0。

输出描述:分别在4行中按照“有理数1 运算符 有理数2 = 结果”的格式顺序输出2个有理数的和、差、积、商。注意输出的每个有理数必须是该有理数的最简形式“k a/b”,其中k是整数部分,a/b是最简分数部分;若为负数,则须加括号;若除法分母为0,则输出“Inf”。题目保证正确的输出中没有超过整型范围的整数。

输入例子:
5/3 0/6

输出例子:
1 2/3 + 0 = 1 2/3
1 2/3 - 0 = 1 2/3
1 2/3 * 0 = 0
1 2/3 / 0 = Inf

代码长度限制 16 KB
时间限制 200 ms
内存限制 64 MB

[解]

#include<iostream>
#include<string>
using namespace std;
int gcd(int a, int b) {//求最大公因数
	return b == 0 ? a : gcd(b, a % b);
}
void simplify(int& a, int& b) {//分数化简
	if (b < 0) {//负号挪到分子上
		a = -a;
		b = -b;
	}
	int d = abs(gcd(a, b));
	a = a / d;
	b = b / d;
}
string f(int a, int b) {//转化成几又几分之几
	string s;
	simplify(a, b);
	if (a == 0 && b != 0) {
		s = '0';
		return s;
	}
	if (b == 1) {
		if (a < 0) {
			s = '(' + to_string(a) + ')';
		}
		else
			s = to_string(a);
		return s;
	}
	if (abs(a) < abs(b)) {
		if (a < 0) {
			s = "(" + to_string(a) + '/' + to_string(b) + ')';
		}
		else
			s = to_string(a) + '/' + to_string(b);
	}
	if (abs(a) == abs(b)) {
		if (a < 0) {
			s = '(-1)';
		}
		else
			s = '1';
	}
	if (abs(a) > abs(b)) {
		int k1 = abs(a / b);
		int k2 = abs(a % b);
		if (a < 0) {
			s = "(-" + to_string(k1) + ' ' + to_string(k2) + '/' + to_string(b) + ')';
		}
		else
			s = to_string(k1) + ' ' + to_string(k2) + '/' + to_string(b);
	}
	return s;
}
int main() {
	int a1, b1, a2, b2;
	scanf("%d/%d %d/%d", &a1, &b1, &a2, &b2);
	printf("%s + %s = %s\n", f(a1, b1).c_str(), f(a2, b2).c_str(), f(a1 * b2 + a2 * b1, b1 * b2).c_str());
	printf("%s - %s = %s\n", f(a1, b1).c_str(), f(a2, b2).c_str(), f(a1 * b2 - a2 * b1, b1 * b2).c_str());
	printf("%s * %s = %s\n", f(a1, b1).c_str(), f(a2, b2).c_str(), f(a1 * a2, b1 * b2).c_str());
	if (a2 == 0) {
		printf("%s / 0 = Inf\n", f(a1, b1).c_str());
	}
	else
		printf("%s / %s = %s\n", f(a1, b1).c_str(), f(a2, b2).c_str(), f(a1 * b2, a2 * b1).c_str());
	return 0;
}

[练习2]
央视新闻发了一条微博,指出 2020 年有个罕见的“对称日”,即 2020 年 2 月 2 日,按照 年年年年月月日日 格式组成的字符串 20200202 是完全对称的。

给定任意一个日期,本题就请你写程序判断一下,这是不是一个对称日?

在这里插入图片描述
输入格式:输入首先在第一行给出正整数 N(1<N≤10)。随后 N 行,每行给出一个日期,却是按英文习惯的格式:Month Day, Year。其中 Month 是月份的缩写,对应如下:
一月:Jan
二月:Feb
三月:Mar
四月:Apr
五月:May
六月:Jun
七月:Jul
八月:Aug
九月:Sep
十月:Oct
十一月:Nov
十二月:Dec
Day 是月份中的日期,为 [1, 31] 区间内的整数;Year 是年份,为 [1, 9999] 区间内的整数。

输出格式:对每一个给定的日期,在一行中先输出 Y 如果这是一个对称日,否则输出 N;随后空一格,输出日期对应的 年年年年月月日日 格式组成的字符串。

输入样例:
5
Feb 2, 2020
Mar 7, 2020
Oct 10, 101
Nov 21, 1211
Dec 29, 1229

输出样例:
Y 20200202
N 20200307
Y 01011010
Y 12111121
N 12291229

代码长度限制 16 KB
时间限制 400 ms
内存限制 64 MB

[解]

#include<iostream>
#include<algorithm> //reverse头
using namespace std;
bool panduan(string a) {
	string b = a;
	reverse(b.begin(), b.end());
	if (b == a)
		return true;
	else
		return false;
}
struct pro {
	string year;
	string month;
	string day;
}a[15];
int main() {
	int n;
	cin >> n;
	for(int i=0;i<n;i++){
		cin >> a[i].month>> a[i].day>> a[i].year;
		if (a[i].month == "Jan")
			a[i].month = "01";
		else if (a[i].month == "Feb")
			a[i].month = "02";
		else if (a[i].month == "Mar")
			a[i].month = "03";
		else if (a[i].month == "Apr")
			a[i].month = "04";
		else if (a[i].month == "May")
			a[i].month = "05";
		else if (a[i].month == "Jun")
			a[i].month = "06";
		else if (a[i].month == "Jul")
			a[i].month = "07";
		else if (a[i].month == "Aug")
			a[i].month = "08";
		else if (a[i].month == "Sep")
			a[i].month = "09";
		else if (a[i].month == "Oct")
			a[i].month = "10";
		else if (a[i].month == "Nov")
			a[i].month = "11";
		else
			a[i].month = "12";

		if (a[i].day.size() != 3)//还有个逗号
			a[i].day = '0' + a[i].day;

		if (a[i].year.size() == 3)
			a[i].year = '0' + a[i].year;
		if (a[i].year.size() == 2)
			a[i].year = "00" + a[i].year;
		if (a[i].year.size() == 1)
			a[i].year = "000" + a[i].year;
	}
	for (int i = 0; i < n; i++) {
		string temp = a[i].year + a[i].month + a[i].day[0] + a[i].day[1];
		if (panduan(temp))
			cout << "Y" << " " << temp << endl;
		else
			cout << "N" << " " << temp << endl;
	}
	return 0;
}

[练习3] 钱串子的加法
人类习惯用 10 进制,可能因为大多数人类有 10 根手指头,可以用于计数。这个世界上有一种叫“钱串子”(学名“蚰蜒”)的生物,有 30 只细长的手/脚,在它们的世界里,数字应该是 30 进制的。本题就请你实现钱串子世界里的加法运算。

输入格式:
输入在一行中给出两个钱串子世界里的非负整数,其间以空格分隔。所谓“钱串子世界里的整数”是一个 30 进制的数字,其数字 0 到 9 跟人类世界的整数一致,数字 10 到 29 用小写英文字母 a 到 t 顺次表示。输入给出的两个整数都不超过 105 位。

输出格式:
在一行中输出两个整数的和。注意结果数字不得有前导零。

输入样例:
2g50ttaq 0st9hk381

输出样例:
11feik2ir

代码长度限制 16 KB
时间限制 400 ms
内存限制 64 MB

[解]

#include<iostream>
#include<algorithm>
using namespace std;
int change(char x) {
	if (x >= '0' && x <= '9')
		return x - 48;
	else
		return x - 97 + 10;
}
int main() {
	string num1, num2, sum;
	string all = "0123456789abcdefghijklmnopqrst";
	int jinwei = 0;
	cin >> num1 >> num2;
	reverse(num1.begin(), num1.end());
	reverse(num2.begin(), num2.end());
	if (num1.length() < num2.length())//num1长
		swap(num1, num2);
	num2.append(num1.length() - num2.length(), '0');
	for (int i = 0; i < num1.length(); i++) {
		int n = change(num1[i]) + change(num2[i]) + jinwei;
		//sum = sum + all[n % 30];//超时
		sum += all[n % 30];//正常
		if (n >= 30) {
			jinwei = 1;
		}
		else
			jinwei = 0;
	}
	if (jinwei == 1)
		cout << 1;//最后一个进位
	reverse(sum.begin(), sum.end());
	int i = 0;
	for (; i < sum.length(); i++) {
		if (sum[i] != '0') {
			break;
		}
	}
	if (i == sum.length()) {
		printf("0");//全为0
	}
	else {
		for (; i < sum.length(); i++) {
			cout << sum[i];
		}
	}
	return 0;
}

[练习4] ChatGPT
ChatGPT(全名:Chat Generative Pre-trained Transformer)近期成为网络讨论的热点话题之一。本题就请你根据某社交网络中发帖的情况,统计每个人帖子中含有 ChatGPT(不区分大小写)的数量(简称“含茶量”),找出最热衷于讨论这个话题的人,即含茶量最高的人。

输入格式:
输入在第一行中给出正整数:N(≤1000),为参加统计的帖子数量。

随后给出 N 条帖子的信息,每条格式为:第一行给出发帖人 ID,是一个长度为 4 位的非空数字串;第二行给出非空的帖子的内容,由不超过 140 个英文字母、数字、空格、标点(只包括 ?、, 和 .)组成,以回车结束(回车不算在 140 字内)。

输出格式:
在一行中输出含茶量最高的 ID,及其含茶量。数字间以 1 个空格分隔,行首尾不得有多余空格。

题目保证输出唯一。

输入样例:
4
1010
I am not interested in ChatGPT.
2333
I am gonna talk about chatgpt, and Chatgpt, and CHATGPT
2333
they are all ChatGPT
0002
So what are you talking about, chatPPT?

输出样例:
2333 4

代码长度限制 16 KB
Java (javac)
时间限制 600 ms
内存限制 256 MB
其他编译器
时间限制 400 ms
内存限制 64 MB

[解] (未在评测系统测试)

#include<iostream>
#include <string>
using namespace std;
int main() {
	int n;
	cin >> n;
	int count[100005]={0};
	for (int i = 0; i < n; i++) {
		int id;
		cin >> id;
		getchar();
		string s;
		getline(cin, s);//获取一行数据,存入s
		int len = s.length();
		for (int j = 0; j < len; j++) {
			s[j] = tolower(s[j]);//把字母字符转换成小写,非字母字符不做出处理
		}
		for (int j = 0; j < len-6; j++) {
			if (s[j] == 'c' && s[j + 1] == 'h' && s[j + 2] == 'a' && s[j + 3] == 't' && s[j + 4] == 'g' && s[j + 5] == 'p' && s[j + 6] == 't') {
				count[id]++;
				j = j + 6;
			}
		}
	}
	int max = -1;
	int maxpos=0;
	for (int i = 0; i < 10000; i++) {
		if (max <= count[i]) {
			max = count[i];
			maxpos = i;
		}
	}
	printf("%04d %d", maxpos, max);
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

卡__卡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值