Using a print function to output to a new file - c++

I have a program analyzing the number of distinct and total words in a text file and then writing it to a new output file. I've got the first part down, but I don't know how to get my print function to print onto the new text file. Printing the total words or distinct words onto the new file works but the Print2() function doesn't seem to work. Please take a look at the //POINT OF INTEREST// section, where i believe the problem stems.
#include <iostream>
#include <fstream>
#include <string>
#include <cctype>
int distinctWord = 0;
using namespace std;
typedef int ItemType;
struct Node {
string word;
int count = 1;
Node* left;
Node* right;
};
class TreeType {
private:
Node* root;
void Insert(Node*& root, string word);
void Destroy(Node*& root);
void PrintTree(Node* root);
void Print2File(Node* root, ofstream& fout);
public:
TreeType() {root = nullptr;}
~TreeType();
void PutItem(string word);
void Print();
void Print2(ofstream& fout);
};
void TreeType::Print() {
PrintTree(root);
cout << endl;
}
void TreeType::PrintTree(Node* root) {
if (root == nullptr)
return;
PrintTree(root->left);
cout << root->word << " " << root->count << endl;
PrintTree(root->right);
}
///////////////POINT OF INTEREST///////////////////////////
///////////////POINT OF INTEREST///////////////////////////
void TreeType::Print2File(Node* root, ofstream& fout){
if (root == nullptr)
return;
PrintTree(root->left);
fout << root->word << " " << root->count << endl;
PrintTree(root->right);
}
void TreeType::Print2(ofstream& fout) {
Print2File(root, fout);
cout << "Printed to another file" << endl;
}
///////////////POINT OF INTEREST///////////////////////////
///////////////POINT OF INTEREST///////////////////////////
void TreeType::PutItem(string word) {
Insert(root, word);
}
void TreeType::Insert(Node*& root, string word) {
if (root == nullptr) {
root = new Node;
distinctWord++;
root->word = word;
root->right = nullptr;
root->left = nullptr;
return;
}
if(root->word == word){
root->count++;
return;
}else if (word < root->word)
Insert(root->left, word);
else
Insert(root->right, word);
}
TreeType::~TreeType() {
Destroy(root);
}
int main(int argc, const char * argv[]) {
int totalwords = 0;
ifstream file;
string word;
char c;
ofstream fout;
ifstream file;
string filename;
cout << "Enter name of file with text to analyze: ";
cin >> filename;
fin.open(filename.c_str());
if (fin.fail()) {
cout << "Error opening file.\n";
exit(1);
}
cout << "\nAnalyzing " << filename << ".\n";
TreeType t;
while(!file.eof()){
file.get(c);
if(isalpha(c) || c == '\''){
word += c;
c = '\0';
}else if(c == ' ' || c == '\n' || c == '-' || c == '.'){
if(isalpha(word[0])){
transform(word.begin(), word.end(), word.begin(), ::tolower);
t.PutItem(word);
totalwords++;
word = "";
c = '\0';
}
}
}if(isalpha(word[0])){
transform(word.begin(), word.end(), word.begin(), ::tolower);
t.PutItem(word);
totalwords++;
}
file.close();
fout.open("results.txt");
cout << "\nWord counts:\n\n";
t.Print();
t.Print2(fout);
cout << "\nTotal number of words in text: " << totalwords << ".\n";
fout << "\nTotal number of words in text: " << totalwords << ".\n";
cout << "Number of distinct words appearing in text: "
<< distinctWord << ".\n";
fout << "Number of distinct words appearing in text: "
<< distinctWord << ".\n";
fout.close();
return 0;
}

You will have to pass your output file stream to your
PrintTree(root); too.
Right now you are printing to cout which will dump everything to whatever console your application is associated with.
The modified function after adding the ofstream parameter becomes:
void TreeType::PrintTree(Node* root, ofstream &fout) {
if (root == nullptr)
return;
PrintTree(root->left, fout);
fout << root->word << " " << root->count << endl;
PrintTree(root->right, fout);
}
You will need to pass the ofstream object throughout in all callers of PrintTree

Related

AVLTree can't find data when searched for

I am working on an assignment for school. I have to create an AVLTree, read data from a text file and then create Professor object with that data. However, when I try and search for a Professor by name, it can't be found. It keeps defaulting to Michael Scott in the program and can't find who I'm looking for. My readFromFile function works perfectly and gets me all the data from the file, so I have the data. At this point it's a matter of issues with the AVL Tree. I'll link everything below.
Driver.cpp:
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include "AVLTree.h"
using namespace std;
void readFromFile(AVLTree *treeAccess) {
int numOfProfs = 0;
string line;
const char *path="/Users/collinchappell/Desktop/Program4Official/Program4Official/ProfessorData.txt";
fstream myFile (path, ios::in);
if (!myFile) {
cout << "Sorry can't read ProfessorData.txt!" << endl;
}
else {
// Splitting up all the data in the .txt file and the looping through using string stream
// Not the best solution, however nothing else would work for me so this is what I went with.
while (getline(myFile, line)) {
string n;
string nT;
string s;
int b1,b2,b3,b4,b5,b6,b7;
replace(line.begin(), line.end(), '$', ' ');
stringstream ss(line);
for (int k = 0; k < 11; k++) {
ss >> n;
ss >> nT;
n = n + " " + nT;
ss >> s;
ss >> b1;
ss >> b2;
ss >> b3;
ss >> b4;
ss >> b5;
ss >> b6;
ss >> b7;
numOfProfs++;
Professor p(n, s, b1, b2, b3, b4, b5, b6, b7);
cout << p;
treeAccess->insertNode(n, &p);
}
}
}
cout << numOfProfs << " Proffesors have added from the file." << endl << endl;
}
int main() {
AVLTree tree;
readFromFile(&tree);
bool cont = true;
while (cont) {
cout << "Which Computer Science professor do you want details about?" << endl;
tree.displayInOrder();
cout << endl << endl << "Type Professor Name: ";
string typeName;
getline(cin, typeName);
while (tree.searchNode(typeName) == NULL) {
cout << "Couldn't find that professor! Please type another: ";
getline(cin, typeName);
}
cout << tree.searchNode(typeName);
cout << "Would you like to search another? (Y/N): ";
string ans;
cin >> ans;
if (ans == "y" || ans == "Y") {
continue;
}
else if (ans == "n" || ans == "N") {
return 0;
}
}
return 0;
}
AVLTree.h:
#ifndef AVLTree_h
#define AVLTree_h
#include <iostream>
#include "Professor.h"
using namespace std;
class AVLTree {
private:
// TreeNode structure
struct TreeNode {
string name;
Professor *prof;
struct TreeNode* left;
struct TreeNode* right;
};
// Root of tree
TreeNode* root;
// Function declarations
void insert(TreeNode *&nodePtr, TreeNode *&newNode);
void destroySubTree(TreeNode *nodePtr);
void displayInOrder(TreeNode *nodePtr) const;
int height(TreeNode *nodePtr);
int diff(TreeNode *nodePtr);
void balance(TreeNode *&temp);
TreeNode* l_rotation(TreeNode *parent) {
TreeNode *temp;
temp = parent->right;
parent->right = temp->left;
temp->left = parent;
return temp;
}
TreeNode* r_rotation(TreeNode *parent) {
TreeNode *temp;
temp = parent->left;
parent->left = temp->right;
temp->right = parent;
return temp;
}
TreeNode* lr_rotation(TreeNode *parent) {
TreeNode *temp;
temp = parent->left;
parent->left = (l_rotation(temp));
return r_rotation(parent);
}
TreeNode* rl_rotation(TreeNode *parent) {
TreeNode *temp;
temp = parent->right;
parent->right = (r_rotation(temp));
return l_rotation(parent);
}
public:
AVLTree() { // Constructor
root = NULL;
}
~AVLTree() { // Destructor
destroySubTree(root);
}
void insertNode(string n, Professor* professor);
Professor* searchNode(string);
// Call private displayInOrder()
void displayInOrder() const {
displayInOrder(root);
}
};
#endif /* AVLTree_h */
AVLTree.cpp:
#include <iostream>
#include "AVLTree.h"
using namespace std;
// Insert a node into the tree recursively
void AVLTree::insert(TreeNode *&nodePtr, TreeNode *&newNode) {
if (nodePtr == NULL) {
nodePtr = newNode;
}
else if (newNode->name < nodePtr->name) {
insert(nodePtr->left, newNode);
balance(nodePtr);
}
else {
insert(nodePtr->right, newNode);
balance(nodePtr);
}
}
// Destory the sub tree
void AVLTree::destroySubTree(TreeNode *nodePtr) {
if (nodePtr) {
if (nodePtr->left) {
destroySubTree(nodePtr->left);
}
if (nodePtr->right) {
destroySubTree(nodePtr->right);
}
delete nodePtr;
}
}
// Display the tree in order
void AVLTree::displayInOrder(TreeNode *nodePtr) const {
if (nodePtr) {
displayInOrder(nodePtr->left);
cout << nodePtr->name << endl;
displayInOrder(nodePtr->right);
}
}
// Get the tree's height
int AVLTree::height(TreeNode *temp) {
int leftHeight, rightHeight;
if (temp) {
leftHeight = height(temp->left);
rightHeight = height(temp->right);
if (leftHeight > rightHeight) {
return leftHeight + 1;
}
else if (leftHeight < rightHeight) {
return rightHeight + 1;
}
else {
return 0;
}
}
return 0;
}
// Get the difference
int AVLTree::diff(TreeNode *temp) {
int l_height = height(temp->left);
int r_height = height(temp->right);
return l_height - r_height;
}
// Balance the tree
void AVLTree::balance(TreeNode *&temp) {
int bal_factor = diff (temp);
if (bal_factor > 1)
{
if (diff(temp->left) > 0) // 2, 1 RIGHT
{
temp = r_rotation(temp);
cout << "\nRIGHT rotation";
}
else // 2, -1 LEFT-RIGHT
{
temp = lr_rotation(temp);
cout << "\nLEFT-RIGHT rotation";
}
}
else if (bal_factor < -1)
{
if (diff (temp->right) > 0) // -2, 1 RIGHT-LEFT
{
temp = rl_rotation(temp);
cout << "\nRIGHT-LEFT rotation";
}
else // -2, -1 LEFT
{
temp = l_rotation(temp);
cout << "\nLEFT Rotation";
}
}
}
// Insert a node, calls the private insert function
void AVLTree::insertNode(string n, Professor *proffesor) {
TreeNode *newNode = NULL; // Pointer to a new node.
newNode = new TreeNode;
newNode->name = n;
newNode->prof = proffesor;
newNode->left = newNode->right = NULL;
// Insert the node.
insert(root, newNode);
}
Professor* AVLTree::searchNode(string s) {
cout << "Name inputted into search: " << s << endl;
cout << endl << "Actual name: " << root->name << endl;
TreeNode *nodePtr = root;
while (nodePtr != NULL) {
if (nodePtr->name == s) {
return nodePtr->prof;
}
else if (nodePtr->name > s) {
nodePtr = nodePtr->left;
cout << "Left -> " << nodePtr << endl;
}
else {
nodePtr = nodePtr->right;
cout << "Right -> " << nodePtr << endl;
}
}
return NULL;
}
Professor.h:
#ifndef PROFESSOR_H
#define PROFESSOR_H
#include <iostream>
#include <iomanip>
using namespace std;
class Professor
{
private:
string name;
string course;
bool clearGrading;
bool goodFeedback;
bool caring;
bool reachable;
bool toughGrader;
bool lectureHeavy;
bool attendance;
public:
Professor(string n, string course, bool cG, bool gF, bool c, bool r, bool tG, bool lH, bool a) {
this->name = n;
this->course = course;
this->clearGrading = cG;
this->goodFeedback = gF;
this->caring = c;
this->reachable = r;
this->toughGrader = tG;
this->lectureHeavy = lH;
this->attendance = a;
}
friend ostream &operator << (ostream &strm, Professor &p)
{
strm << endl << endl;
strm << setw(30) << "Professor:" << setw(20) << p.name << endl;
strm << setw(30) << "Course:" << setw(20) << p.course << endl;
strm << setw(30) << "Clear Grading Criteria:" << setw(20);
if(p.clearGrading == 0) strm << "no"; else strm << "yes";
strm << endl;
strm << setw(30) << "Provides Good Feedback:" << setw(20);
if(p.goodFeedback == 0) strm << "no"; else strm << "yes";
strm << endl;
strm << setw(30) << "Caring:" << setw(20);
if(p.caring == 0) strm << "no"; else strm << "yes";
strm << endl;
strm << setw(30) << "Reachable Outside of Class:" << setw(20);
if(p.reachable == 0) strm << "no"; else strm << "yes";
strm << endl;
strm << setw(30) << "Tough Grader:" << setw(20);
if(p.toughGrader == 0) strm << "no"; else strm << "yes";
strm << endl;
strm << setw(30) << "Lecture Heavy:" << setw(20);
if(p.lectureHeavy == 0) strm << "no"; else strm << "yes";
strm << endl;
strm << setw(30) << "Attendance Mandatory:" << setw(20);
if(p.attendance == 0) strm << "no"; else strm << "yes";
strm << endl;
return strm;
}
};
#endif
ProfessorData.txt:
Michael Scott$CSC1310$0$0$1$1$0$1$1$Jim Halpert$CSC1310$1$1$1$0$0$0$0$Pam Beesly$CSC1300$1$1$1$0$1$0$1$Dwight Schrute$CSC2400$1$1$0$0$1$1$1$Angela Martin$CSC1300$1$0$0$0$1$1$1$Kelly Kapoor$CSC1300$0$0$0$0$0$0$0$Andy Bernard$CSC2400$1$0$1$1$0$1$1$Kevin Malone$CSC1310$0$1$1$1$0$0$0$Meredith Palmer$CSC1310$0$1$1$1$0$0$0$Phyllis Vance$CSC1300$1$1$1$0$1$0$0$Oscar Nunez$2400$1$1$1$1$1$1$1$
Running the program:
11 Proffesors have added from the file.
Which Computer Science professor do you want details about?
Andy Bernard
Angela Martin
Dwight Schrute
Jim Halpert
Kelly Kapoor
Kevin Malone
Meredith Palmer
Michael Scott
Oscar Nunez
Pam Beesly
Phyllis Vance
Type Professor Name: Andy Bernard
Name inputted into search: Andy Bernard
Actual name: Michael Scott
Left -> 0x100704570
Left -> 0x105a045b0
Left -> 0x105b04120
Left -> 0x105b041a0
Name inputted into search: Andy Bernard
Actual name: Michael Scott
Left -> 0x100704570
Left -> 0x105a045b0
Left -> 0x105b04120
Left -> 0x105b041a0
0x7ffeefbfee18Would you like to search another? (Y/N):
As you can see, I've put in some prints to kind of debug what's happening. I believe my objects are not getting inserted into the tree right, or my search function is off. Also, I'm not 100% on the balance function. Any help would be amazing.

How can I implement a linked list and allow users to choose a specific node to remove with C++?

I've spent pretty much all day trying to do this, I understand pointers and what a linked list does, but I don't know how to actually code it and all I've found are Java and C examples which don't help because I'm using C++.
Thanks in advance for taking a look at my code and helping me, I really appreciate it considering how many days I've spent stressed out and confused about this. I'm not going to lie so far most of my deleteNode function is probably trash. But like I've said I'm just lost I don't even know where to start or how to progress because I only understand the concepts.
This is my data file.
John Doe 80
Jane Smith 70
Bill Jones 50
Pat Hughes 90
Sam Sosa 40
This is my Header file
#include<string>
using namespace std;
class student {
public:
student(); // constructor method
void st_fn(string fn);
string st_fn();
void st_ln(string ln);
string st_ln();
void st_score(float s);
float st_score();
string st_pass_or_fail();
// need a pointer to the next object
student *nxt_ptr;
protected: // protected can be inherited
float m_score;
string m_ln;
string m_fn;
string m_pf_msg;
};
student::student() //constructor
{
nxt_ptr = NULL;
m_score = 0;
}
void student::st_fn(string fn)
{
m_fn = fn;
}
string student::st_fn()
{
return m_fn;
}
void student::st_ln(string ln)
{
m_ln = ln;
}
string student::st_ln()
{
return m_ln;
}
void student::st_score(float s)
{
m_score = s;
}
float student::st_score()
{
return m_score;
}
string student::st_pass_or_fail()
{
if (m_score >= 60)
m_pf_msg = "PASSED";
else
m_pf_msg = "FAILED";
return m_pf_msg;
}
This is my .cpp file.
#include<iostream>
#include<string>
#include<fstream>
#include "Header.h"
using namespace std;
int display_menu()
{
int option;
cout << endl << endl;
cout << "1. Display List" << endl;
cout << "2. Add a student" << endl;
cout << "3. Delete first student" << endl;
cout << "4. Search by Last Name" << endl;
cout << "5. Exit" << endl;
cin >> option;
return option;
}
student * search_last_name(student *h)
{
student *f = NULL;
student *t = NULL;
string s_ln;
// prompt for last name to search for
cout << "Enter Last Name of the Student";
cin >> s_ln;
if (h != NULL)
{
t = h;
while (t != NULL)
{
if (t->st_ln() == s_ln)
f = t; // found the last name so save t
t = t->nxt_ptr;
}
}
else
cout << "List is empty" << endl;
return f;
}
void add_student(student *&head) // h is the head of the list
{
student *new_st, *r;
string fn, ln;
float s;
cout << "Enter new students first name, last name and score";
cin >> fn >> ln >> s;
// instantiate a new node, use new_st
new_st = new student;
new_st->st_fn(fn);
new_st->st_ln(ln);
new_st->st_score(s);
if (head == NULL)
head = new_st;
else
{
// find the last node, use r for this
// write code
r = head;
while (r->nxt_ptr != nullptr)
r = r->nxt_ptr;
// add to the back of the list
// write code
r->nxt_ptr = new_st;
} // end of else
} // end of add student
student * delete_front(student * head)
{
student *t;
// delete front node
// check for empty list
if (head != NULL)
{
// delete first node
t = head;
head = head->nxt_ptr;
delete(t);
}
else
cout << "List is empty - nothing to delete" << endl;
return head;
}
void deleteNode(struct Node *head, struct Node *n)
{
// When node to be deleted is head node
if (head == n)
{
n = head->next;
//Remove the link of next node
head->next = head->next->next;
return;
}
//When not first node, folow the normal deletion process
//Find the previous node
struct Node *prev = head;
while (prev->next != NULL && prev->next != n)
prev = prev->next;
// Check if node really exists in Linked List
if (prev->next == NULL)
{
cout << endl << "Given node is not present in Linked List";
return;
}
//Remove node from linked list should it exist
prev->next = prev->next->next;
return;
}
void display_list(student *t)
{
if (t == NULL)
cout << "List is Empty!";
else
{
while (t != NULL)
{
cout << "******Student******" << endl;
cout << t->st_ln() << endl;
cout << t->st_fn() << endl;
cout << t->st_score() << endl << endl;
t = t->nxt_ptr;
}
}
}
int main()
{
string ln, fn;
float s;
int n;
ifstream infile;
student *head = NULL; //pointer to a student object
student *cp = NULL; // pointer to end of the list
student *new_st = NULL; // pointer to a new student object
student *f = NULL; // pointer to found node
int option; // the numbe of menu item the user selects
infile.open("lab8d.txt");
while (!infile.eof())
{
infile >> fn >> ln >> s;
//instantiate a student object
new_st = new student;
//load the object with data
new_st->st_fn(fn);
new_st->st_ln(ln);
new_st->st_score(s);
// check for empty list - its a special case
if (head == NULL)
{
head = new_st;
cp = new_st;
}
else // list is not empty
{
cp->nxt_ptr = new_st;
cp = new_st;
}
} // end of loop
// loop to give the user some options
option = display_menu();
while (option != 5)
{
if (option == 1)
display_list(head);
else if (option == 2)
add_student(head);
else if (option == 3)
head = delete_front(head);
else if (option == 4)
{
f = search_last_name(head);
if (f != NULL)
{
cout << f->st_fn() << endl;
cout << f->st_ln() << endl;
cout << f->st_score() << endl;
cout << f->st_pass_or_fail() << endl;
}
else
cout << "Name not in the list" << endl;
}
else if (option == 6)
{
cout << "Enter the number of the node you would like to delete: " << endl;
cin >> n;
}
option = display_menu();
}
system("pause");
return 0;
}
The simpler and self-contained your functions are, the easier they are to test and debug, and the less like they are to fail.
Try something more like this:
Student.h:
#include <string>
class student_list;
class student
{
public:
student();
student(const std::string &fn, const std::string &ln, float s, student *nxt = NULL);
void next(student *s);
student* next() const;
void firstName(const std::string &fn);
std::string firstName() const;
void lastName(const std::string &ln);
std::string lastName() const;
void score(float s);
float score() const;
std::string pass_or_fail() const;
void display(bool showPassOrFail = false) const;
friend class student_list;
protected: // protected can be inherited
student *m_next;
std::string m_fn;
std::string m_ln;
float m_score;
};
Student.cpp:
#include "Student.h"
#include <iostream>
student::student()
: m_next(NULL), m_score(0)
{
}
student::student(const std::string &fn, const std::string &ln, float s, student *nxt)
: m_next(nxt), m_fn(fn), m_ln(ln), m_score(s)
{
}
void student::next(student *s)
{
m_next = s;
}
student* student::next() const
{
return m_next;
}
void student::firstName(const std::string &fn)
{
m_fn = fn;
}
std::string student::firstName() const
{
return m_fn;
}
void student::lastName(const std::string &ln)
{
m_ln = ln;
}
std::string student::lastName() const
{
return m_ln;
}
void student::score(float s)
{
m_score = s;
}
float student::score() const
{
return m_score;
}
std::string student::pass_or_fail() const
{
if (m_score >= 60)
return "PASSED";
else
return "FAILED";
}
void student::display(bool showPassOrFail) const
{
std::cout << lastName() << std::endl;
std::cout << firstName() << std::endl;
std::cout << score() << std::endl;
if (showPassOrFail)
std::cout << pass_or_fail() << std::endl;
}
StudentList.h:
#include <string>
class student;
class student_list
{
public:
student_list();
~student_list();
student* search_last_name(const std::string &ln);
student* insert(const std::string &fn, const std::string &ln, float s, student* after = NULL);
bool remove(int idx);
void display() const;
private:
student *m_head;
};
StudentList.cpp:
student_list::student_list()
: m_head(NULL)
{
}
student_list::~student_list()
{
while (m_head)
remove(0);
}
student* student_list::search_last_name(const std::string &ln)
{
student *t = m_head;
while (t)
{
if (t->lastName() == ln)
break; // found the last name
t = t->next();
}
return t;
}
student* student_list::insert(const std::string &fn, const std::string &ln, float s, student* after)
{
student **r;
if (after)
{
// add to list after the specified node
// get pointer to next node
r = &(after->m_next);
}
else
{
// add to the back of the list
// find pointer to last node
r = &m_head;
while (*r)
r = &((*r)->m_next);
}
// instantiate a new node
student *new_st = new student(fn, ln, s);
if (after)
new_st->next(*r);
// add to list
*r = new_st;
return new_st;
}
bool student_list::remove(int idx)
{
// delete a node at index
// find pointer to node
student **r = &m_head;
while ((*r) && (idx-- > 0))
r = &((*r)->m_next);
if (*r)
{
// delete node
student *t = *r;
*r = t->next();
delete t;
return true;
}
return false;
}
void student_list::display() const
{
student *t = m_head;
if (!t)
std::cout << "List is Empty!" << std::endl;
else
{
do
{
std::cout << "******Student******" << std::endl;
t->display();
t = t->next();
}
while (t);
}
}
Main.cpp:
#include "Student.h"
#include "StudentList.h"
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include <limits>
#include <cstdlib>
int read_number()
{
int value;
while (!(std::cin >> value))
{
std::cout << "Must be a number, try again: ";
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
return value;
}
int display_menu()
{
int option;
std::cout << std::endl << std::endl;
std::cout << "1. Display List" << std::endl;
std::cout << "2. Add a student" << std::endl;
std::cout << "3. Delete first student" << std::endl;
std::cout << "4. Search by Last Name" << std::endl;
std::cout << "5. Delete student by index" << std::endl;
std::cout << "6. Exit" << std::endl << std::endl;
std::cout << "Choice: ";
do
{
option = read_number();
if ((option >= 1) && (option <= 6))
break;
std::cout << "Must be 1..6, try again: ";
}
while (true);
return (option != 6) ? option : -1;
}
int main()
{
student_list students;
std::ifstream infile("lab8d.txt");
if (infile.is_open())
{
student *cp = NULL;
std::string ln, fn;
float s;
while (infile >> fn >> ln >> s)
cp = students.insert(fn, ln, s, cp);
infile.close();
}
// loop to give the user some options
int option; // the number of menu item the user selects
while ((option = display_menu()) != -1)
{
switch (option)
{
case 1:
{
students.display();
break;
}
case 2:
{
// prompt for student info
std::string info;
std::cout << "Enter new student's first name, last name, and score: ";
std::string ln, fn;
float s;
if (std::cin >> fn >> ln >> s)
students.insert(fn, ln, s);
break;
}
case 3:
{
if (!students.remove(0))
std::cout << "List is empty" << std::endl;
break;
}
case 4:
{
// prompt for last name to search for
std::string ln;
std::cout << "Enter Last Name of the Student: ";
if (std::cin >> ln)
{
student *f = students.search_last_name(ln);
if (f)
f->display(true);
else
std::cout << "Name not found in List" << std::endl;
}
break;
}
case 5:
{
std::cout << "Enter the index of the Student to Delete: " << std::endl;
int idx = read_number();
if (!students.remove(idx))
std::cout << "Index not found in List" << std::endl;
break;
}
}
}
std::system("pause");
return 0;
}
That being said, you really should be using the std::list container instead, eg:
Student.h:
#include <string>
class student_list;
class student
{
public:
student();
student(const std::string &fn, const std::string &ln, float s);
void firstName(const std::string &fn);
std::string firstName() const;
void lastName(const std::string &ln);
std::string lastName() const;
void score(float s);
float score() const;
std::string pass_or_fail() const;
void display(bool showPassOrFail = false) const;
friend class student_list;
protected: // protected can be inherited
std::string m_fn;
std::string m_ln;
float m_score;
};
Student.cpp:
#include "Student.h"
#include <iostream>
student::student()
: m_score(0)
{
}
student::student(const std::string &fn, const std::string &ln, float s)
: m_fn(fn), m_ln(ln), m_score(s)
{
}
void student::firstName(const std::string &fn)
{
m_fn = fn;
}
std::string student::firstName() const
{
return m_fn;
}
void student::lastName(const std::string &ln)
{
m_ln = ln;
}
std::string student::lastName() const
{
return m_ln;
}
void student::score(float s)
{
m_score = s;
}
float student::score() const
{
return m_score;
}
std::string student::pass_or_fail() const
{
if (m_score >= 60)
return "PASSED";
else
return "FAILED";
}
void student::display(bool showPassOrFail) const
{
std::cout << lastName() << std::endl;
std::cout << firstName() << std::endl;
std::cout << score() << std::endl;
if (showPassOrFail)
std::cout << pass_or_fail() << std::endl;
}
Main.cpp:
#include "Student.h"
#include <list>
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include <limits>
#include <algorithm>
#include <cstdlib>
int read_number()
{
int value;
while (!(std::cin >> value))
{
std::cout << "Must be a number, try again: ";
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
return value;
}
int display_menu()
{
int option;
std::cout << std::endl << std::endl;
std::cout << "1. Display List" << std::endl;
std::cout << "2. Add a student" << std::endl;
std::cout << "3. Delete first student" << std::endl;
std::cout << "4. Search by Last Name" << std::endl;
std::cout << "5. Delete student by index" << std::endl;
std::cout << "6. Exit" << std::endl << std::endl;
std::cout << "Choice: ";
do
{
option = read_number();
if ((option >= 1) && (option <= 6))
break;
std::cout << "Must be 1..6, try again: ";
}
while (true);
return (option != 6) ? option : -1;
}
int main()
{
std::list<student> students;
std::ifstream infile("lab8d.txt");
if (infile.is_open())
{
std::string ln, fn;
float s;
while (infile >> fn >> ln >> s)
students.push_back(student(fn, ln, s));
infile.close();
}
// loop to give the user some options
int option; // the number of menu item the user selects
while ((option = display_menu()) != -1)
{
switch (option)
{
case 1:
{
if (students.empty())
std::cout << "List is Empty!" << std::endl;
else
{
for(const auto &s : students)
{
std::cout << "******Student******" << std::endl;
s.display();
}
}
break;
}
case 2:
{
// prompt for student info
std::string info;
std::cout << "Enter new student's first name, last name, and score: ";
std::string ln, fn;
float s;
if (std::cin >> fn >> ln >> s)
students.push_back(student(fn, ln, s));
break;
}
case 3:
{
if (students.empty())
std::cout << "List is empty" << std::endl;
else
students.erase(students.begin());
break;
}
case 4:
{
// prompt for last name to search for
std::string ln;
std::cout << "Enter Last Name of the Student: ";
if (std::cin >> ln)
{
auto f = std::find(students.begin(), students.end(),
[&](const student &s){ return (s.lastName() == ln); }
);
if (f != students.end())
f->display(true);
else
std::cout << "Name not found in List" << std::endl;
}
break;
}
case 5:
{
std::cout << "Enter the index of the Student to Delete: " << std::endl;
int idx = read_number();
if ((idx < 0) || (idx >= students.size()))
std::cout << "Index not found in List" << std::endl;
else
students.erase(std::next(students.begin(), idx));
break;
}
}
}
std::system("pause");
return 0;
}

Segmentation Fault 11 on return

I realize there are other answers like this one but seg faults are pretty general and none of them fit my situation exactly. I am creating a binary tree and storing data. In the printInOrder function, it recurses all the way to the furthest leftChild and then seg faults when it reaches the return statement. I am not sure why it is doing this. Thanks in advance for the help.
#include <string>
#include <cstdlib>
#include <iostream>
#include "BST.h"
using namespace std;
BST::BST(void) {
root = NULL;
cout << "Default object is being creating." << "\n";
};
/*
BST::BST(string word, int count) {
cout << "Default object is being creating." << "\n";
this->root->word = word;
this->root->count = count;
};
BST::BST(string word) {
cout << "Default object is being creating." << "\n";
this->root->word = word;
this->root->count = 1;
};
*/
bool BST::hasWord(string word) {
return true;
};
void BST::printInOrder() {
pio(this->root);
}
void BST::pio(struct node* node) {
cout << "root: " << root << endl;
cout << "node: " << node << endl;
cout << "leftChild: " << node->leftChild->leftChild << endl;
if (node != NULL){
/* first recur on left child */
pio(node->leftChild);
/* then print the data of node */
cout << "Word: " << node->word << endl;
cout << "Count: " << node->count << endl;
/* now recur on right child */
pio(node->rightChild);
}
if (node == NULL) {
return;
}
}
void BST::insert(string word)
{
if(this->root != NULL)
insert(word, this->root);
else
{
cout << "obj has been inserted " << endl;
this->root = new node;
cout << root << endl;
this->root->word = word;
this->root->count = 1;
this->root->leftChild = NULL;
this->root->rightChild = NULL;
}
}
void BST::insert(string word, struct node *leaf)
{
if(word< leaf->word)
{
if(leaf->leftChild != NULL)
insert(word, leaf->leftChild);
else
{
cout << "obj has been inserted " << endl;
leaf->leftChild = new node;
cout << leaf->leftChild << endl;
leaf->leftChild->word = word;
leaf->leftChild->count = 1;
leaf->leftChild->leftChild = NULL; //Sets the leftChild child of the child node to null
leaf->leftChild->rightChild = NULL; //Sets the rightChild child of the child node to null
}
}
else if(word>leaf->word)
{
if(leaf->rightChild != NULL)
insert(word, leaf->rightChild);
else
{
cout << "obj has been inserted " << endl;
leaf->rightChild = new node;
cout << leaf->rightChild << endl;
leaf->rightChild->word = word;
leaf->rightChild->count = 1;
leaf->rightChild->leftChild = NULL; //Sets the leftChild child of the child node to null
leaf->rightChild->rightChild = NULL; //Sets the rightChild child of the child node to null
}
}
//word is already in the tree so we increment counter
else leaf->count += 1;
}
Main file:
#include <string>
#include <vector>
#include <fstream>
#include <iostream>
#include <dirent.h>
#include <cstring>
#include <functional>
#include <algorithm>
#include <sstream>
#include "BST.h"
using namespace std;
void parseFile(string fullPath, BST bst) {
ifstream infile(fullPath); // Open it up!
std::string line;
char c;
string word = "";
while (std::getline(infile, line))
{
// Iterate through the string one letter at a time.
for (int i = 0; i < line.length(); i++) {
c = line.at(i); // Get a char from string
tolower(c);
// if it's NOT within these bounds, then it's not a character
if (! ( ( c >= 'a' && c <= 'z' ) || ( c >= 'A' && c <= 'Z' ) ) ) {
//if word is NOT an empty string, insert word into bst
if ( word != "" ) {
bst.insert(word);
//reset word string
word = "";
}
}
else {
word += string(1, c);
}
}
}
}
void getReqDirs(BST bst, const string path, vector<string> files,const bool showHiddenDirs = false){
DIR *dpdf;
struct dirent *epdf;
dpdf = opendir(path.c_str());
int count = 0;
if (dpdf != NULL){
while ((epdf = readdir(dpdf)) != NULL){
if(showHiddenDirs ? (epdf->d_type==DT_DIR && string(epdf->d_name) != ".." && string(epdf->d_name) != "." ) : (epdf->d_type==DT_DIR && strstr(epdf->d_name,"..") == NULL && strstr(epdf->d_name,".") == NULL ) ){
getReqDirs(bst,path+epdf->d_name+"/",files, showHiddenDirs);
}
if(epdf->d_type==DT_REG){
//files.push_back(path+epdf->d_name);
//parseFile(path+epdf->d_name, bst);
cout << path+epdf->d_name << " ";
}
}
}
closedir(dpdf);
}
int main()
{
vector <string> words; // Vector to hold our words we read in.
string str; // Temp string to
cout << "Read from a file!" << endl;
BST bst;
string path = "test/"; //name of directory that holds the data base
vector<string> files; //create vector for file names
/*
//collect all the file names in the data base
getReqDirs(bst,path,files,false);
for (int i = 0; i < files.size(); i++) {
cout << files[i] << " ";
}*/
bst.insert("gary");
bst.insert("Mil");
bst.insert("Taylor");
bst.insert("BrIaN");
bst.insert("fart");
bst.insert("Juan");
bst.insert("James");
bst.insert("Gary");
bst.printInOrder();
//parseFile(path, bst);
return 0;
}
Please let me know if any other info is required.
The following line is the only problematic line of code I found in pio:
cout << "leftChild: " << node->leftChild->leftChild << endl;
It is a problem since node is bound be NULL at some point.
Remove that line.
Also, you don't need the lines
if (node == NULL) {
return;
}
They don't do anything useful and can be removed. Here's an updated version of the function:
void BST::pio(struct node* node) {
cout << "root: " << root << endl;
cout << "node: " << node << endl;
if (node != NULL){
/* first recur on left child */
pio(node->leftChild);
/* then print the data of node */
cout << "Word: " << node->word << endl;
cout << "Count: " << node->count << endl;
/* now recur on right child */
pio(node->rightChild);
}
}

cardealership with dead end - Endless loop and no solution

I just can't seem to figure out why my code doesn't work.
My program is about reading two text files representing a cardealership, and putting the input into a linked list or an STL list depending on mode. Then the orders are read and depending on the availability an error log is created.
The thng is that it keeps on looping in the linked list mode and that is doesn't seem to write the error log.
I feel pretty stupid about this. I don't want you guys to solve the error but teach me how to do it. I'm thankful for any review of my code by more experienced people.
I've tried debugging in Eclipse in XCode and in VS2012(VM with Win8). In none of the IDEs the variables are shown in the debug editor which I just don't understand. I use the MacOSX GCC Compiler.
So here are the txt files:
input.txt
Brera 3
Golf 5
Punto 13
Fiesta 19
and orders.txt
323 Brera 1
324 Golf 6
354 Punto 3
337 Gobldibock 1
this is my main method:
// file main.cpp
#include "cardealership.hpp"
#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
int main( int argc, char* argv[] ) {
std::cout << "argv[2]: " << argv[2] << "\n";
std::cout << "argv[3]: " << argv[3] <<"\n";
const unsigned int mode = atoi( argv[1]);
std::string arg2 = argv[2];
std::string arg3 = argv[2];
cardealership* dealer = new cardealership(arg2, arg3, mode);
std::cout << "dealership created" << "\n";
dealer->readInputFileToList();
std::cout << "still running" << "\n";
dealer->readOutputFileAndAlterInventory();
std::cout << "finishing" << "\n";
return 0;
}
Here are the header of the class containing the actual lists:
// file cardealership.hpp
#ifndef CARDEALERSHIP_HPP // prevent multiple inclusions
#define CARDEALERSHIP_HPP
#include <string>
#include <list>
#include <vector>
typedef struct linkedNode
{
char* data; // will store information
int amountOfCars;
linkedNode* next; // the reference to the next node.
};
class cardealership
{
public:
cardealership (std::string inputFile, std::string ordersFile, const unsigned int mode);
~cardealership();
void readInputFileToList();
void readOutputFileAndAlterInventory();
void printInventory (); //TODO
private:
const unsigned int mode;
std::string inputFile;
std::string ordersFile;
std::list<linkedNode*> listOfCars; //Using Linked Node without linking them...
std::vector<linkedNode*> linkedListOfCars;
};
#endif
and the footer:
// file cardealership.cpp
#include "cardealership.hpp"
#include <iostream>
#include <cstring>
#include <fstream>
#include <sstream>
cardealership::cardealership(std::string inputFile, std::string ordersFile, const unsigned int mode)
: inputFile(inputFile),
ordersFile(ordersFile),
mode(mode)
{}
cardealership::~cardealership()
{
listOfCars.clear();
linkedListOfCars.clear();
}
void cardealership::readInputFileToList(){
std::ifstream infile;
std::string line;
infile.open(inputFile.c_str(),
std::ifstream::in);
if (!infile.good()){
std::cout << "Na na na Input File" << "\n";
}
linkedNode* previousNode;
while(getline(infile, line)){
char* model;
int amountOfCars;
linkedNode* tmpNode;
std::stringstream helperStream;
getline(infile, line);
helperStream << line;
helperStream >> model;
helperStream >> amountOfCars;
//Test
std::cout << "Line: " << line << std::endl;
std::cout << model << ", " << amountOfCars << std::endl;
tmpNode->data = model;
tmpNode->amountOfCars = amountOfCars;
if (mode == 0) { //Use linked list
if(previousNode != NULL){
previousNode->next = tmpNode; //Link that shit
previousNode = tmpNode;
linkedListOfCars.push_back(tmpNode);
}
else{
linkedListOfCars.push_back(tmpNode);
}
}
else if (mode == 1){ //Use STL list
listOfCars.push_back(tmpNode);
}
else{
std::cout<< "invalid mode" << std::endl;
}
if (infile.eof()){
break; // Not too nice but necessary because of last line problem
}
}
infile.close();
}
void cardealership::readOutputFileAndAlterInventory(){
std::ifstream infile;
std::string line;
infile.open(ordersFile.c_str(), std::ifstream::in);
if (!infile.good()){
std::cout << "Na na na Orders File" << "\n";
}
int id;
char* model;
int amountNeeded;
std::ofstream log("errorLog.txt");
if (!log.good()){
std::cout << "Na na na Log File" << "\n";
}
while (getline(infile, line)){
getline(infile, line);
std::stringstream helperStream;
helperStream << line;
helperStream >> id;
helperStream >> model;
helperStream >> amountNeeded;
if (mode == 0) { //Use linked list
linkedNode* tmpNode;
linkedNode* previousNode;
if (!linkedListOfCars.empty()){
tmpNode = linkedListOfCars.front();
while(tmpNode){
if (tmpNode->data == model) {
std::cout<< "Model found!" << std::endl;
}
if (tmpNode->amountOfCars > amountNeeded){
std::cout<< "Enough cars available!" << std::endl;
tmpNode->amountOfCars -= amountNeeded;
}
if (tmpNode->amountOfCars <= amountNeeded){ //
if (previousNode != NULL) {
linkedNode tmp3Node = *previousNode;
tmp3Node.next = tmpNode->next;
}
linkedNode* tmp2Node;
tmp2Node = tmpNode->next;
tmpNode = NULL;
tmpNode = tmp2Node;
//write error to log
log << "ID: "<< id << ", Not enough items!";
previousNode = tmpNode;
tmpNode = tmpNode->next;
}
}
if (!tmpNode) {
std::cout<< "Model not found." << std::endl;
//write error to log.
log << "ID: "<< id << ", Model not available!";
}
}
else{
std::cout<< "No cars to sell." << std::endl;
}
}
else if (mode == 1){ //Use STL list
if (!listOfCars.empty()) {
//Iterator copied and adapted from: http://www.cplusplus.com/reference/stl/list/begin/
std::list<linkedNode*>::iterator it;
for ( it=listOfCars.begin() ; it != listOfCars.end(); it++ ){
linkedNode* tmpNode = *it;
if (tmpNode->data == model) {
std::cout<< "Model found!" << std::endl;
}
if (tmpNode->amountOfCars >= amountNeeded){
std::cout<< "Enough cars available!" << std::endl;
tmpNode->amountOfCars -= amountNeeded;
}
if (tmpNode->amountOfCars < amountNeeded){
//delete entry and write error to log
it = listOfCars.erase(it);
log << "ID: "<< id << ", Not enough items!";
}
if (it++ == listOfCars.end()) {
//Write error to log if end of list is reached
log << "ID: "<< id << ", Model not available!";
}
}
}
else{
std::cout<< "No cars to sell." << std::endl;
}
}
else{
std::cout<< "Invalid mode." << std::endl;
}
}
infile.close();
}
void cardealership::printInventory (){
if (mode == 0) { //Use linked list
}
}
The post seems pretty long to me now but I hope I can still get some help...
Thanks in advance,
L
When adding a new linkedNode you declare a pointer to a node:
linkedNode* tmpNode;
The next mention of tmpNode is the following:
tmpNode->data = model;
However, tmpNode isn't a linkedNode, it's just a pointer to one. You're basically trying to save some data into space that other parts of your program may use. You need to make a linkedNode for tmpNode to point to so that it has its own storage. You may want to look into the new keyword.

C++ simple string replace, non complicated code, but producing crazy error

First, thank for you all your help!
The error I am getting is:
Unhandled exception at 0x7c812afb
(kernel32.dll) in Readerboard.exe:
Microsoft C++ exception:
std::out_of_range at memory location
0x0012f8a8..
I have found the problem to be with this line:
str.replace(str.find(sought), sought.size(), replacement);
It is located in this procedure:
void DisplayMessages() {
ifstream myReadFile;
string str;
static string myMessages[10];
static int i; // of course my famous i
static int MyPosition;
string sought;
string replacement;
myReadFile.open("C:\\Documents and Settings\\agerho000\\Desktop\\cms_export_test\\outages.htm",ios::in);
i = 0; //the start of my array
sought = "</td>"; // value that I want to replace with nothing
replacement.clear();
if(!myReadFile) // is there any error?
{
cout << "Error opening the file! Aborting…\n";
exit(1);
}
if (myReadFile.is_open())
{
cout << endl;
while (!myReadFile.eof())
{
getline(myReadFile, str);
if (str == "<tr>")
{
myReadFile.seekg(4,ios::cur);
getline(myReadFile, str);
str.replace(str.find(sought), sought.size(), replacement);
cout << str;
myMessages[i]=str;
i++;
}
}
}
i=0;
while (i < 10)
{
cout << i << ") " << myMessages[i] << endl;
i++;
if (myMessages[i]=="")
{
break;
}
}
myReadFile.close();
mainMenu();
}
The whole cpp file is displayed below:
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
void mainMenu();
void DisplayMessages();
void AddMessage();
void DeleteMessage();
void EditMessage();
void RunTests();
void CheckFile();
void CreateHtmlFile(string myMessages[10]);
/*
#define MIN 1
#define MAX 100
#define TRUE 1
#define FALSE 0
*/
int main() {
cout << endl;
cout << endl;
cout << "Hello Andrew.\n";
cout << "First you need some sort of menu.\n";
mainMenu();
return 0;
}
void mainMenu() {
int Command;
cout << endl;
cout << endl;
cout << endl;
cout << "What would you like to do?\n";
// cout << "1) Check that tests work!\n";
// cout << "2) Check that the file exists\n";
cout << "3) Display Messages\n";
// cout << "4) Edit a message\n";
// cout << "5) Add a message\n";
// cout << "6) Delete a message\n";
cout << "7) Exit\n";
cout << "Enter a number: ";
cin >> Command;
if (Command == 3)
{
DisplayMessages();
}
if (Command == 7)
{
cout << "Exiting...";
exit(EXIT_SUCCESS);
}
if (Command == 6)
{
DisplayMessages();
}
}
void DisplayMessages() {
ifstream myReadFile;
string str;
static string myMessages[10];
static int i; // of course my famous i
static int MyPosition;
string sought;
string replacement;
myReadFile.open("C:\\Documents and Settings\\agerho000\\Desktop\\cms_export_test\\outages.htm",ios::in);
i = 0; //the start of my array
sought = "</td>"; // value that I want to replace with nothing
replacement.clear();
if(!myReadFile) // is there any error?
{
cout << "Error opening the file! Aborting…\n";
exit(1);
}
if (myReadFile.is_open())
{
cout << endl;
while (!myReadFile.eof())
{
getline(myReadFile, str);
if (str == "<tr>")
{
myReadFile.seekg(4,ios::cur);
getline(myReadFile, str);
str.replace(str.find(sought), sought.size(), replacement);
cout << str;
myMessages[i]=str;
i++;
}
}
}
i=0;
while (i < 10)
{
cout << i << ") " << myMessages[i] << endl;
i++;
if (myMessages[i]=="")
{
break;
}
}
myReadFile.close();
mainMenu();
}
void AddMessage() {
}
/*
void DeleteMessage() {
ifstream myReadFile;
string str;
static string myMessages[10];
static int i; // of course my famous i
static int MyPosition;
string sought;
string replacement;
static int Command;
myReadFile.open("C:\\Documents and Settings\\agerho000\\Desktop\\cms_export_test\\outages.htm",ios::in);
i = 0; //the start of my array
sought = "</b></td>"; // value that I want to replace with nothing
replacement.clear();
if(!myReadFile) // is there any error?
{
cout << "Error opening the file! Aborting…\n";
exit(1);
}
if (myReadFile.is_open())
{
cout << endl;
while (!myReadFile.eof())
{
getline(myReadFile, str);
if (str == "<tr>")
{
myReadFile.seekg(7,ios::cur);
getline(myReadFile, str);
str.replace(str.find(sought), sought.size(), replacement);
myMessages[i]=str;
i++;
}
}
}
i=0;
while (i < 10)
{
cout << i << ") " << myMessages[i] << endl;
i++;
if (myMessages[i]=="")
{
break;
}
}
myReadFile.close();
cout << "Enter the number of the message you would like to delete?\n";
cout << "Or enter 11 to go back to the main menu.\n";
cin >> Command;
while (Command >= 12)
{
cout << "Invalid number, try again!\n";
cout << endl;
cout << "Enter the number of the message you would like to delete?\n";
cout << "Or enter 11 to go back to the main menu.\n";
cin >> Command;
}
if (Command == 11)
{
mainMenu();
}
myMessages[Command].clear();
//clear the string
//now rebuild the htm file with the new array
CreateHtmlFile(myMessages);
}
void EditMessage() {
}
void RunTests() {
}
void CheckFile() {
}
void CreateHtmlFile(string myMessages[])
{
}
//File.seekg(-5); moves the inside pointer 5 characters back
//File.seekg(40); moves the inside pointer 40 characters forward
//tellg() Returns an int type, that shows the current position of the inside-pointer for reading
//tellp() same as above but for writing
//seekp() just like seekg() but for writing
*/
Please help I am so stumped!
str.replace(str.find(sought), sought.size(), replacement); is wrong when str.find() doesn't find what it's looking for. str.find() will return str::npos, which will not be a valid location in the string. Hence, the call to replace fails with the index out of range exception you're seeing.
Change that to:
std::size_t foundIndex = str.find(sought);
if (foundIndex != str.npos)
str.replace(foundIndex, sought.size(), replacement);
else
std::cout << "Oops.. didn't find " << sought << std::endl;
and let us know if that helps you.
EDIT: You might also want to consider using boost::algorithm::replace_all from the Boost String Algorithms Library
A complete function for replacing strings:
std::string ReplaceString(std::string subject, const std::string& search,
const std::string& replace) {
size_t pos = 0;
while ((pos = subject.find(search, pos)) != std::string::npos) {
subject.replace(pos, search.length(), replace);
pos += replace.length();
}
return subject;
}
If you need performance, here is an optimized function that modifies the input string, it does not create a copy of the string:
void ReplaceStringInPlace(std::string& subject, const std::string& search,
const std::string& replace) {
size_t pos = 0;
while ((pos = subject.find(search, pos)) != std::string::npos) {
subject.replace(pos, search.length(), replace);
pos += replace.length();
}
}
Tests:
std::string input = "abc abc def";
std::cout << "Input string: " << input << std::endl;
std::cout << "ReplaceString() return value: "
<< ReplaceString(input, "bc", "!!") << std::endl;
std::cout << "ReplaceString() input string not modified: "
<< input << std::endl;
ReplaceStringInPlace(input, "bc", "??");
std::cout << "ReplaceStringInPlace() input string modified: "
<< input << std::endl;
Output:
Input string: abc abc def
ReplaceString() return value: a!! a!! def
ReplaceString() input string not modified: abc abc def
ReplaceStringInPlace() input string modified: a?? a?? def