【Gizmos】#001 Copy的代码中有行号且去除麻烦?试试代码前缀“去质器“

【Gizmos】#001 Copy的代码中有行号且去除麻烦?试试代码前缀"去质器"

    • 1. 问题的引出
    • 2. 问题解决方案
    • 3. 代码实现
    • 4. 运行结果
    • 5. 不足之处
    • 写在最后

从今天开始,笔者将开启一个新板块——Gizmos(译为小发明或小物件),板块名称来源于Unity3D的一个小模块。该板块旨在分享一些实用小工具,它们往往是轻量且简洁的,是笔者对于日常生活进行观察后获得的灵感,然后通过编码将自己的Idea实现。要说明的是,这种实现很大可能不是最优的,总会存在这样那样的局限性,

1. 问题的引出

作为21世纪的人,比如看到这篇文章的你(您),总有需要"借鉴"别人代码的时候,这时候可能就会去CSDN,博客园等去找寻,然后使用无敌的“CV”大法占为己有。这不,笔者今天正想着入门OpenCV,配置好OpenCV的环境后,在CSDN上CV了如下代码,用以测试环境配置是否成功:

1.  #include <opencv2\opencv.hpp> //加载OpenCV 4.1头文件
2.  #include <iostream>
3.
4.  using namespace std;
5.  using namespace cv; //opencv的命名空间
6.
7.  int main()
8. {
	9.    Mat img; //声明一个保存图像的类
	10.    img = imread("G:/opencv/lena.png"); //读取图像,根据图片所在位置填写路径即可
	11.    if (img.empty()) //判断图像文件是否存在
		12.    {
		13.      cout << "请确认图像文件名称是否正确" << endl;
		14.      return -1;
		15.    }
	16.    imshow("test", img); //显示图像
	17.    waitKey(0); //等待键盘输入
	18.    return 0; //程序结束
	19.  }

观察上面代码,发现每行开头总有序号,代码不长时倒还好,可以一个个去掉,但当行数上百、上千甚至上万时,手动去除可就不妙了。

笔者是个懒人,即便copy的代码不到20行,也不想手动完成这种琐事,于是花了近1小时来实现、调试、完善和泛化行号去除的功能。用程序处理后的代码文本如下:

  #include  //加载OpenCV 4.1头文件
  #include 

  using namespace std;
  using namespace cv; //opencv的命名空间

int main()
 {
    Mat img; //声明一个保存图像的类
    img = imread("G:/opencv/lena.png"); //读取图像,根据图片所在位置填写路径即可
    if (img.empty()) //判断图像文件是否存在
    {
      cout << "请确认图像文件名称是否正确" << endl;
      return -1;
    }
    imshow("test", img); //显示图像
    waitKey(0); //等待键盘输入
    return 0; //程序结束
  }

2. 问题解决方案

问题描述: 给定一个文本文件,其中每一行的开头都可能有(或没有)序号,序号形式通常为xxx.xxx:等,请读取文本文件,去除文本文件中每一行开始的序号,将运行结果保存在另一个文件中。

解决方案通过C/C++的文件操作逐行读取字符串,去除其中的序号后再逐行输出到保存文件中。去除序号的关键特征为分隔符".",考虑到分隔符的多样性,这里交由用户来决定,即在文件的第一行输入分隔符,但考虑很多情况下序号的分隔符就是".",而且用户更倾向于把代码贴到文本文件中就完事了。为了便利起见,笔者设默认分隔符为"."。这样,即便用户没有在第一行输入分隔符,程序也能正常进行。

关于程序的使用步骤和其余细节,尤其是文件的输入部分(fscanf()fgets()),详见代码实现。

3. 代码实现

/*
根据分隔符去除文本的前缀部分
例如:chsplit = '.'时,代表将文本文件中每一行第一个'.'及之前的所有字符滤去
====================使用说明==================== 
1. 使用前,先创建名为data_in.txt的文本文件; 
2. 在文本第一行,填写特征分隔符,比如,你要去掉每行代码的序号"xxx.",
此时你就在第一行写'.',程序将把每行第一个'.'及之前的字符去除(第一行只能有一个字符); 
3. 在第一行后粘贴需要修改的代码,保存并关闭文件;
4. 运行代码生成的.exe文件,运行结果保存在了data_out.txt中。 
	
Author: 圣☆哥
E-Mail: [email protected]
IDE: DevCpp5.4.0 
Create Date:2021/12/14
Update Date:2021/12/14
CSDN Blog: https://me.csdn.net/weixin_42430021
*/

#include 
#include 
#include
#include
#define maxn 1005
char buff[maxn];
using namespace std;

// 检查buff中是否只有一个非空字符 
bool checkOneChar(){
	int n = strlen(buff);
	int cnt = 0;
	for (int i=0; i<n; ++i){
		if(buff[i] != ' '){
			cnt++;
			if(cnt > 1)
				return false;
		}
	}
	return cnt == 1;
}

int main(){
	FILE* fin = NULL;
	FILE* fout = NULL;
	char chsplit='.'; 
	fin = fopen("./data_in.txt", "rb");
	fout = fopen("./data_out.txt", "wb");
	if(!fin){
		printf("data_in.txt read error. Please check if the name of text file is correct\n");
		getchar();
		exit(-1);
	}
	if(!fout){
		printf("data_out.txt write error."
		"Please insure the file is not occupied by other process.\n");		
		getchar();
		exit(-1);
	}
	fscanf(fin, "%s", buff);
	while (fgetc(fin) != '\n') continue; // 滤去换行符 
	if(!checkOneChar()){ // 第一行有且仅有一个字符 
		printf("Warning: The first line of data_in.txt must be one character for left striping.\n"
		"I assume that you want to use \'.\' to left strip the text file.\n");
		rewind(fin);
	}
	else{
		chsplit = buff[0];
	}
	
	while (fgets(buff, maxn, fin)){
		string s(buff);
		fprintf(fout, "%s", s.substr(s.find_first_of(chsplit)+1).c_str());
	}
	fclose(fin);
	fclose(fout);
	printf("Done!\n");
	getchar();
	return 0;
}

4. 运行结果

这里就把输入和输出文件展示一下,注意输入文件的命名是固定的data_in.txt

【Gizmos】#001 Copy的代码中有行号且去除麻烦?试试代码前缀“去质器“_第1张图片

5. 不足之处

  1. 只能处理前缀;

  2. 只是以单字符为特征来分割字符串,不过考虑到应用场景主要是代码的序号去除,这不是啥大问题;

  3. 没有考虑代码的对齐,这个步骤笔者就暂时交由编辑器实现了;

  4. 其余笔者没有想到的、潜在的bug和不足…

写在最后

我想每个程序员都应该有着 “To be a Dream Weaver” 这样的理想,即能够将任何理论可行的想法变成现实,虽然这么说很夸张,毕竟人的精力有限,“术业有专攻”,但是,人要有梦想嘛。

“总有一天,我要成为神奇宝贝大师” —— 小智

笔者水平有限,欢迎批评指正~

你可能感兴趣的:(Gizmos,c++,文件操作,小工具)