How do I replace a string with another string? - c++

I've sat on this problem for quite some time and I can't figure out, what to do.
I am trying to write a programm, that reads a text file, searches and replaces string and saves the file under a new name. Depending on your input with minimum and maximum value as well as inkrement, several files are created.
Everything works except the replacing of a string (function replaceVariable).
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <algorithm>
#include <conio.h>
using namespace std;
string replaceVariable(string text1, string oldVariable, long double wert){
cout<< "replace-function open............."<<endl;
size_t foundAt = text1.find(oldVariable); //find position of old variable
cout<<"position old variable: "<<foundAt<<endl;
string newText = to_string(wert); //convert long double 'wert' to string
cout<<"new variable: "<<newText<<endl;
size_t lengthNewText = newText.length(); //find length of new string
string text2= text1.replace(foundAt, lengthNewText, newText); //replace with new string with length 'lengthNewText' starting at position 'foundAt'
return text2;
}
void writeFile ( string text, string filename ){
ofstream myfile;
myfile.open ( filename.c_str() );
myfile << text;
cout<<"file written.............."<<endl;
myfile.close();
}
template <typename T>
std::string to_string(T const& value) {
stringstream sstr;
sstr << value;
return sstr.str();
}
int main(){
ifstream inFile;
inFile.open("C:\\Users\\User\\Desktop\\Test\\testing.txt");//open the input file
if (inFile.is_open()){
cout<< "file open"<<endl<<endl;
stringstream strStream;
strStream << inFile.rdbuf();
string str = strStream.str();
cout << "---------------------------------------------------------------"<<endl;
cout<< str << endl;
cout << "---------------------------------------------------------------"<<endl<<endl;
string line;
string name;
long double minWert = 0;
long double maxWert = 0;
long double inkWert = 0;
cout << "Enter minimum value:" << endl;
cin >> minWert;
cout << "Enter maximum value:" << endl;
cin >> maxWert;
cout << "Enter inkrement:" << endl;
cin >> inkWert;
int numFiles = (maxWert-minWert)/inkWert + 1; //calculation number of files needed
cout << "minimum value: " << minWert << endl;
cout << "maximum value: " << maxWert << endl;
cout << "inkrement: " << inkWert << endl;
cout << "number of files: " << numFiles << endl<<endl<<endl;
string oldVariable = "xyz "; //string to be replaced, xyz followed by 5 spaces
for( int fileNum = 1; fileNum <= numFiles; ++fileNum ) {
cout<< "loop number: "<< fileNum<<endl;
string output = str;
replaceVariable(output, oldVariable, minWert);
cout << "---------------------------------------------------------------"<<endl;
cout << output << endl;
cout << "---------------------------------------------------------------"<<endl<<endl;
string text = output;
name = "C:\\Users\\User\\Desktop\\Test\\comp";
name += to_string( fileNum );
name += ".bdf";
writeFile( text, name );
cout<<minWert<<endl;
minWert = minWert+inkWert;
cout <<"new Minimalwert: "<< minWert<<endl<<endl;
}
inFile.close();
} else{cout << "Unable to open file";}
getch();
return 0;
}
I've already searched numerous sites and googled every thinkable combination.
Do you have any ideas what might help?

If your functionality of the function 'replaceVariable' is right then this might be the issue,
string output = str;
/*function replaceVariable is returning replaced string but you didn't receive
at the calling place and assign back to output(which you are writing in output file)*/
replaceVariable(output, oldVariable, minWert);
So replace like,
string output = replaceVariable(str, oldVariable, minWert);

Several points to be noted in your code.
First, string::find may return npos if the pattern string is not found, you should check that.
Second, string::replace does an inplace replacement on the original string, for better performance you could pass the text1 argument by reference.
Third, replaceVariable only replaces the first occurrence of the variable, is that really what you want?
Here is my version of replacing patterns in a string:
// replaces at most `limit` occurrences of pattern `p` in text `s` with string `repl`.
// if `limit` <= 0, replace all occurrences.
// returns number of replacement that actually took place.
int replace(std::string &s, const std::string &p, const std::string &repl, int limit=0) {
int nrepl = 0;
size_t pos = 0,
plen = p.length(),
rlen = repl.length(),
npos = std::string::npos;
while ((pos = s.find(p, pos)) != npos) {
s.replace(pos, plen, repl);
pos += rlen;
++nrepl;
if (limit > 0 && nrepl >= limit) break;
}
return nrepl;
}
Hope that helps.

Related

C++ UTF-8 Reading text file, counting characters and outputing results to another file. ‘ gets saved as nothing, but is counted. ā and € appears

I have a task in C++ to read from a UTF-8 text file, count the characters, and save the character + count in a tsv.
I use everywhere wstring, wifstream, and wofstream.
In the terminal, there are many empty spaces when checking everything, but when outputting to tsv everything is overall fine except for 3 things.
‘ when saved appears as nothing, but its amount is counted correctly.
From nowhere ā and € appear. They are counted as the same amount, but they are not present in the original text at all.
What might be the cause of these issues?
The code is a bit crude but looks like this currently
#include <iostream>
#include <algorithm>
#include <fstream>
#include <vector>
using namespace std;
int main()
{
vector <wchar_t> characters;
vector <int> counter;
string filename;
string param;
cout << "Please input the filename: ";
cin >> filename;
cout << "Please, if you want to convert everything to lowercase, input 'lower', else input 'No': ";
cin >> param;
wifstream inFile;
wofstream endFile("dancing_men_char_frequency.tsv");
inFile.open(filename);
wstring Tfile;
int checker;
//inFile >> Tfile;
while(getline(inFile, Tfile)) {
//wcout << Tfile;
//sort(Tfile.begin(), Tfile.end());
if(param == "lower"){
transform(
Tfile.begin(), Tfile.end(),
Tfile.begin(),
towlower);
}
for(int i = 0; i < Tfile.length(); i++){
if(find(characters.begin(), characters.end(), Tfile[i]) != characters.end())
{
if(isblank(Tfile[i])){}else{
checker = 0;
while(characters[checker] != Tfile[i]){
checker++;
}
counter[checker] += 1;
}
}else{
if(isblank(Tfile[i])){}else{
characters.push_back(Tfile[i]);
counter.push_back(1);
}
}
}
}
int sum = 0;
for(int i = 0; i < characters.size(); i++){
wcout << characters[i] << " ";
cout << counter[i] << " " << i << endl;
sum += counter[i];
endFile << characters[i] << '\t' << counter[i] << '\n';
}
cout << sum << endl;
//wcout << Tfile;
//sort(Tfile.begin(), Tfile.end());
//wcout << Tfile;
endFile.close();
inFile.close();
return 0;
}

Error on getline function no instance matches the arguments

Why my code is not executing and showing me error ?? Im getting error on this line
while (getline(s, word, ' , '))
my Code is below:
#include <fstream>
#include <string>
#include <string.h>
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
// first we define a class that will represent all the candidates
class Candidate
{
string name;
int votes;
public:
Candidate()
{
name = "";
int votes = 0;
}
Candidate(string cand_name, int vote_count)
{
name = cand_name; votes = vote_count;
} string getName() { return name; } int getVotes() { return votes; } void get_details() { cout << name << ", " << votes << endl; }
//Following member method is used to increment the vote count
void vote_this_candidate() { votes++; }
};
int main()
{
cout << "Welcome to Student President Voting System!!!" << endl;
Candidate allCandidates[100];
int totalVotes = 0;
// File pointer fstream fin; // Open an existing file
fstream fin;
fin.open("candidantes.txt", ios::in); // Read the Data from the file // as String Vector
vector <string> row;
string line, word, temp; int index = 0; // Following while loop will iterate for each line in the file
while (fin >> temp) {
row.clear(); // read an entire row and // store it in a string variable 'line'
getline(fin, line); // used for breaking words
string s(line); // read every column data of a row and // store it in a string variable, 'word'
while (getline(s, word, ' , '))
{ // adding the splitted words to row
row.push_back(word);
} allCandidates[index] = Candidate(row[0], stoi(row[1])); totalVotes += stoi(row[1]); index++;
}
string name = ""; cout << "\nPlease enter the name of the candidante you want to vote : ";
getline(cin, name); int cand_no = -1; string userChoice; int i = 0; //Now we find the candidante with the same inputted name
while (i < index) {
if (allCandidates[i].getName() == " " + name) {
cand_no = i; cout << "Do you want to vote this candidante [y/n] : ";
cin >> userChoice; //After finding the candidate just ask the user to vote the candidante
if (userChoice == "y") { //to vote just call the member method that increments the vote count
allCandidates[cand_no].vote_this_candidate(); totalVotes++; cout << endl << "You successfully voted to " << name << " Thanks for voting!!!" << endl;
}
else { cout << "You didn't vote!!!" << endl; } break;
}
i++;
} if (cand_no == -1) {
cout << "Candidante not found!!! Do you like to add this candidate [y/n]: ";
cin >> userChoice; if (userChoice == "y") { allCandidates[index + 1] = Candidate(name, 1); totalVotes++; index++; }
}
//To show top five candidates we first sort the array with lambda
std::sort(allCandidates, allCandidates + 10, [](Candidate a, Candidate b) -> bool { return a.getVotes() > b.getVotes(); });
//then we show only first five candidates
cout << endl << "These are top 5 candidantes so far : " << endl;
for (int i = 0; i < 5; i++)
{
cout << i + 1 << ","; allCandidates[i].get_details();
} cout << endl << "Total studnets voted: " << totalVotes;
}
Problem is here:
string s(line);
while (getline(s, word, ' , '))
because getline has no overload that takes a std::string as its first parameter.
However, there is an overload that takes a stringstream, so you can do:
stringstream ss(line);
while (getline(ss, word, ' , '))
Also, ' , ' won't do what you think. Perhaps you meant ','.
Finally, int votes = 0; in your Candidate() constructor should just be votes = 0;. As it is, you are just declaring, initialising and then discarding a local variable.
The problem is that the compiler is telling you that the parameters you've given don't match a definition of the function. In your case I believe the problem is that you've given it 3 characters instead of 1 in the character portion (remember, a space is also a character). Try changing ' , ' to ','

Find a word in a sentence c++

This code should say if a word is present in a sentence or not. When I insert the sentence and the word where I declare the strings(for exemple: string s = "the cat is on the table" string p = "table" the program says that the word is in the sentence) the code works but, with the getline, the for cycle never begin and it always says that the word isn't in the sentence.
Please help I dont know what to do
#include <iostream>
#include <string>
using namespace std;
int main () {
string s;
string p;
string word;
bool found = false;
int sl = s.length();
int beg = 0;
int pl = p.length();
cout << "sentence: ";
getline(cin, s);
cout << "word: ";
getline(cin, p);
for(int a = 0; a<sl; a++)
{
if(s[a]== ' ')
{
word = s.substr(beg, a-beg);
if (word== p)
{
found = true;
break;
}
beg = a+1;
}
}
if (found== true)
{
cout <<"word " << p << " is in a sentence " << s;
}
else
{
word = s.substr(beg);
if (word== p)
{
found = true;
}
if(found == true)
{
cout <<"the word " << p << " is in the sentence " << s;
}
else
{
cout <<"the word " << p << " isn't in the sentence " << s;
}
}
}
after taking the input strings then use length() to find the length, otherwise you are not taking the actual size of the strings.
getline(cin, s);
getline(cin, p);
int sl = s.length();
int pl = p.length();
For splitting the words after taking the input string by getline() you can use stringstream which is a builtin c++ function, like :
#include <sstream>
#include <iostream>
using namespace std;
int main(){
string arr;
getline(cin, arr);
stringstream ss(arr);
string word;
while(ss >> word){
// your desired strings are in `word` one by one
cout << word << "\n";
}
}
Another thing is that you can declare the strings like string s, p, word;

how to initialize the recursive function for length

int countChars(string str)
{
int count = 0;
if (str == "")
return count;
else
{
count++;// add a character to the count
return count + countChars(str.substr(1));// function calls itself
}
}
I need to take the above function and call in in the program below and I'm not sure how to initialize it properly. Below is what I tried and it doesn't work. I'm not allowed to use the .length() because otherwise the program would be done.
int main()
{
char find = '\0';
string str;
int count = 0;
int length = int(countChars);
//ask the user for a sentence
cout << "Enter a sentence " << endl;
getline(cin, str);
//ask the user which letter they want the count of
cout << "Which letter would you like to find the number of appearances: " << endl;
cin >> find;
for (int i = 0; i < length; i++)
{
if (str[i] == find)
{
count++;
}
}
cout << "the letter " << find << " appears " << length << " times " << endl;
//waits for user to exit
system("pause");
cin.get();
}
It seems the function should count the number of appearances of a letter in a string. If so then it is declared and defined incorrectly. It has to have at least two parameters an object of type std::string and an object of type char.
Here is shown how such a recursive function can look
#include <iostream>
#include <string>
size_t countChars( const std::string &s, char c )
{
return s.empty() ? 0 : ( s[0] == c ) + countChars( { s, 1 }, c );
}
int main()
{
std::cout << "Enter a sentence ";
std::string s;
std::getline( std::cin, s );
std::cout << "Which letter would you like to find the number of appearances: ";
char c = '\0';
std::cin >> c;
std::cout << "The letter " << c
<< " appears " << countChars( s, c )
<< " times " << std::endl;
return 0;
}
The program output might look like
Enter a sentence My name is Alycia
Which letter would you like to find the number of appearances: a
The letter a appears 2 times
If you mean a function that just calculates the length of a string then it can look like
size_t countChars( const std::string &s )
{
return s.empty() ? 0 : 1 + countChars( { s, 1 } );
}
and shall be called after the statement
getline(cin, str);

Extra string outputs if user input is more than one word

This is my first time asking a question on here, so be gentle lol. I wrote up some code for an assignment designed to take information from a (library.txt datatbase) file, store it in arrays, then access/search those arrays by title/author then output that information for the user based on what the user enters.
The issue I am having is, whenever the user enters in a search term longer than one word, the output of "Enter Q to (Q)uit, Search (A)uthor, Search (T)itle, (S)how All: " is repeated several times before closing.
I am just looking to make this worthy of my professor lol. Please help me.
#include <iostream>
#include <fstream>
#include <string>
#include <iomanip>
using namespace std;
struct Book
{
string title;
string author;
};
int loadData(string pathname);
char switchoutput();
void showAll(int count);
int showBooksByAuthor(int count, string name);
int showBooksByTitle(int count, string title);
int FindAuthor(int count, string userinput);
int FindTitle(int count, string userinput);
void ConvertStringToLowerCase(const string orig, string& lwr); //I found this program useful to convert any given string to lowercase, regardless of user input
const int ARRAY_SIZE = 1000;
Book books[ARRAY_SIZE];
int main()
{
string pathname;
string name;
string booktitle;
int count = 0;
int counta = 0;
int countt = 0;
char input = 0;
cout << "Welcome to Jacob's Library Database." << endl;
cout << "Please enter the name of the backup file: " ;
cin >> pathname;
count = loadData(pathname);
cout << count << " records found in the database." << endl;
while (toupper(input != 'Q'))
{
input = switchoutput(); // function call for switchoutput function
switch (input)
{
case 'A':
cout << "Author's Name: ";
cin >> name;
counta = showBooksByAuthor(count, name);
cout << counta << " records found." << endl;
break;
case 'T':
cout << "Book Title: ";
cin >> booktitle;
countt = showBooksByTitle(count, booktitle);
cout << countt << " records found." << endl;
break;
case 'S':
showAll(count);
break;
case 'Q':
break;
}
}
//Pause and exit
cout << endl << "Press 'ENTER' to quit";
getchar();
getchar();
return 0;
}
int loadData(string pathname) //loading data into the array of structs
{
ifstream inFile;
inFile.open(pathname);
if (!inFile) {
cout << "Error, could not read into file. Please re-compile." << endl;
system("PAUSE");
exit(1); //if not in file, exit;
}
int i = 0;
while (!inFile.eof()) {
getline(inFile, books[i].title);
getline(inFile, books[i].author);
i++;
}
return i;
}
char switchoutput() //seperate output function to get my characteroutput constantly resetting and returning the uppercase version for my switch
{
char input;
cout << "Enter Q to (Q)uit, Search (A)uthor, Search (T)itle, (S)how All: ";
cin >> input;
return toupper(input);
}
int showBooksByAuthor(int count, string name)
{
int authorcount = 0;
authorcount = FindAuthor(count, name);
return authorcount;
}
int showBooksByTitle(int count, string title)
{
int titlecount = 0;
titlecount = FindTitle(count, title);
return titlecount;
}
void showAll(int count)
{
for (int i = 0; i < count; i++)
{
cout << books[i].title << " (" << books[i].author << ")" << endl;
}
}
int FindAuthor(int count, string userinput)
{
int authorcount = 0;
string stringlower, arraylower;
int num;
// called upon function to lowercase any of the user inputs
ConvertStringToLowerCase(userinput, stringlower);
for (int i = 0; i < count; ++i) //this function's count determines at which locations to output the author and names (an argument from books by author)
{
// called upon function to lowercase any of the stored authors'
ConvertStringToLowerCase(books[i].author, arraylower);
num = arraylower.find(stringlower); // searches string for userinput (in the lowered array) and stores its value
if (num > -1) // you can never get a -1 input value from an array, thus this loop continues until execution
{
cout << books[i].title << " (" << books[i].author << ")" << endl; //cout book title and book author
authorcount++; //count
}
}
return authorcount;
}
int FindTitle(int count, string userinput) //same as previous but for titles
{
int titlecount = 0;
string stringlower, arraylower;
int num;
ConvertStringToLowerCase(userinput, stringlower);
for (int i = 0; i < count; ++i)
{
ConvertStringToLowerCase(books[i].title, arraylower);
num = arraylower.find(stringlower);
if (num > -1)
{
cout << books[i].title << " (" << books[i].author << ")" << endl;
titlecount++; //count
}
}
return titlecount;
}
void ConvertStringToLowerCase(const string orig, string& lwr) // I found this from another classmate during tutoring, I thought to be useful.
{
lwr = orig;
for (int j = 0; j < orig.length(); ++j) //when called upon in my find functions, it takes the string and convers the string into an array of lowercase letters
{
lwr[j] = tolower(orig.at(j));
}
}