首页 > 其他分享 >文件排版(文本文件读写)

文件排版(文本文件读写)

时间:2024-12-12 12:00:00浏览次数:5  
标签:right str 读写 空格 文本文件 line 排版 left

【问题描述】 

英文电影中参演人员名单一般以某种方式进行排版显示。给定一个未排版的文件listin.txt,该文件中每行参演人员名单由冒号":"分隔成前后两部分,但格式杂乱无章,单词(由除空格和水平制表符之外的其它字符构成)之间可能有多个空格或水平制表符分隔。编写程序,要求将其按如下排版规则排版输出到另一个文件listout.txt中:

1.从标准输入整数,作为排版后所有各行冒号在一行中的固定位置,输入的整数肯定大于排版后所有各行冒号前的字符个数,位置从1开始计数;

2.冒号左边的单词串以行头为基准左对齐,左边的最后一个单词与冒号之间以空格填充;冒号右边的单词串以冒号基准左对齐,最后一个单词后只有回车换行符,不再有其它字符;

3.冒号左右两边的单词间都只有一个空格分隔,并且要求冒号两边至少各有一个空格。

假设输入文件中每行字符个数不超过100。

 【输入形式】

 待排版的参演人员名单从当前目录下的listin.txt文件中读入,表示冒号位置的整数从标准输入读入。

 【输出形式】

 排版后的参演人员名单输出到当前目录下的listout.txt中。

 【输入样例】仅为示例

假设文件listin.txt内容为:

Supervising    Digital Colorist:Steven J. Scott  

 Second Colorist :Andrew Francis

 Digital Intermediate Producer:Loan Phan

Digital   Intermediate Editor:  Devon Miller   

键盘输入:40

【输出样例】

【样例说明】

输入的文件listin.txt中有四行参演人员名单,要求排版后冒号位于第40个字符的位置,按照上述排版规则输出到文件listout.txt中。以上仅为参考示例,因为浏览器的显示可能带来误差,以题面文字描述为准。

一、思路:

把因为不确定中间的是空格还是制表符,我们就遇上制表符就全都换成空格。然后遍历查找是否有连续空格,有的话删除到只剩下一个。最后计算一下40这个位置到左边部分一共需要多少个空格,在填充中间部分就好了

二、代码实现:

1.开始的必要找两个文件的环节(如果运行结果是文件不存在,表明可能是读取的时候不存在那个listin.txt文件,因为是ofstream和fstream才会在找不到文件的时候给你自动创建一个)

    //找两个文件
	fstream infile("listin.txt", ios::in);		//其实默认就是读取,用ifstream不会自动创建,用ofstream或者fstream才行
	if (!infile) {
		cerr << "open error!" << endl;
		exit(1);		//表示立即终止程序的执行(貌似return 也行?)
	}
	ofstream outfile("listout.txt",ios::out);		//创建输出文件流对象,关联文件listout.txt
	if (!outfile) {			//文件打开失败返回一个值
		cerr << "open error!" << endl;
		exit(1);
	}

2.之后是循环读取一行的字符串,再进行处理,为避免臃肿写成函数形式

string line;
while (getline(infile, line)) {
	string formatted_line = rewrite(line, location);
	outfile << formatted_line << endl;
}

这是函数部分

//排版文字
string rewrite(const string& line, int location) {
	istringstream iss(line);
	string left, right;
	getline(iss, left, ':');		//获取一串字符,直到遇上":"
	getline(iss, right);

	//首尾处理,但感觉应该有更好的方法,还是写复杂了(那两个left.find_first_not_of和find_last_not_of也是我上网查的)
	left.erase(0, left.find_first_not_of(" \t"));		//删除0到“第一个不是空格或者制表符”之间的所有元素
	left.erase(left.find_last_not_of(" \t") + 1);
	right.erase(0, right.find_first_not_of(" \t"));
	right.erase(right.find_last_not_of(" \t") + 1);
	
//嵌套一个删除空格的函数
	rmove(left);
	rmove(right);
	//计算左边需要填充的空格数
	int padding = location - left.length() -1;		//-1是要除去:本身所在的位置

	//排版
	string formatted_line = left ;
	formatted_line.append(padding, ' ');		//填空空格
	right = ": " + right;                        //因为不会整体处理把这个冒号弄上去,我就分成了left和right两部分
	formatted_line += right;
	return formatted_line;
}

这是嵌套函数中删除空格的部分

//删除多个连续空格,保留当前位置的一个
void rmove(string& str) {
	//把所有制表符都替换为一个空格
	for (size_t i = 0; i < str.length(); i++) {
		if (str[i] == '\t') {
			str.replace(i, 1, " ");
		}
	}
	//删除空格
	bool sign = false;						//保证初始时候至少有一个空格
	auto it = str.begin();
	while (it != str.end()) {
		if (*it == ' ') {
			if (sign) {
				it = str.erase(it);			//持续检查当前位置
			}
			else {
				sign = true;
				it++;						//说明当前位置已经无多余的空格
			}
		}
		else {
			sign = false;
			it++;
		}
	}
}

三、完整代码

#include<iostream>
#include<fstream>
#include<sstream>		//istringstream
#include<vector>
#include<string>

using namespace std;
//删除多个连续空格,保留1
void rmove(string& str) {
	//将制表符替换为空格(替换剩下部分版本;)
	//auto tab_len = 8;
	//for (size_t i = 0, pos = 0; i < str.length(); i++) {
	//	if (str[i] == '\t') {
	//		size_t len_to_next = tab_len - (pos % tab_len);			//填充空格的长度
	//		str.replace(i, 1, len_to_next, ' ');
	//		//更新索引
	//		i += len_to_next - 1;
	//		//更新位置计数器
	//		pos += len_to_next - 1;
	//	}
	//}
	
	//把所有制表符都替换为一个空格版
	for (size_t i = 0; i < str.length(); i++) {
		if (str[i] == '\t') {
			str.replace(i, 1, " ");
		}
	}
	//删除空格
	bool sign = false;						//保证初始时候至少有一个空格
	auto it = str.begin();
	while (it != str.end()) {
		if (*it == ' ') {
			if (sign) {
				it = str.erase(it);			//持续检查当前位置
			}
			else {
				sign = true;
				it++;						//说明当前位置已经无多余的空格
			}
		}
		else {
			sign = false;
			it++;
		}
	}
}
//排版文字
string rewrite(const string& line, int location) {
	istringstream iss(line);
	string left, right;
	getline(iss, left, ':');		//获取一串字符,直到遇上":"
	getline(iss, right);

	//去除空格
	left.erase(0, left.find_first_not_of(" \t"));		//删除0到“第一个不是空格或者制表符”之间的所有元素
	left.erase(left.find_last_not_of(" \t") + 1);
	right.erase(0, right.find_first_not_of(" \t"));
	right.erase(right.find_last_not_of(" \t") + 1);
	
	rmove(left);
	rmove(right);
	//计算左边需要填充的空格数
	int padding = location - left.length() -1;		//-1 冒号前面的第一个空格

	//构建排版
	string formatted_line = left ;
	formatted_line.append(padding, ' ');		//填空空格
	right = ": " + right;
	formatted_line += right;
	return formatted_line;
}
int main() {
	int location = 0;
	cin >> location;			//表示冒号的位置

	//找两个文件
	fstream infile("listin.txt", ios::in);		//其实默认就是读取,用ifstream不会自动创建,用ofstream或者fstream才行
	if (!infile) {
		cerr << "open error!" << endl;
		exit(1);		//表示立即终止程序的执行(貌似return 也行?)
	}
	ofstream outfile("listout.txt",ios::out);		//创建输出文件流对象,关联文件listout.txt
	if (!outfile) {			//文件打开失败返回一个值
		cerr << "open error!" << endl;
		exit(1);
	}
	string line;
	while (getline(infile, line)) {
		string formatted_line = rewrite(line, location);
		outfile << formatted_line << endl;
	}

	infile.close();
	outfile.close();
	return 0;
}

之后我的完整代码应该都会像这样。。。把一些奇怪的想法和自言自语加进去。(说白了就是懒得再找注释然后删除了,这人。。。)谨慎辨别,思路看思路为主,不建议直接copy。

标签:right,str,读写,空格,文本文件,line,排版,left
From: https://blog.csdn.net/2403_87544412/article/details/144422754

相关文章

  • 手搓了个读写锁...囧
    业务需求,适合需要使用读写锁进行控制,印象里delphi一直都没有读写锁,网上搜了搜也都是自己实现的所以就手搓了一个,搓完才发现,系统自带了跨平台的高效读写锁TLightweightMREW留档存个念想吧.....附测试代码unitUnit1;interfaceusesWinapi.Windows,Winapi.Mess......
  • 部署达梦8读写分离集群
    一、原理读写分离集群其实是主备集群的升级版本,在双机热备的基础上把用户写和读的会话事务分别放在主库和备库上执行。写事务会被分发到主库上执行,读事务则部分分发到备库上执行,分发比例在dm_svc.conf中控制,如:RW_PERCENT=25,指的是25%的读分发到主库。由接口负责读写事务的分发......
  • 【源码】Sharding-JDBC源码分析之SQL中读写分离动态策略、数据库发现规则及DatabaseDi
     Sharding-JDBC系列1、Sharding-JDBC分库分表的基本使用2、Sharding-JDBC分库分表之SpringBoot分片策略3、Sharding-JDBC分库分表之SpringBoot主从配置4、SpringBoot集成Sharding-JDBC-5.3.0分库分表5、SpringBoot集成Sharding-JDBC-5.3.0实现按月动态建表分表6、【源码......
  • 【Linux内核】4张IO时序图,一次搞懂Linux下的文件读写
    因为如今大多数资源都是通过网络访问的:数据库、对象存储和其他微服务。大多数服务器应用程序开发人员在考虑I/O时,都会考虑网络I/O,然而,数据库开发人员还必须考虑文件I/O。一般来说,在Linux服务器上访问文件有四种选择:传统读/写、mmap、直接I/O(DIO)读/写和异步直接I/O(AIO/DIO)。......
  • 使用SELECT…INTO OUTFILE导出文本文件
    ​MySQL数据库导出数据时,允许使用包含导出定义的SELECT语句进行数据的导出操作。该文件被创建到服务器主机上,因此必须拥有文件写入权限(FILE权限)才能使用此语法。“SELECT...INTOOUTFILE'filename'”形式的SELECT语句可以把被选择的行写入一个文件中,并且filename不能是一个已经存......
  • Android14 关于读写权限 (Vivo)
    按常理来讲,在相机业务,或从相册读取图片时,应该要申请读写权限,在使用Delphi12+Android14环境下,发现在申请读写权限时,申请权限内容中,这二项不需要授权?不清楚是自己处理的问题,还是规则有所变更>>申请权限>>相机申请三项权限,无论怎么操作,都只有相机权限一项返回(关于读写......
  • 【Linux】多线程(自旋锁、读写锁)
     ......
  • C#FileStrea读写
    //FileStream操作字节的//StreamReader和StreamWriter操作字符的FileStreamfsRead=newFileStream(@"C:\Users\admin\Desktop\av.txt",FileMode.OpenOrCreate,FileAccess.Read);byte[]buffer=newbyte[1024*1024*5];fsRea......
  • H7-TOOL自制Flash读写保护算法系列,为复旦微FM33LG和FM33LE制作使能和解除算法,支持在线
    说明:很多IC厂家仅发布了内部Flash算法文件,并没有提供读写保护算法文件,也就是选项字节算法文件,需要我们制作。实际上当前已经发布的TOOL版本,已经自制很多了,比如已经支持的兆易创新大部分型号,新唐的大部分型号等。但是依然有些厂家还没自制,所以陆续开始为这些厂家提供读写保护支持......
  • Mycat2+Mysql一主一从实现读写分离配置
    Mycat2+Mysql一主一从实现读写分离配置前置配置Mysql一主一从搭建Mycat2环境搭建环境信息ip地址软件角色版本192.168.1.19Mysql主8.0.40-0ubuntu0.20.04.1192.168.1.19Mycat2——1.21-release-3-14192.168.1.20Mysql从8.0.40-0ubuntu0.20.04.1......