Inserting a space behind capital letters of a string - c++

I'm trying to add a space behind capital letters of a string for example. "ILikeBananas" would turn into "I like bananas"
I've tried using a while loop, isupper, and .insert((i-1), " ").
I noticed that it would work if it were i+1 however that would give me the wrong output.
void fixedInput(string &userInput) {
int i = 1;
while (userInput[i]) {
if (isupper(userInput[i])) {
userInput.insert((i-1)," ");
tolower(userInput[i]);
}
i++;
}
}
with (i-1) there is no output

Take a look at https://stackoverflow.com/a/14494432/11397643
Using that concept you should be able to append a space as well when doing a conversion

Related

C++ breaking string into new line after punctuation

I'm trying to learn strings and I've figured out how to replace as well as insert into an existing string. I have 3 strings at the moment which I've declared as constants, I've merged them into one string variable which puts them all one after eachother.
I've also changed every single occurance of "Hi" to "Bye" in those strings. My 3 strings bundled into a single one are as following:
"Hi! My name is xxxx! I would like to be on my own but I don't know how to, could you help me?"
I want it to display as:
Hi!
My name is xxxx!
I would like to be on my own but I don't know how to, could you help me?
As soon as a puncutation occurs I'd like to insert a line break "\n", using replace works but that means the punctuation will disappear, using insert will first insert the line break before the punctuation, and it won't continue to the next one which results in:
"Hi!
My name is xxxx! I would like to be on my own but I don't know how to, could you help me?"
I changed the code to only include dots to simplify it, once solved the same solution can be applied to any other part such as question marks or exclamation marks.
Any tips on how to fix this?
#include <iostream>
#include <string>
using namespace std;
string const Text0 = "Hi.";
string const Text1 = "My name is xxxx.";
string const Text2 = "I would like to be on my own but I don't know how to, could you help me.";
string const Text3 = "I would, but I don't know how to.";
string text = Text0 + Text1 + Text2 + Text3;
int main() {
while (text.find("I") != string::npos) {
text.replace(text.find("I"), 1, "J");
}
while (text.find("like") != string::npos) {
text.replace(text.find("like"), 4, "milk");
}
text.insert(text.find("."), "\n");
cout << text;
return 0;
}
You can create your own short function that will add newline after every punctuation sign.
For example:
void addNewLines(std::string *text)
{
for (int i = 0; i < text->length(); i++)
{
if ((*text)[i] == '!' || (*text)[i] == '?' || (*text)[i] == '.')
{
(*text)[i + 1] = '\n';
}
}
}
As you can see in this piece of code, in the for loop you are going from the first to the last character of the string, and after every punctuation sign you replace empty space with \n character.
I'm using pointers here to prevent copying of the string to the function, in case it is a huge string, but you could do it without pointers, that way syntax is a little bit cleaner.

filtering string to keep a-z and space marks c++?

I'm using QT to design a dictionary to sort a word/string of words entered by a user.
In 'silent mode' I want the user to only enter a single word (a-z) or a string of words (a-z, separated by a space).
I'm really having trouble trying to filter out non-alphabetical while keeping whitespaces!
if(ui->silentButton->isChecked())
{
if(userWord == " ") // if user enters just a space
{
QMessageBox messageBox;
messageBox.critical(0,"Error!","Please enter a valid word to continue...");
messageBox.setFixedSize(500,200);
}
else if(userWord == "") // if user enters nothing
{
QMessageBox messageBox;
messageBox.critical(0,"Error!","Please enter a valid word to continue...");
messageBox.setFixedSize(500,200);
}
else if (userWord.contains(" ")) // if user enters a string that contains a space
{
QStringList Splitstring = userWord.split(QRegExp("\\W"), QString::SkipEmptyParts);
for(int i = 0; i < Splitstring.size(); ++i)
{
MyTree->insert(MyTree->getRoot(), Splitstring.at(i).toLocal8Bit().constData());
}
}
else
{
MyTree->insert(MyTree->getRoot(),userWord);
}
Unfortunately this does not work as it still allows the user to enter a non-alphabetical or a string containing a non-alphabetical i.e. } a} a b c}
I want it to bring up an error when they enter anything at all that is non alphabetical. I have tried using if(userWord.contains(QRegExp("\\w"))) however this also filters out spaces too.
Can anyone point me in the right direction?
if(ui->silentButton->isChecked())
{
if(userWord.trimmed() == "") // if user enters just a space or nothing
{
QMessageBox messageBox;
messageBox.critical(0,"Error!","Please enter a valid word to continue...");
messageBox.setFixedSize(500,200);
}
else if (userWord.contains(" ")) // if user enters a string that contains a space
{
QStringList splitString { userWord.split(QRegularExpression("[^a-z]"), QString::SkipEmptyParts) };
for(int i = 0; i < splitString.size(); ++i)
{
MyTree->insert(MyTree->getRoot(), splitString.at(i).toLocal8Bit().constData());
}
}
else
{
MyTree->insert(MyTree->getRoot(),userWord);
}
}
This should do the trick for you.
I've made some improvements like adding trimmed() because that will make it work for both input errors, as well as specifying more than one space and adjusted the regular expression to exclude what you don't need.
I've replaced QRegExp, because QRegularExpression should be used instead as it is faster (new).
Variables should start with lowercase, therefore the splitString renaming.
Now the result for this input:
"test } awa} fa baad cdda c}"
is:
test
awa
fa
baad
cdda
c
As #deW1 pointed out you should be using QRegularExpression for performance issues and try using this for regular expression
/^([a-zA-Z]+( )?[a-zA-Z]+)*$/
This will allow blank spaces separated values.

want to optimize this string manipulation program c++

I've just solve this problem:
http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=3139
Here's my solution:
https://ideone.com/pl8K3K
int main(void)
{
string s, sub;
int f,e,i;
while(getline(cin, s)){
f=s.find_first_of("[");
while(f< s.size()){
e= s.find_first_of("[]", f+1);
sub = s.substr(f, e-f);
s.erase(f,e-f);
s.insert(0, sub);
f=s.find_first_of("[", f+1);
}
for(i=0; i<s.size(); i++){
while((s[i]==']') || (s[i]=='[')) s.erase(s.begin()+i);
}
cout << s << endl;
}
return 0;
}
I get TLE ,and I wanna know which operation in my code costs too expensive and somehow optimize the code..
Thanks in advance..
If I am reading your problem correctly, you need to rethink your design. There is no need for functions to search, no need for erase, substr, etc.
First, don't think about the [ or ] characters right now. Start out with a blank string and add characters to it from the original string. That is the first thing that speeds up your code. A simple loop is what you should start out with.
Now, while looping, when you actually do encounter those special characters, all you need to do is change the "insertion point" in your output string to either the beginning of the string (in the case of [) or the end of the string (in the case of ]).
So the trick is to not only build a new string as you go along, but also change the point of insertion into the new string. Initially, the point of insertion is at the end of the string, but that will change if you encounter those special characters.
If you are not aware, you can build a string not by just using += or +, but also using the std::string::insert function.
So for example, you always build your output string this way:
out.insert(out.begin() + curInsertionPoint, original_text[i]);
curInsertionPoint++;
The out string is the string you're building, the original_text is the input that you were given. The curInsertionPoint will start out at 0, and will change if you encounter the [ or ] characters. The i is merely a loop index into the original string.
I won't post any more than this, but you should get the idea.

C++: Removing all asterisks from a string where the asterisks are NOT multiplication symbols

So basically, I might have some string that looks like: "hey this is a string * this string is awesome 97 * 3 = 27 * this string is cool".
However, this string might be huge. I'm trying to remove all the asterisks from the string, unless that asterisk appears to represent multiplication. Efficiency is somewhat important here, and I'm having trouble coming up with a good algorithm to remove all the non-multiplication asterisks from this.
In order to determine whether an asterisk is for multiplication, I can obviously just check whether it's sandwiched in between two numbers.
Thus, I was thinking I could do something like (pseudocode):
wasNumber = false
Loop through string
if number
set wasNumber = true
else
set wasNumber = false
if asterisk
if wasNumber
if the next word is a number
do nothing
else
remove asterisk
else
remove asterisk
However, that^ is ugly and inefficient on a huge string. Can you think of a better way to accomplish this in C++?
Also, how could I actually check whether a word is a number? It's allowed to be a decimal. I know there's a function to check if a character is a number...
Fully functioning code:
#include <iostream>
#include <string>
using namespace std;
string RemoveAllAstericks(string);
void RemoveSingleAsterick(string&, int);
bool IsDigit(char);
int main()
{
string myString = "hey this is a string * this string is awesome 97 * 3 = 27 * this string is cool";
string newString = RemoveAllAstericks(myString);
cout << "Original: " << myString << "\n";
cout << "Modified: " << newString << endl;
system("pause");
return 0;
}
string RemoveAllAstericks(string s)
{
int len = s.size();
int pos;
for(int i = 0; i < len; i++)
{
if(s[i] != '*')
continue;
pos = i - 1;
char cBefore = s[pos];
while(cBefore == ' ')
{
pos--;
cBefore = s[pos];
}
pos = i + 1;
char cAfter = s[pos];
while(cAfter == ' ')
{
pos++;
cAfter = s[pos];
}
if( IsDigit(cBefore) && IsDigit(cAfter) )
RemoveSingleAsterick(s, i);
}
return s;
}
void RemoveSingleAsterick(string& s, int i)
{
s[i] = ' '; // Replaces * with a space, but you can do whatever you want
}
bool IsDigit(char c)
{
return (c <= 57 && c >= 48);
}
Top level overview:
Code searches the string until it encounters an *. Then, it looks at the first non-whitespace character before AND after the *. If both characters are numeric, the code decides that this is a multiplication operation, and removes the asterick. Otherwise, it is ignored.
See the revision history of this post if you'd like other details.
Important Notes:
You should seriously consider adding boundary checks on the string (i.e. don't try to access an index that is less than 0 or greater than len
If you are worried about parentheses, then change the condition that checks for whitespaces to also check for parentheses.
Checking whether every single character is a number is a bad idea. At the very least, it will require two logical checks (see my IsDigit() function). (My code checks for '*', which is one logical operation.) However, some of the suggestions posted were very poorly thought out. Do not use regular expressions to check if a character is numeric.
Since you mentioned efficiency in your question, and I don't have sufficient rep points to comment on other answers:
A switch statement that checks for '0' '1' '2' ..., means that every character that is NOT a digit, must go through 10 logical operations. With all due respect, please, since chars map to ints, just check the boundaries (char <= '9' && char >= '0')
You can start by implementing the slow version, it could be much faster than you think. But let's say it's too slow. It then is an optimization problem. Where does the inefficiency lies?
"if number" is easy, you can use a regex or anything that stops when it finds something that is not a digit
"if the next word is a number" is just as easy to implement efficiently.
Now, it's the "remove asterisk" part that is an issue to you. The key point to notice here is that you don't need to duplicate the string: you can actually modify it in place since you are only removing elements.
Try to run through this visually before trying to implement it.
Keep two integers or iterators, the first one saying where you are currently reading your string, and the second one saying where you are currently writing your string. Since you only erase stuff, the read one will always be ahead of the writing one.
If you decide to keep the current string, you just need to advance each of your integers/iterators one by one, and copying accordingly. If you don't want to keep it, just advance the reading string! Then you only have to cut the string by the amount of asterisks you removed. The complexity is simply O(n), without any additional buffer used.
Also note that your algorithm would be simpler (but equivalent) if written like this:
wasNumber = false
Loop through string
if number
set wasNumber = true
else
set wasNumber = false
if asterisk and wasNumber and next word is a number
do nothing // using my algorithm, "do nothing" actually copies what you intend to keep
else
remove asterisk
I found your little problem interesting and I wrote (and tested) a small and simple function that would do just that on a std::string. Here u go:
// TestStringsCpp.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <string>
#include <iostream>
using namespace std;
string& ClearAsterisk(string& iString)
{
bool bLastCharNumeric = false;
string lString = "0123456789";
for (string::iterator it = iString.begin(); it != iString.end() ; ++it) {
switch (*it) {
case ' ': break;//ignore whitespace characters
case '*':
if (bLastCharNumeric) {
//asterisk is preceded by numeric character. we have to check if
//the following non space character is numeric also
for (string::iterator it2 = it + 1; it2 != iString.end() ; ++it2) {
if (*it2 != ' ') {
if (*it2 <= '9' && *it2 >= '0') break;
else iString.erase(it);
break; //exit current for
}
}
}
else iString.erase(it);;
break;
default:
if (*it <= '9' && *it >= '0') bLastCharNumeric= true;
else bLastCharNumeric = false; //reset flag
}
}
return iString;
}
int _tmain(int argc, _TCHAR* argv[])
{
string testString = "hey this is a string * this string is awesome 97 * 3 = 27 * this string is cool";
cout<<ClearAsterisk(testString).c_str();
cin >> testString; //this is just for the app to pause a bit :)
return 0;
}
It will work perfectly with your sample string but it will fail if you have a text like this: "this is a happy 5 * 3day menu" because it checks only for the first nonspace character after the '*'. But frankly I can't immagine a lot of cases you would have this kind of construct in a sentence.
HTH,JP.
A regular expression wouldn't necessarily be any more efficient, but it would let you rely on somebody else to do your string parsing and manipulation.
Personally, if I were worried about efficiency, I would implement your pseudocode version while limiting needless memory allocations. I might even mmap the input file. I highly doubt that you'll get much faster than that.

How to compare a string with certain words and if a match is found print the whole string

I am trying to write a little program that will load in a file, compare each line with a specific array of words, and if that line has any of those words in it then I want to "print" that line out to a file.
My current code is:
int main()
{
string wordsToFind[13] =
{"MS SQL", "MySQL", "Virus", "spoof", "VNC", "Terminal", "imesh", "squid",
"SSH", "tivo", "udp idk", "Web access request dropped", "bounce"};
string firewallLogString = "";
ifstream firewallLog("C:\\firewalllogreview\\logfile.txt");
ofstream condensedFirewallLog("C:\\firewalllogreview\\firewallLog.txt");
if(firewallLog.fail())
{
cout << "The file does not exist. Please put the file at C:\\firewalllogreview and run this program again." << endl;
system("PAUSE");
return 0;
}
while(!firewallLog.eof())
{
getline(firewallLog, firewallLogString);
for(int i = 0; i < 13; i++)
{
if(firewallLogString == wordsToFind[i])
{
firewallLogString = firewallLogString + '\n';
condensedFirewallLog << firewallLogString;
cout << firewallLogString;
}
}
}
condensedFirewallLog.close();
firewallLog.close();
}
When I run the program it will compare the string, and if it matches it will only print out the specific word instead of the string. Any help would be much appreciated.
If I understand your problem correctly, you want to check if the line contains one of the word and print it if it does.
Right now what you are doing is this:
if(firewallLogString == wordsToFind[i])
Which checks if the string exactly matches the word. So, if the string contains one of the word but has other words in it, the test will fail.
Instead, check if the word is part of the string, like this:
if(firewallLogString.find(wordsToFind[i]) != string::npos)
There is something wrong in your code.
in this line
getline(firewallLog, firewallLogString);
you are reading a line, not a word, but then later you are comparing the whole line with a word from your array. Your IF shall not work actually.
Instead you need to use strstr method, to lookup for any word in your firewallLogString and if it finds you do the rest of your code.
Use std::string's find method to find the occurrence of your pattern words.