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文件(全) 的相关文章

  • Func 方法参数的首选命名约定是什么?

    我承认这个问题是主观的 但我对社区的观点感兴趣 我有一个缓存类 它采用类型的缓存加载器函数Func
  • 如何在C++中实现模板类协变?

    是否可以以这样一种方式实现类模板 如果模板参数相关 一个对象可以转换为另一个对象 这是一个展示这个想法的例子 当然它不会编译 struct Base struct Derived Base template
  • FFMPEG Seeking 带来音频伪影

    我正在使用 ffmpeg 实现音频解码器 在读取音频甚至搜索已经可以工作时 我无法找到一种在搜索后清除缓冲区的方法 因此当应用程序在搜索后立即开始读取音频时 我没有任何工件 avcodec flush buffers似乎对内部缓冲区没有任何
  • Cygwin 下使用 CMake 编译库

    我一直在尝试使用 CMake 来编译 TinyXML 作为一种迷你项目 尝试学习 CMake 作为补充 我试图将其编译成动态库并自行安装 以便它可以工作 到目前为止 我已经设法编译和安装它 但它编译成 dll 和 dll a 让它工作的唯一
  • 为什么禁止在 constexpr 函数中使用 goto?

    C 14 对你能做什么和不能做什么有规则constexpr功能 其中一些 没有asm 没有静态变量 看起来相当合理 但标准也不允许goto in constexpr功能 即使它允许其他控制流机制 这种区别背后的原因是什么 我以为我们已经过去
  • C# 中可空类型是什么?

    当我们必须使用nullable输入 C net 任何人都可以举例说明 可空类型 何时使用可空类型 https web archive org web http broadcast oreilly com 2010 11 understand
  • 将字符串从非托管代码传递到托管

    我在将字符串从非托管代码传递到托管代码时遇到问题 在我的非托管类中 非托管类 cpp 我有一个来自托管代码的函数指针 TESTCALLBACK FUNCTION testCbFunc TESTCALLBACK FUNCTION 接受一个字符
  • 使用 C# 在 WinRT 中获取可用磁盘空间

    DllImport kernel32 dll SetLastError true static extern bool GetDiskFreeSpaceEx string lpDirectoryName out ulong lpFreeBy
  • c 中的错误:声明隐藏了全局范围内的变量

    当我尝试编译以下代码时 我收到此错误消息 错误 声明隐藏了全局范围内的变量 无效迭代器 节点 根 我不明白我到底在哪里隐藏或隐藏了之前声明的全局变量 我怎样才能解决这个问题 typedef node typedef struct node
  • 基于范围的 for 循环中的未命名循环变量?

    有没有什么方法可以不在基于范围的 for 循环中 使用 循环变量 同时也避免编译器发出有关未使用它的警告 对于上下文 我正在尝试执行以下操作 我启用了 将警告视为错误 并且我不想进行像通过在某处毫无意义地提及变量来强制 使用 变量这样的黑客
  • 使用向量的 merge_sort 在少于 9 个输入的情况下效果很好

    不知何故 我使用向量实现了合并排序 问题是 它可以在少于 9 个输入的情况下正常工作 但在有 9 个或更多输入的情况下 它会执行一些我不明白的操作 如下所示 Input 5 4 3 2 1 6 5 4 3 2 1 9 8 7 6 5 4 3
  • 是否有比 lex/flex 更好(更现代)的工具来生成 C++ 分词器?

    我最近将源文件解析添加到现有工具中 该工具从复杂的命令行参数生成输出文件 命令行参数变得如此复杂 以至于我们开始允许它们作为一个文件提供 该文件被解析为一个非常大的命令行 但语法仍然很尴尬 因此我添加了使用更合理的语法解析源文件的功能 我使
  • 像“1$”这样的位置参数如何与 printf() 一起使用?

    By man I find printf d width num and printf 2 1 d width num 是等价的 但在我看来 第二种风格应该与以下相同 printf d num width 然而通过测试似乎man是对的 为什
  • .NET 选项将视频文件流式传输为网络摄像头图像

    我有兴趣开发一个应用程序 它允许我从 xml 构建视频列表 包含视频标题 持续时间等 并将该列表作为我的网络摄像头流播放 这意味着 如果我要访问 ustream tv 或在实时通讯软件上激活我的网络摄像头 我的视频播放列表将注册为我的活动网
  • 检查 url 是否指向文件或页面

    我们需要以下内容 如果文件确实是文件 则从 URL 下载该文件 否则 如果它是一个页面 则什么也不做 举个简单的例子 我有以下命令来下载文件 My Computer Network DownloadFile http www wired c
  • EPPlus Excel 更改单元格颜色

    我正在尝试将给定单元格的颜色设置为另一个单元格的颜色 该单元格已在模板中着色 但worksheet Cells row col Style Fill BackgroundColor似乎没有get财产 是否可以做到这一点 或者我是否必须在互联
  • 如何在内存中存储分子?

    我想将分子存储在内存中 这些可以是简单的分子 Methane CH4 C H bond length 108 7 pm H H angle 109 degrees But also more complex molecules like p
  • 窗体最大化时自动缩放子控件

    有没有办法在最大化屏幕或更改分辨率时使 Windows 窗体上的所有内容自动缩放 我发现手动缩放它是正确的 但是当切换分辨率时我每次都必须更改它 this AutoScaleDimensions new System Drawing Siz
  • 如何使用 ReactiveList 以便在添加新项目时更新 UI

    我正在创建一个带有列表的 Xamarin Forms 应用程序 itemSource 是一个reactiveList 但是 向列表添加新项目不会更新 UI 这样做的正确方法是什么 列表定义 listView new ListView var
  • 将变量分配给另一个变量,并将一个变量的更改反映到另一个变量中

    是否可以将一个变量分配给另一个变量 并且当您更改第二个变量时 更改会瀑布式下降到第一个变量 像这样 int a 0 int b a b 1 现在 b 和 a 都 1 我问这个问题的原因是因为我有 4 个要跟踪的对象 并且我使用名为 curr

随机推荐

  • 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