(50 marks) A string in C++ is simply an array of characters with the null charac
ID: 3871012 • Letter: #
Question
(50 marks) A string in C++ is simply an array of characters with the null character() used to mark the end of the string. C++ provides a set of string handling function in <string.h> as well as I/O functions in <iostream>. With the addition of the STL (Standard Template Library), C++ now provides a string class.
But for this assignment, you are to develop your own string class. This will give you a chance to develop and work with a C++ class, define constructors and destructors, define member functions outside of the class body, develop a copy constructor and assignment operator (and understand why!), work with C-Style strings and pointers, dynamically allocate memory and free it when done.
Of course, you must also do suitable testing which implies writing a main function that uses your new string class. Submit your assignment under URCourses.
The following is the skeleton of the Mystring class declaration. Mystring.h file is provided. You must produce the Mystring.cpp and main.cpp files.
class Mystring { private: char *pData; //pointer to simple C-style representation of the string //(i.e., sequence of characters terminated by null) //pData is only a pointer. You must allocate space for //the actual character data int length; //length of the string
//… //possibly other private data
public: MyString(); //constructor --- create empty string MyString(char *cString); //constructor --- create a string whose data is a copy of //cString ~MyString(); //destructor -- don't forget to free space allocated by the constructor //i.e., the space allocated for the character data
MyString(MyString const& s); //override the default copy constructor --- why? //important -- think about it -- possible test question MyString operator = (MyString const& s); //override default assignment operator void Put(); //output string void Reverse(); //reverse the string MyString operator + (MyString const& s); //concatenation operator // … //other useful member functions //as you wish };
Explanation / Answer
#include <iterator>
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <string>
class CSVRow
{
public:
std::string const& operator[](std::size_t index) const
{
return m_data[index];
}
std::size_t size() const
{
return m_data.size();
}
void readNextRow(std::istream& str)
{
std::string line;
std::getline(str, line);
std::stringstream lineStream(line);
std::string cell;
m_data.clear();
while(std::getline(lineStream, cell, ','))
{
m_data.push_back(cell);
}
// This checks for a trailing comma with no data after it.
if (!lineStream && cell.empty())
{
// If there was a trailing comma then add an empty element.
m_data.push_back("");
}
}
private:
std::vector<std::string> m_data;
};
std::istream& operator>>(std::istream& str, CSVRow& data)
{
data.readNextRow(str);
return str;
}
int main()
{
std::ifstream file("plop.csv");
CSVRow row;
while(file >> row)
{
std::cout << "4th Element(" << row[3] << ") ";
}
}
But with a little work we could technically create an iterator:
class CSVIterator
{
public:
typedef std::input_iterator_tag iterator_category;
typedef CSVRow value_type;
typedef std::size_t difference_type;
typedef CSVRow* pointer;
typedef CSVRow& reference;
CSVIterator(std::istream& str) :m_str(str.good()?&str:NULL) { ++(*this); }
CSVIterator() :m_str(NULL) {}
// Pre Increment
CSVIterator& operator++() {if (m_str) { if (!((*m_str) >> m_row)){m_str = NULL;}}return *this;}
// Post increment
CSVIterator operator++(int) {CSVIterator tmp(*this);++(*this);return tmp;}
CSVRow const& operator*() const {return m_row;}
CSVRow const* operator->() const {return &m_row;}
bool operator==(CSVIterator const& rhs) {return ((this == &rhs) || ((this->m_str == NULL) && (rhs.m_str == NULL)));}
bool operator!=(CSVIterator const& rhs) {return !((*this) == rhs);}
private:
std::istream* m_str;
CSVRow m_row;
};
int main()
{
std::ifstream file("plop.csv");
for(CSVIterator loop(file); loop != CSVIterator(); ++loop)
{
std::cout << "4th Element(" << (*loop)[3] << ") ";
}
}
std::vector<std::string> vec;
using namespace boost;
tokenizer<escaped_list_separator<char> > tk(
line, escaped_list_separator<char>('\', ',', '"'));
for (tokenizer<escaped_list_separator<char> >::iterator i(tk.begin());
i!=tk.end();++i)
{
vec.push_back(*i);
}
void foo()
{
std::string data = "1,2,3,4,5 "
"0,2,4,6,8 "
"1,3,5,7,9 ";
strtk::token_grid grid(data,data.size(),",");
for(std::size_t i = 0; i < grid.row_count(); ++i)
{
strtk::token_grid::row_type r = grid.row(i);
for(std::size_t j = 0; j < r.size(); ++j)
{
std::cout << r.get<int>(j) << " ";
}
std::cout << std::endl;
}
std::cout << std::endl;
}
using namespace std;
int main()
{
//
CsvWorker csv;
csv.loadFromFile("example.csv");
cout << csv.getRowsNumber() << " " << csv.getColumnsNumber() << endl;
csv.getFieldRef(0, 2) = "0";
csv.getFieldRef(1, 1) = "0";
csv.getFieldRef(1, 3) = "0";
csv.getFieldRef(2, 0) = "0";
csv.getFieldRef(2, 4) = "0";
csv.getFieldRef(3, 1) = "0";
csv.getFieldRef(3, 3) = "0";
csv.getFieldRef(4, 2) = "0";
for(unsigned int i=0;i<csv.getRowsNumber();++i)
{
//cout << csv.getRow(i) << endl;
for(unsigned int j=0;j<csv.getColumnsNumber();++j)
{
cout << csv.getField(i, j) << ".";
}
cout << endl;
}
csv.saveToFile("test.csv");
//
CsvWorker csv2(4,4);
csv2.getFieldRef(0, 0) = "a";
csv2.getFieldRef(0, 1) = "b";
csv2.getFieldRef(0, 2) = "r";
csv2.getFieldRef(0, 3) = "a";
csv2.getFieldRef(1, 0) = "c";
csv2.getFieldRef(1, 1) = "a";
csv2.getFieldRef(1, 2) = "d";
csv2.getFieldRef(2, 0) = "a";
csv2.getFieldRef(2, 1) = "b";
csv2.getFieldRef(2, 2) = "r";
csv2.getFieldRef(2, 3) = "a";
csv2.saveToFile("test2.csv");
return 0;
}
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <iostream>
#include <string>
namespace qi = boost::spirit::qi;
namespace bascii = boost::spirit::ascii;
template <typename Iterator>
struct csv_parser : qi::grammar<Iterator, std::vector<std::string>(),
bascii::space_type>
{
qi::rule<Iterator, char() > COMMA;
qi::rule<Iterator, char() > DDQUOTE;
qi::rule<Iterator, std::string(), bascii::space_type > non_escaped;
qi::rule<Iterator, std::string(), bascii::space_type > escaped;
qi::rule<Iterator, std::string(), bascii::space_type > field;
qi::rule<Iterator, std::vector<std::string>(), bascii::space_type > start;
csv_parser() : csv_parser::base_type(start)
{
using namespace qi;
using qi::lit;
using qi::lexeme;
using bascii::char_;
start = field % ',';
field = escaped | non_escaped;
escaped = lexeme['"' >> *( char_ -(char_('"') | ',') | COMMA | DDQUOTE) >> '"'];
non_escaped = lexeme[ *( char_ -(char_('"') | ',') ) ];
DDQUOTE = lit("""") [_val = '"'];
COMMA = lit(",") [_val = ','];
}
};
int main()
{
std::cout << "Enter CSV lines [empty] to quit ";
using bascii::space;
typedef std::string::const_iterator iterator_type;
typedef csv_parser<iterator_type> csv_parser;
csv_parser grammar;
std::string str;
int fid;
while (getline(std::cin, str))
{
fid = 0;
if (str.empty())
break;
std::vector<std::string> csv;
std::string::const_iterator it_beg = str.begin();
std::string::const_iterator it_end = str.end();
bool r = phrase_parse(it_beg, it_end, grammar, space, csv);
if (r && it_beg == it_end)
{
std::cout << "Parsing succeeded ";
for (auto& field: csv)
{
std::cout << "field " << ++fid << ": " << field << std::endl;
}
}
else
{
std::cout << "Parsing failed ";
}
}
return 0;
}
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <string>
using namespace std;
int main() {
string filename = "test.bin";
// Write to File
ofstream fout(filename.c_str(), ios::out | ios::binary);
if (!fout.is_open()) {
cerr << "error: open file for output failed!" << endl;
abort();
}
int i = 1234;
double d = 12.34;
fout.write((char *)&i, sizeof(int));
fout.write((char *)&d, sizeof(double));
fout.close();
// Read from file
ifstream fin(filename.c_str(), ios::in | ios::binary);
if (!fin.is_open()) {
cerr << "error: open file for input failed!" << endl;
abort();
}
int i_in;
double d_in;
fin.read((char *)&i_in, sizeof(int));
cout << i_in << endl;
fin.read((char *)&d_in, sizeof(double));
cout << d_in << endl;
fin.close();
return 0;
}
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <string>
using namespace std;
int main() {
string filename = "test.bin";
// Write to File
ofstream fout(filename.c_str(), ios::out | ios::binary);
if (!fout.is_open()) {
cerr << "error: open file for output failed!" << endl;
abort();
}
int i = 1234;
double d = 12.34;
fout.write((char *)&i, sizeof(int));
fout.write((char *)&d, sizeof(double));
fout.close();
// Read from file
ifstream fin(filename.c_str(), ios::in | ios::binary);
if (!fin.is_open()) {
cerr << "error: open file for input failed!" << endl;
abort();
}
int i_in;
double d_in;
fin.read((char *)&i_in, sizeof(int));
cout << i_in << endl;
fin.read((char *)&d_in, sizeof(double));
cout << d_in << endl;
fin.close();
return 0;
}
Related Questions
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.