第18课 字符串及文件操作举例

发布时间:2024年01月06日


前言

字符、字符串以及字符文件的读写处理是编程竞赛中的重要部分,不可忽视、不可偏废。


一、课堂举例

1. 查找单词问题

在一段英文文本中查找指定的单词,如果找到,给出单词在文本中出现的次数和第一次出现的位置下标。

代码如下(参考)

#include <iostream>
using namespace std;

int main() {
	int first, index, count = 0;
	string word, text;
	getline(cin, word);	// word to be find
	getline(cin, text);
	for(int i=0; i<word.length(); i++) {
		if(word[i]>='A' && word[i]<='Z')  word[i] += 32;
	}
	for(int i=0; i<text.length(); i++) {
		if(text[i]>='A' && text[i]<='Z')  text[i] += 32;
	}
	first = index = text.find(word);
	while(index!=-1) {
		count++;
		index = text.find(word, index+1);
	}
	if(count!=0) cout << count << ' ' << first << endl;
	else cout << first << endl;
    return 0;
}

运行程序,输入输出数据如下。

To
to be or not to be is a question!
2 0

2. 查找单词问题(二)

在一段英文文本中查找指定的单词,如果找到,给出单词在文本中出现的次数和每一次出现的位置下标。
代码如下(参考)

#include <iostream>
#include <iomanip>
using namespace std;

int main() {
	int first, index, count = 0;
	int c[20] = {0};
	string word, text;
	getline(cin, word);	// word to be find
	getline(cin, text);
	for(int i=0; i<word.length(); i++) {
		if(word[i]>='A' && word[i]<='Z')  word[i] += 32;
	}
	for(int i=0; i<text.length(); i++) {
		if(text[i]>='A' && text[i]<='Z')  text[i] += 32;
	}
	first = index = text.find(word);
	while(index!=-1) {
		c[count] = index;
		index = text.find(word, index+1);
		count++;
	}
	if(count!=0) {
		for(int i=0; i<count; i++) {
			cout << setw(8) << c[i];
		}
		cout << endl;
	}
	else cout << first << endl;
    return 0;
}

运行程序,输入输出如下。

To
To be or not to be is a question!
       0      13

上面的代码中,数组定义 c[20]假设被查找的单词在文本串中最多出现20次,根据实际情况可以调整数组的长度。当然也可以考虑使用C++中的vector容器类。

#include <iostream>
#include <iomanip>
#include <vector>
using namespace std;

int main() {
	int first, index, count = 0;
	//int c[20] = {0};
	vector<int> vect;	//声明一个存放int型元素的向量
	string word, text;
	getline(cin, word);	// word to be find
	getline(cin, text);
	for(int i=0; i<word.length(); i++) {
		if(word[i]>='A' && word[i]<='Z')  word[i] += 32;
	}
	for(int i=0; i<text.length(); i++) {
		if(text[i]>='A' && text[i]<='Z')  text[i] += 32;
	}
	first = index = text.find(word);
	while(index!=-1) {
		//c[count] = index;
		vect.push_back(index);
		index = text.find(word, index+1);
		//count++;
	}
	if(count!=0) {
//		for(int i=0; i<count; i++) {
//			cout << setw(8) << c[i];
//		}
		for(int i=0; i<vect.size(); i++) {
	    	cout << setw(8) << vect[i];
		}
		cout << endl;
	}
	else cout << first << endl;
    return 0;
}

运行程序,输入输出如下。

To
to be to be to be to be to be to be or not to be!
       0       6      12      18      24      30      43

3. 基因相关性问题

脱氧核糖核酸( DNA )由两条互补的碱基链以双螺旋的方式结合而成。为了获知基因序列在功能和结构上的相似性,经常需要将几条不同序列的 DNA 进行比对,以判断该比对的 DNA 是否具有相关性。
现比对两条长度相同的 DNA 序列。定义两条 DNA 序列相同位置的碱基为一个碱基对,如果一个碱基对中的两个碱基相同的话,则称为相同碱基对。接着计算相同碱基对占总碱基对数量的比例。如果该比例大于等于给定阈值,则判定该两条 DNA 序列是相关的;否则,不相关。
输入:数据在文件 gene.in 中,有3行,第一行是用来判定出两条 DNA 序列是否是相关的阈值,随后两行是两条 DNA 序列(长度不大于500)。
输出:数据在 gene.out 文件中,若两条 DNA 序列相关,则输出 yes ,否则输出no。
样例输入:gene.in
0.85
ATCGCCGTAAGTAACGGTTTTAAATAGGCC
ATCGCCGGAAGTAACGGTCTTAAATAGGCC
样例输出:gene. out
yes
【数学分析】
此题目本质上是求两个字符串位置相同的字符是否相等以及其所占比例。首先循环判断位置相同字符是否相等,如果相等,则计数值加1。然后用计数值除以总长得到比例,最后判断该比例是否大于阈值。
【算法描述】
(1)定义两个字符串变量 str1 和str2,循环变量 i ,两个浮点变量 same 和 threshold ( same 用于存放相等字符个数, threshold 存放阈值),定义输入文件流 fin 和输出文件流 fout ,并打开指定文件;
(2)从文件输入 threshold、str1、str2。
(3)循环 i 从0到 str1.length()。如果 str1[i]和str2[i]相等,那么 same++。
(4)如果 same /str1.length() >= threshold ,那么文件输出 yes ;否则,文件输出 no 。

下面直接给出基因相关性问题的参考代码。

#include <iostream>
#include <fstream>
using namespace std;

int main() {
	string str1, str2;
	int i, len;
	double threshold, same;
	ifstream fin("gene.in");
	ofstream fout("gene.out");
	fin >> threshold;
	getline(fin, str1);
	getline(fin, str2);
	len = str1.length();
	for(int i=0; i<len; i++) {
		if(str1[i]==str2[i]) same++;
	}
	if(same/len >= threshold) fout << "yes";
	else fout << "no";
	fin.close();
	fout.close();
	cout << "Comparison completed!" << endl;
    return 0;
}

4. 情报加密问题

在情报传递过程中,为了防止情报被截获,往往需要对情报用一定的方式加密。一些简单的加密算法虽然不足以完全避免情报被破译,但仍然能防止情报被轻易地识别。我们给出一种最简单的加密方法,对给定的一个字符串,把其中从 a ~ y 、 A ~ Y 的字母用其后继字母替代,把 z用a替代,把 Z 用 A 替代,其他非字母字符不变,则可得到一个简单的加密字符串。
输入:数据在文件 password.in 中,有一行,包含一个字符串,长度小于80个字符。
输出:数据在 password.out 文件中,包含输出每行字符串的加密字符串。
样例输入: password.in
Hello! How are you!
样例输出: password.out
Ifmmp! Ipx bsf zpv!

#include <iostream>
#include <fstream>
using namespace std;

int main() {
	string text;
	ifstream fin("original.txt");
	ofstream fout("encrypted.txt");
	getline(fin, text);
	for(int i=0; i<text.length(); i++) {
		if(text[i]>='a' && text[i]<='y' || text[i]>='A' && text[i]<='Y')
			text[i] += 1;
		else if(text[i]=='z') text[i] = 'a';
		else if(text[i]=='Z') text[i] = 'A';
	}
	fout << text;
	fin.close();
	fout.close();
	cout << "Encryption completed!" << endl;
    return 0;
}

如果输入文件中的内容有多行,我们可以一行一行地分行进行加密处理。

#include <iostream>
#include <fstream>
using namespace std;

int main() {
	string text;
	ifstream fin("original.txt");
	ofstream fout("encrypted2.txt");
	while(!fin.eof()) {
		getline(fin, text);
		for(int i=0; i<text.length(); i++) {
			if(text[i]>='a' && text[i]<='y' || text[i]>='A' && text[i]<='Y')
				text[i] += 1;
			else if(text[i]=='z') text[i] = 'a';
			else if(text[i]=='Z') text[i] = 'A';
		}
		fout << text << endl;
	}
	fin.close();
	fout.close();
	cout << "Encryption completed!" << endl;
    return 0;
}

运行程序,如果original.txt的内容如下。

Hello! How are you!
abcdefghijklmnopqrstuvwxyz
ABCDEFGHIJKLMNOPQRSTUVWXYZ

则输出文件encrypted2.txt的内容如下:

Ifmmp! Ipx bsf zpv!
bcdefghijklmnopqrstuvwxyza
BCDEFGHIJKLMNOPQRSTUVWXYZA

5. 最长/最短单词问题

输入:数据在数据文件words.txt中,有一行英文文本信息,单词与单词之间由空格分隔,标点符号之后均有一个空格。
输出:数据在maxmin.txt中,包含2行,第一行为找到的最长的单词,第二行为找到的最短的单词。

#include <iostream>
#include <fstream>
using namespace std;

int main() {
	string text, word, maxword, minword;
	int blank_index, begin;
	ifstream fin("words.txt");
	ofstream fout("maxmin.txt");
	getline(fin, text);
	begin = 0;
	blank_index = text.find(' ');
	//str1.substr(begin_index[, number_of_characters])
	
	//the first word of the text
	maxword = minword = text.substr(begin, blank_index-begin);
	begin = blank_index + 1;
	cout << maxword << endl;

	while(blank_index != -1) {
		blank_index = text.find(' ', blank_index + 1);
		word = text.substr(begin, blank_index-begin);
		begin = blank_index + 1;
		cout << word << endl;
		if(word.length()>maxword.length()) maxword = word;
		if(word.length()<minword.length()) minword = word;
	}
	
	cout << "========================" << endl;
	cout << "maxword: " << maxword << endl;
	cout << "minword: " << minword << endl;
	fout << "maxword: " << maxword << endl;
	fout << "minword: " << minword << endl;
	fin.close();
	fout.close();
	cout << "========================\nDone!" << endl;
    return 0;
}

运行程序,如果words.txt的内容如下。

I am studing C++ programming language in CASIA, It is very powerful and flexible!

则输出文件maxmin.txt的内容如下。

I
am
studing
C++
programming
language
in
CASIA,
It
is
very
powerful
and
flexible!
========================
maxword: programming
minword: I
========================
Done!

6. 最长/最短单词问题(增强版)

同样,对于上题,我们读取的words.txt文件的文本内容一般会有多行。此时,可以添加一个对每一行内容进行读取的循环结构来增强代码。下面给出一种代码实现以供参考。

#include <iostream>
#include <fstream>
using namespace std;

int main() {
	string text, word, maxword, minword;
	int blank_index, begin;
	ifstream fin("words.txt");
	ofstream fout("maxmin.txt");
	maxword = minword = "I";	//the first word of the text
	while(!fin.eof()) {
		getline(fin, text);
		begin = 0;
		blank_index = text.find(' ');
		//str1.substr(begin_index[, number_of_characters])
		word = text.substr(begin, blank_index-begin);
		begin = blank_index + 1;
		cout << word << endl;
		if(word.length()>maxword.length()) maxword = word;
		if(word.length()<minword.length()) minword = word;
		while(blank_index != -1) {
			blank_index = text.find(' ', blank_index + 1);
			word = text.substr(begin, blank_index-begin);
			begin = blank_index + 1;
			cout << word << endl;
			if(word.length()>maxword.length()) maxword = word;
			if(word.length()<minword.length()) minword = word;
		}
	}
	cout << "========================" << endl;
	cout << "maxword: " << maxword << endl;
	cout << "minword: " << minword << endl;
	fout << "maxword: " << maxword << endl;
	fout << "minword: " << minword << endl;
	fin.close();
	fout.close();
	cout << "========================\nDone!" << endl;
    return 0;
}

运行程序,如果words.txt的内容如下。

I am studing C++ programming language in CASIA, It is very powerful and flexible!
Introducing the new Bing. The AI-powered assistant for your search.
The number of characters to be removed.

则输出文件maxmin.txt的内容如下。

I
am
studing
C++
programming
language
in
CASIA,
It
is
very
powerful
and
flexible!
Introducing
the
new
Bing.
The
AI-powered
assistant
for
your
search.
The
number
of
characters
to
be
removed.
====================
maxword: programming
minword: I
====================
Done!

二、课后练习

2. 删除字符串中的某种字符

给定一个字符串,将其中的所有数字字符删除。

#include<iostream>

using namespace std;

int main() {
	string str = "Announcing 2the Next Wave of AI Innovation \
					with Microsoft Bing and Edge Celebrating \
					6 six months of 9the new AI-powered Bing.";
	cout << str << endl << endl;
	//str.erase(index[,count]);
	for(int i=0; i<str.length(); i++) {
		if(str[i]>='0' && str[i]<='9')
			str.erase(i, 1);
	}
	cout << str << endl;
	return 0;
}

运行程序,输出如下。

Announcing 2the Next Wave of AI Innovation
with Microsoft Bing and Edge Celebrating
6 six months of 9the new AI-powered Bing.

Announcing the Next Wave of AI Innovation
with Microsoft Bing and Edge Celebrating
 six months of the new AI-powered Bing.

3. 字符串比较大小

从键盘输入3个字符串,找出其中的最小字符串并输出。
样例输入:
aabbcc
aabcbc
abcabc
样例输出:
aabbcc

代码如下(示例)

#include<iostream>

using namespace std;

int main() {
	string str[3], min_str;
	for(int i=0; i<3; i++) {
		getline(cin, str[i]);
	}
	min_str = str[0];
	for(int i=0; i<3; i++) {
		if(str[i] < min_str) min_str = str[i];
	}
	cout << endl << min_str << endl;
	return 0;
}

运行程序,输入输出如下。

upper
middle
lower

lower

4. 超长数据加法

在文件add.txt中有两行内容,每一行是一个30位的十进制正整数,编程计算这两个正整数相加的结果并保存在文件added.txt中。
提示:超长数据的加法可以按字符串类型进行存取。
代码如下(参考)

#include<iostream>
#include<fstream>
#include<iomanip>

using namespace std;

int main() {
	short int c, d, e, len;
	string addend1, addend2;
	ifstream fin("add.txt");
	ofstream fout("added.txt");
	getline(fin, addend1);
	getline(fin, addend2);
	cout << setw(31) << addend1 << endl;
	cout << setw(31) << addend2 << endl;
	fout << setw(31) << addend1 << endl;
	fout << setw(31) << addend2 << endl;
	len = addend1.length();
	char sum[len+1];
	sum[len] = '\0';
	c = 0;
	for(int i=len-1; i>=0; i--) {
		d = (int(addend1[i])-48) + (int(addend2[i])-48) + c;
		if(d>=10) c=1;
		else c=0;
		sum[i+1] = char(d%10+48);
	}
	if(c==1) sum[0] = '1';
	cout << setw(31) << sum << endl;
	fout << setw(31) << sum << endl;
	fin.close();
	fout.close();
	return 0;
}

设输入文件add.txt中的内容如下。

123456789987654321123456789897
987654321234567891123456789098

则运行程序,输出和生成的added.txt文件内容如下。

 123456789987654321123456789897
 987654321234567891123456789098
1111111111222222212246913578995

文章来源:https://blog.csdn.net/red2brick/article/details/135417245
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。