fbpx

C++: CSV Data Manipulation

Bjarne-stroustrup
 

CSV spreadsheet files are suitable for storing tabular data in a relatively portable way. The CSV format is flexible but somewhat ill-defined. For present purposes, authors may assume that the data fields contain no commas, backslashes, or quotation marks.

The task here is to read a CSV file, change some values and save the changes back to a file. For this task we will use the following CSV file:

C1,C2,C3,C4,C5
1,5,9,13,17
2,6,10,14,18
3,7,11,15,19
4,8,12,16,20

#include <map>
#include <vector>
#include <iostream>
#include <fstream>
#include <utility>
#include <functional>
#include <string>
#include <sstream>
#include <algorithm>
#include <cctype>

class CSV
{
public:
	CSV(void) : m_nCols( 0 ), m_nRows( 0 )
	{}

	bool open( const char* filename, char delim = ',' )
	{
		std::ifstream file( filename );

		clear();
		if ( file.is_open() )
		{
			open( file, delim );
			return true;
		}

		return false;
	}

	void open( std::istream& istream, char delim = ',' )
	{
		std::string         line;

		clear();
		while ( std::getline( istream, line ) )
		{
			unsigned int nCol = 0;
			std::istringstream    lineStream(line);
			std::string           cell;

			while( std::getline( lineStream, cell, delim ) )
			{
				m_oData[std::make_pair( nCol, m_nRows )] = trim( cell );
				nCol++;
			}
			m_nCols = std::max( m_nCols, nCol );
			m_nRows++;
		}
	}

	bool save( const char* pFile, char delim = ',' )
	{
		std::ofstream ofile( pFile );
		if ( ofile.is_open() )
		{
			save( ofile );
			return true;
		}
		return false;
	}

	void save( std::ostream& ostream, char delim = ',' )
	{
		for ( unsigned int nRow = 0; nRow < m_nRows; nRow++ )
		{
			for ( unsigned int nCol = 0; nCol < m_nCols; nCol++ )
			{
				ostream << trim( m_oData[std::make_pair( nCol, nRow )] );
				if ( (nCol+1) < m_nCols )
				{
					ostream << delim;
				}
				else
				{
					ostream << std::endl;
				}
			}
		}
	}

	void clear()
	{
		m_oData.clear();
		m_nRows = m_nCols = 0;
	}

	std::string& operator()( unsigned int nCol, unsigned int nRow )
	{
		m_nCols = std::max( m_nCols, nCol+1 );
		m_nRows = std::max( m_nRows, nRow+1 );
		return m_oData[std::make_pair(nCol, nRow)];
	}

	inline unsigned int GetRows() { return m_nRows; }
	inline unsigned int GetCols() { return m_nCols; }

private:
	// trim string for empty spaces in begining and at the end
	inline std::string &trim(std::string &s) 
	{

		s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun<int, int>(std::isspace))));
		s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun<int, int>(std::isspace))).base(), s.end());
		return s;
	}

private:
	std::map<std::pair<unsigned int, unsigned int>, std::string> m_oData;

	unsigned int    m_nCols;
	unsigned int    m_nRows;
};


int main()
{
	CSV oCSV;

	oCSV.open( "test_in.csv" );
	oCSV( 0, 0 ) = "Column0";
	oCSV( 1, 1 ) = "100";
	oCSV( 2, 2 ) = "200";
	oCSV( 3, 3 ) = "300";
	oCSV( 4, 4 ) = "400";
	oCSV.save( "test_out.csv" );
	return 0;
}
Output (in test_out.csv):
Column0,C2,C3,C4,C5
1,100,9,13,17
2,6,200,14,18
3,7,11,300,19
4,8,12,16,400

SOURCE

Content is available under GNU Free Documentation License 1.2.

Our team found a curious site for our readers that are fans of online gaming, a rather exciting site that provides the latest gaming technology. Casinodots.com is the site, they compile the best reviews of MGA casino utan svensk licens sites. This site might pique your curiosity and you can win extra money!