c++ 解析.csv文件(全)

2023-11-15

c++ 解析csv文件 

一、项目要求:

(1) 这个程序需要做到将csv文件的内容读取进来解析,并将每一个联系人的数据进行打印;
(2) 用户输入排序的属性key,将排序完成的结果打印出来;
(3) 能够对错误格式的文件进行检测;
(4) 能够对错误的数据进行容错;
(5) 文件编码格式不限,输出为UTF8格式

二、分析问题

1.问题1对与csv文件的读取,要如何读取,想到可以对文件进行读操作的文件方法函数,对文件读取之后怎么去进行将每一行的数据进行剪切成每一个主题。剪切后的数据如何保持,是用二维数组,还是用结构体(分析得出为了后面的任务方便进行,还是用结构体来存储数据是最好的)

2.问题二 属性key的排序,对于排序,比如 用id ,age 等数字型的数据项进行排序,其中的排序是如何实现?是升序还是降序?这个都要了解。排序好了之后怎么再次打印出来,个用户查看等

3.要考虑到csv文件的错误格式有哪些,什么场景下会比较容易产生错误的格式文件,又如何对其进行检测,检测完之后如何让用户更改过来等。

4.问题四 对错误的数据进行容错,首先要知道了解,数据的错误又那些?其中我下面的代码实现中实现两个常见的错误数据例如 用分号注释的字符 "****",或 ","这些,csv文件有编码格式可能不符合,导致解析到数据乱码

三、代码实现

#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>
#include<algorithm>

#include <Windows.h>
using namespace std;

struct student {          //成员结构体

	int id;
	string name;
	int age;
	string hobby;


};
class new_csv {                    //创建一个功能类

public:

	void output(vector<student>& vectorclient);  //排序输出函数

	int examine(int* num, int& bit);
	char* Fault(string sum);


};

std::wstring utf8ToUtf16(const std::string& utf8String)
{
	std::wstring sResult;
	int nUTF8Len = MultiByteToWideChar(CP_UTF8, 0, utf8String.c_str(), -1, NULL, NULL);
	wchar_t* pUTF8 = new wchar_t[nUTF8Len + 1];

	ZeroMemory(pUTF8, nUTF8Len + 1);
	MultiByteToWideChar(CP_UTF8, 0, utf8String.c_str(), -1, pUTF8, nUTF8Len);
	sResult = pUTF8;
	delete[] pUTF8;

	return sResult;
}
LPCWSTR stringToLPCWSTR(std::string orig)
{
	size_t origsize = orig.length() + 1;
	const size_t newsize = 100;
	size_t convertedChars = 0;
	wchar_t* wcstring = (wchar_t*)malloc(sizeof(wchar_t) * (orig.length() - 1));
	mbstowcs_s(&convertedChars, wcstring, origsize, orig.c_str(), _TRUNCATE);
	return wcstring;
}

std::string wstring2string(wstring wstr)
{
	string result;
	//获取缓冲区大小,并申请空间,缓冲区大小事按字节计算的  
	int len = WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), wstr.size(), NULL, 0, NULL, NULL);
	char* buffer = new char[len + 1];
	//宽字节编码转换成多字节编码  
	WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), wstr.size(), buffer, len, NULL, NULL);
	buffer[len] = '\0';
	//删除缓冲区并返回值  
	result.append(buffer);
	delete[] buffer;
	return result;
}
char* UnicodeToUTF8(wchar_t* wszcString)
{
	int utf8Len = ::WideCharToMultiByte(CP_UTF8, NULL, wszcString, int(wcslen(wszcString)), NULL, 0, NULL, NULL);
	char* szUTF8 = new char[utf8Len + 1];    //给'\0'分配空间
	::WideCharToMultiByte(CP_UTF8, NULL, wszcString, int(wcslen(wszcString)), szUTF8, utf8Len, NULL, NULL);    //转换
	szUTF8[utf8Len] = '\0';

	return szUTF8;
}
std::string utf8ToUnicode(const char* route) {
	//return route;
	wstring wfilepath = utf8ToUtf16(route);
	return wstring2string(wfilepath);
}
std::string TCHAR2STRING(TCHAR* STR)
{
	int iLen = ::WideCharToMultiByte(CP_ACP, 0, STR, -1, NULL, 0, NULL, NULL);
	char* chRtn = new char[iLen * sizeof(char)];
	::WideCharToMultiByte(CP_ACP, 0, STR, -1, chRtn, iLen, NULL, NULL);
	std::string str(chRtn);
	return str;
}


//id的排序函数
bool sortid(const student& a, const student& b)
{
	if (a.id < b.id)
	{
		return true;

	}
	else {
		return false;
	}

}

//age排序函数

bool sortage(const student& a, const student& b)
{
	if (a.age < b.age)
	{
		return true;

	}
	else {
		return false;
	}

}

void  new_csv::output(vector<student>& vectorclient)   //排序输出函数
{

	for (vector<student>::iterator it = vectorclient.begin(); it != vectorclient.end(); it++)
	{
		::cout << "id: " << it->id << " name: " << it->name << " age: " << it->age << " hobby: " << it->hobby << endl;
	}

}
int new_csv::examine(int* num, int& bit)   //对输入文件格式进行判断是否有误
{
	for (int i = 1; i < bit - 1; i++)
	{
		if (num[i] == num[i + 1])
		{
			cout << "csv文件对应要求无误" << endl;
			return 0;

		}
		else
			cout << "请检查文件中是否有空格,或文件编写格式有问题,导致文件信息对应不上" << endl;
		return 0;
	}


}

char* new_csv::Fault(string linestr)
{
	char* sum;
	sum = (char*)malloc(100);
	int len_str = strlen(linestr.c_str());
	int k = 0;
	memset(sum, 0, 100);
	for (int j = 0; j < len_str; j++)
	{
		/*if (linestr[j] == '*')
		{
			linestr[j] = ',';
		}*/
		if (linestr[j] == '"' && linestr[j + 1] == '"')                  //对fgets到的数组结尾的换行符进行替换
		{
			sum[k] = linestr[j];
			k++;
			j = j + 1;
		}
		else if (linestr[j] == '"' && linestr[j + 1] != '"') {
		
				sum[k] = linestr[j + 1];
				k++;
				j = j + 1;
			
		}
		else {
			if (linestr[j] == ',' && linestr[j + 1] == '"' && linestr[j-1] =='"')
			{
				sum[k] = '*';
				k++;
			}
			else
			{
				sum[k] = linestr[j];
				
				k++;
			}
		}
	}
	return sum;

}
int main()
{

	ifstream infile("newfile.csv", ios::in);//infile来自fstream,ifstream为输入文件流(从文件读入)

	string linestr;
	int size_1[10] = { 0 };
	char* sum;
	char* Second_sum;
	int n1 = 1;
	new_csv pot;
	vector<student> vectorclient;
	int num = 0;
	string key;
	int k = 0;
	while (getline(infile, linestr)) 		//读入整行数据到linestr里
	{

		n1 = 1;                              //定义对一行中的 逗号分割的每一段进行计数用来判断存储的区域
		sum = pot.Fault(linestr);
		stringstream ss(sum);//来自sstream
		string str;

		if (num > 0)
		{	//实现只对数据写入vector ,不对标题写入,从而进行排序 
			//按照逗号分隔

			student client;

			while (getline(ss, str, ','))    //数据进行循环存储
			{
				
				int len = strlen(str.c_str());
				for (int j = 0; j < len;j++)
				{
					if (str[j] == '*')
					{
						str[j] = ',';
					}
				}
				
				//cout<<str<<endl;
				switch (n1)
				{
				case 1:
					//int intstr = atoi(str);
					//需先将string转成char*
					client.id = atoi(str.c_str());
					break;
				case 2:
					client.name = utf8ToUnicode(str.c_str());
					//client.name = utf8ToUnicode(char1);
					
					break;
				case 3:
					client.age = atoi(str.c_str());
					break;
				case 4:
					client.hobby = str;;// utf8ToUnicode()将一个字符串的UTF8编码转换成Unicode(UCS-2和UCS-4)编码.
					break;


				}
				n1++;

			}
			size_1[num] = n1;

			vectorclient.push_back(client);//每一行client数据都放到vectorclient中去
		}


		num++;
		free(sum);

	}
	pot.examine(size_1, num);    //对错误数据信息类型进行判断
	//未排序 
	::cout << "————csv文件中获取的信息如下————" << endl;
	//输出结果
	pot.output(vectorclient);

	cout << "注意两个有效key id age 请输入要排序的key:" << endl;

	cin >> key;

	if (key == "id")
	{
		sort(vectorclient.begin(), vectorclient.end(), sortid);
		::cout << "————id排序后的信息如下————" << endl;
		pot.output(vectorclient);

	}
	else if (key == "age")
	{

		sort(vectorclient.begin(), vectorclient.end(), sortage);
		::cout << "————age排序后的信息如下————" << endl;
		pot.output(vectorclient);
	}
	else {

		cout << "无输入选项,无法排序,原信息如下" << endl;
		pot.output(vectorclient);
	}

	return 0;
}

运行结果:

 excel(看到文件中乱码,因为设置了不支持utf-8的编码,所以乱码,更改编码可以直接再notepad++中打开更改就行)

vs运行界面(通过代码将utf-8中的编码格式转换为Unicode可以正常输出中文) 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

c++ 解析.csv文件(全) 的相关文章

随机推荐

  • C++——并发之std::async使用注意的坑,以及promise,future

    promise背景1 promise背景2 async 1 async 与promise future 1 1 async以及获取时间 async函数如下所示 template
  • matlab-min函数

    matlab对二维矩阵用min函数的用法如下 C min A 如果A是一个向量 min A 返回A中的最小元素 如果A是一个矩阵 min A 将A的每一列作为一个向量 返回一行向量包含了每一列的最小元素 C min A B 返回一个和A和B
  • 不看绝对血亏!java面试项目中的技术难点

    正文 MyBatis 的整体架构分为三层 分别是基础支持层 核心处理层和接口层 如下图所示 基础支持层 反射模块 该模块对 Java 原生的反射进行了良好的封装 提供了更加简洁易用的 API 方便上层使调用 并且对反射操作进行了一系列优化
  • 一边是计算机就业哀鸿遍野,一边是高考生疯狂涌向计算机专业

    在张雪峰推荐的几大专业里 计算机专业是其中之一 近几年 计算机专业报考热度不减 但就业前景却令人堪忧 互联网裁员接二连三 许多码农找不到工作 一位网友感叹 一边是计算机就业哀鸿遍野 一边是高考生疯狂涌向计算机专业 太魔幻了 有人说 大部分家
  • 解决报错:java.net.BindException: 无法指定被请求的地址

    今天在linux虚拟机上装了tomcat 但是一直启动不了 查看日志 主要报错如下 严重 StandardServer await create localhost 8005 java net BindException 无法指定被请求的地
  • VCS IDEA没有Enable Version Control Intergration

    在使用IDEA 提交git push到远程上 找到快忘了的流程 仿照着一步步来 发现都有一个步骤就是指定使用版本管理工具 Enable Version Control Integration 我这找了找发现没有 确实是有这一步指定 版本管理
  • 基于 springboot+vue 进行多条件查询历史聊天记录

    查询历史聊天记录 多条件查询记录是经常需要进行编写的功能 这里就以多条件查询历史聊天记录为例子来介绍如何进行基于关键字 日期 聊天记录类型 三种条件进行模糊查询 日期拼接 条件拼接查询 前端 抽屉管理 首先我们控制 element ui 的
  • spring-boot+maven运行和调试的配置

    spring boot maven 首先说直接运行 WIP Saved Searches migrated to WS 6 0 NJ数据下载工具 基于spring boot的小工具运行方法 在控制台上跳转到项目里initial文件夹所在的目
  • 火币什么时间服务器维护,火币全球站已于今日21:45进行系统维护,时间?

    8月10日消息 Twitter在6月30日发布的NFT系列 The 140 Collection 在OpenSea NFT市场上创造了1700 ETH 530万美元 的总交易量 虽然这个数字远低于Axis Infinity和CryptoPu
  • 一个简单的CountDownLauch

    这个类的主要功能就是 当多个线程运行的时候 count满足一定的条件的时候 这里为0 部分线程才开始工作 具体如下 include
  • Python py文件打包成 exe文件

    文章目录 安装 pyinstaller 模块 pyinstaller 的使用 pyinstaller 常用参数 多文件打包 安装 pyinstaller 模块 pip install pyinstaller i https pypi tun
  • 个人简历与自我介绍

    尊敬的面试官你好 我叫谢炜豪 我对本次校招的软件研发工程师和C 开发工程师很感兴趣 希望能得到在贵公司发挥作用的机会 以下是我的自我介绍 我所学的专业是计算机科学与技术 在校期间 除了专业的必修课程之外 我还重点学习了C 语言 能够熟练使用
  • linux sftp目录无法切换,linux – SFTP用户无法编辑或创建文件

    要正确chroot sftponly组成员 您需要在 etc ssh sshd config中设置此选项 Subsystem sftp internal sftp Match Group sftponly ChrootDirectory s
  • 多线程入门学习

    多线程 目录 多线程 1 继承Thread类 2 网图下载 3 初识并发问题 4 龟兔赛跑 5 lamda表达式 6 线程休眠Sleep 1 sleep 时间 指定当前线程阻塞的毫秒数 2 sleep存在异常InterruptedExcep
  • canvas圆球碰撞检测

    本文为canvas绘制圆形碰撞检测 圆形与圆形 后期一直更新哦 x 圆横坐标 y 圆纵坐标 r 圆半径 w 浏览器宽度 h 浏览器高度 arc画圆碰撞 move移动后 碰撞浏览器边缘反弹回来 碰撞检测 x r lt 0 浏览器左边缘 x r
  • Android Studio 中的 Gradle 是什么

    Gradle 是什么 学习内容 Gradle 是一个构建系统 在使用 Android Studio 之前 您将Eclipse用于开发目的 而且很可能您不知道如何在没有 Eclipse 的情况下构建您的 Android APK 您可以在命令行
  • 2020年度 个人随笔

    2020年的年度总结其实很好写 for index in 0 2 Log 我太难了 Log 完 2020年这么难 哪里还有心情写总结 回归正题 总结还是要写的 毕竟人老了就爱回忆 就让往事随风 往事随风 随风 风 前言 马上就是2021年了
  • FISCO BCOS JAVA SDK(以HelloWorld合约为例)

    FISCO BCOS JAVA SDK 环境搭建 文章目录 FISCO BCOS JAVA SDK 环境搭建 前言 一 环境准备 1 开发工具 2 开发环境 二 开发步骤 1 创建一个Gradle应用 2 引入Java SDK 3 配置SD
  • 第十届“泰迪杯”B题论文及代码

    正在为您运送作品详情 点击以上链接即可 想看思路可看我另一篇博客
  • c++ 解析.csv文件(全)

    c 解析csv文件 一 项目要求 1 这个程序需要做到将csv文件的内容读取进来解析 并将每一个联系人的数据进行打印 2 用户输入排序的属性key 将排序完成的结果打印出来 3 能够对错误格式的文件进行检测 4 能够对错误的数据进行容错 5