Making a Boolean trying to print out uppercase letters - c++

The objective is to make it so that all uppercase letters are printed out in a string, however, I must keep the bool function and use it within my code. I have resolved some issues from the past but ran up with a issue that is preventing me from fixing it. Test cases are "HEllO" -> "HEO" "my" -> "" "NAME" -> "NAME" "Is" -> "I" "AnDeRsON" -> "ADRON".
#include <iostream>
using namespace std;
bool isUpperCase(char ch){
if(ch >= 'A' and ch <= 'Z'){
return true;
}
return false;
}
int main() {
string a = "";
cin >> a;
string c = "";
for(int i = 0; i < a.length(); i++)
{
if (isUpperCase(a[i])) i++;
{
c += a[i];
}
}
cout << c << endl;
}
Now whenever I do a case like "CHADnigeria" it turns it into "HDnigeria" even though I want it to say "CHAD". It also removes the capitals which I do not want and it should be removing the lowercases. "DancingInTheSky" turns into "ancingnheky" which should be "DITS". Reminder that the bool function must not be changed though.

I updated your program so that it works:
#include <iostream>
using namespace std;
bool isUpperCase(char ch){
if(ch >= 'A' and ch <= 'Z'){
return true;
}
return false;
}
int main() {
string a = "";
cin >> a;
string c = "";
for(int i = 0; i < a.length(); i++)
{
if (isUpperCase(a[i]))
{
c += a[i];
}
}
cout << c << endl;
}
What was your mistake: You put i++ after the if statement, which caused the weird output.
I hope I could help a little bit

It is a good programming praxis to write return condition; instead of if (condition) return true; else return false;. I would write your isUpperCase function just as:
bool isUpperCase(char ch) {
return (ch >= 'A' and ch <= 'Z');
}
The mistake you are looking for is in the main function, there is a i++ which is causing trouble. You wrote:
if (isUpperCase(a[i])) i++;
{
c += a[i];
}
And the compiler understands it as:
if (isUpperCase(a[i])) {
i++;
}
c += a[i];
Also, when you add a single character into a string in C++ i recommend you to use the push_back() method instead of the + operator. So c += a[i]; would be c.push_back(a[i]);. Both work fine, but push_back() is generally more efficient.

Related

Palindrome program not returning correct answers

I am currently coding in C++ and am wanting only take notice of lowercase letters and numbers.
My problem is that when I enter a string containing integers and characters (such as a lowercase letter), does not return the correct answer for and ODD length (of the array) above the value of 3.
For instance, if I was to enter '1b1', it would return as a palindrome, otherwise if I were to write '1bbb1', it would return false.
Here is the code:
bool isPalindrome(string s){
int len = s.size();
int mid = len / 2;
int unsigned i;
stack<char> palindromeStack;
for (i = 0; i < mid; i++)
{
if(s[i] <= 47 && s[i] >= 58 ||
s[i] <= 96 && s[i] >= 123){
s.erase(i,1);
i--;
}
if (s[i] > 47 && s[i] < 58 ||
s[i] > 96 && s[i] < 123)
{
palindromeStack.push(s[i]);
}
if (len % 2 != 0)
{
i++;
}
}
while (s[i] != '\0')
{
char ele;
ele = palindromeStack.top();
palindromeStack.pop();
if (ele != s[i])
{
return false;
i++;
}
return true;
}}
I assume this has something to do with the IF statements in relation to the length of the array, but since I'm still quite new to programming, I am unable to find the solution.
Any help would be greatly appreciated! (this includes directing me to already answered questions that will solve my issue)
P.S. Code brackets were slightly modified to fit within the Stack Overflow Code Sample function.
Thanks
I have a much better code. Usage of any data structure template does not indicate that it is a good code. If your target is to check if a string is palindrome including alphanumeric characters please refer to the following code. I have shared the screenshots as an example :-
#include <iostream>
#include<string>
using namespace std;
string transform(string s)
{
string result = "";
for(char ch : s)
{
if(('a'<=ch && ch<='z') || ('0'<=ch && ch<='9') )
result += ch;
}
return result;
}
int main() {
string s="";
// reading the input from the std input
cin>>s;
s = transform(s);
bool isPalindrome = true;
for(int i = 0, j = s.size()-1; i<=j; i++,j--)
{
if(s[i]!=s[j])
{
isPalindrome = false;
break;
}
}
if(isPalindrome)
{
cout<<"Palindrome";
}
else
{
cout<<"Not Palindrome";
}
return 0;
}
The key point is it won't be a palindrome if the values are not same from both ends of the string. If any character is unequal it is proven that it is not a palindrome, hence we need not to go for other comparisons.
This has lesser lines of code and works in every scenario.
This code will bail out checking at first sign of a mismatch :
#include <cassert>
#include <string>
bool is_palindrome(const std::string& str)
{
for (int front = 0, back = static_cast<int>(str.length()) - 1; front < back; ++front, --back)
{
if (str[front] != str[back]) return false;
}
return true;
}
int main()
{
assert(is_palindrome(""));
assert(is_palindrome("1"));
assert(is_palindrome("121"));
assert(is_palindrome("abcdefedcba"));
assert(!is_palindrome("121abc"));
return 0;
}
Edit (now with iterator & reverse iterator):
bool is_palindrome(const std::string& str)
{
for (auto [front, back] = std::tuple{str.begin(), str.rbegin()}; front < back.base(); ++front, ++back)
{
if (*front != *back) return false;
}
return true;
}

What is wrong with my program to find the longest word in a sentence?

#include <iostream>
using namespace std;
int main() {
char a[101]{0};
cin>>a;
cin.getline(a,101);
cin.ignore();
int currLen{0};
int maxLen{0};
int startInd{-1};
int endInd{-1};
for(int i=0; i<101; i++) {
if(a[i]!=' ' ) {
++currLen;
} else if(a[i]==' '||a[i]=='\0') {
if(currLen>maxLen) {
maxLen=currLen;
startInd=i-currLen;
endInd=i-1;
}
if(a[i]=='\0')
break;
currLen=0;
}
}
cout<<maxLen<<endl;
if(startInd==-1)
cout<<-1;
else
for(int i=startInd; i<=endInd; i++)
cout<<a[i];
return 0;
}
If I take an input here, for example, "My name is Manav Kampani"
It will output 5
Manav instead of 7
Kampani
But if I write "My name is Manav Kampani ", with space after the last word
than it is considering Kampani too printing Kampani.
Also when I input "Kampani Manav is my name" then too it's displaying the wrong output. That means it is not considering the first word of the sentence.
if(a[i]!=' ' )
{
++currLen;
}
else if(a[i]==' '||a[i]=='\0')
{
....
}
Consider the case of a[i] == 0. Which of these if-statements will apply.
Answer: the first one. Which means you'll never look at the final word in the string. You also don't exit at the end of the string, but instead loop through whatever is in your string all the way out to character 101.
As a general structure, be very, very careful with this:
if (condition)
else if (condition)
// without a final else section
If you do that, you need to think about what you're doing. In this particular case, you can have:
if (a[i] != 0 && a[i] != ' ')
else
It may not solve all your issues, but it should solve some.
A nice sliding window pattern implementation.
You have 3 problems in your code
You must not write cin >> a;
You must not write cin.ignore();
You need to modify your if statement like so: if (a[i] != ' ' && a[i] != '\0') Otherwise you will not detect the last word.
Your complete working code with that minor fixes will lokk like that.
int main()
{
char a[101]{ 0 };
//cin >> a;
cin.getline(a, 101);
//cin.ignore();
int currLen{ 0 };
int maxLen{ 0 };
int startInd{ -1 };
int endInd{ -1 };
for (int i = 0; i < 101; i++)
{
if (a[i] != ' ' && a[i] != '\0')// Add comparison
{
++currLen;
}
else if (a[i] == ' ' || a[i] == '\0')
{
if (currLen > maxLen)
{
maxLen = currLen;
startInd = i - currLen;
endInd = i - 1;
}
if (a[i] == '\0')
break;
currLen = 0;
}
}
cout << maxLen << endl;
if (startInd == -1)
cout << -1;
else
for (int i = startInd; i <= endInd; i++)
cout << a[i];
return 0;
}
Additionally. You should not use C-Style arrays in C++. And please use std::string
There is a couple of things here:
1- You don't need to do a cin>>a this is actually consuming the first word, and afterwards the content is overrided by cin.getline(). So removing the firsst cin>>ayou'll be fine.
2- The last word is not read because there isn't any if condition that matches the condition aka.
if(a[i]!=' ' ) case of not a space
//not end of word
else if(a[i]==' '||a[i]=='\0') case of space or null
//end of word
So your last character is not a space nor null, that means you don't detect the last word.

Find prefix within a string

I'm currently doing a leetcode question where I have to find a prefix within a sentence and return the word number within the sentence else return -1. I came up with a solution but it crashes with some strings and i dont know why. An example of this is the following:
Input: sentence = "i love eating burger", searchWord = "burg"
Output: 4 (I also get an output of 4)
Explanation: "burg" is prefix of "burger" which is the 4th word in the sentence.
but fails this example:
Input: sentence = "this problem is an easy problem", searchWord = "pro"
Output: 2 ( I get an output of 6)
Explanation: "pro" is prefix of "problem" which is the 2nd and the 6th word in the sentence, but we return 2 as it's the minimal index.
My cout for this one produced a very weird snippet:
problem is an easy problem
problem is an easy problem
problem is an easy problem
problem is an easy problem
probl
proble
problem
problem
problem i
problem is
it completely ignored the first couple substrings when i increments, this is the only time it happens tho.
int isPrefixOfWord(string sentence, string searchWord)
{
string sub;
int count = 1;
for (int i = 0; i < sentence.length(); i++)
{
if (sentence[i] == ' ')
count++;
for (int j = i; j < sentence.length(); j++)
{
sub = sentence.substr(i, j);
cout<<sub<<endl;
if (sub == searchWord)
{
return count;
}
}
}
return -1;
}
Any Ideas?
int isPrefixOfWord(string sentence, string searchWord)
{
string sub;
int count = 1;
for (int i = 0; i < sentence.length() - searchWord.length() - 1; i++)
{
if (sentence[i] == ' ')
count++;
sub = sentence.substr(i,searchWord.length());
if ( sub == searchWord && (sentence[i-1] == ' ' || i == 0))
{
return count;
}
}
return -1;
}
A very simple C++20 solution using starts_with:
#include <string>
#include <sstream>
#include <iostream>
int isPrefixOfWord(std::string sentence, std::string searchWord)
{
int count = 1;
std::istringstream strm(sentence);
std::string word;
while (strm >> word)
{
if ( word.starts_with(searchWord) )
return count;
++count;
}
return -1;
}
int main()
{
std::cout << isPrefixOfWord("i love eating burger", "burg") << "\n";
std::cout << isPrefixOfWord("this problem is an easy problem", "pro") << "\n";
std::cout << isPrefixOfWord("this problem is an easy problem", "lo");
}
Output:
4
2
-1
Currently, LeetCode and many other of the online coding sites do not support C++20, thus this code will not compile successfully on those online platforms.
Therefore, here is a live example using a C++20 compiler
We can just use std::basic_stringstream for solving this problem. This'll pass through:
// The following block might slightly improve the execution time;
// Can be removed;
static const auto __optimize__ = []() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cout.tie(nullptr);
return 0;
}();
// Most of headers are already included;
// Can be removed;
#include <cstdint>
#include <string>
#include <sstream>
static const struct Solution {
static const int isPrefixOfWord(
const std::string sentence,
const std::string_view search_word
) {
std::basic_stringstream stream_sentence(sentence);
std::size_t index = 1;
std::string word;
while (stream_sentence >> word) {
if (!word.find(search_word)) {
return index;
}
++index;
}
return -1;
}
};
The bug that effects the function output is that you aren't handling the increment of i within your inner for loop:
for (int i = 0; i < sentence.length(); i++)
{
if (sentence[i] == ' ')
count++;
for (int j = i; j < sentence.length(); j++)
{
sub = sentence.substr(i, j);
cout<<sub<<endl;
if (sub == searchWord)
{
return count;
}
}
}
Notice that once your inner-loop is complete that i always iterates by one. So your next search through a word will incorrectly start at its next character, which incorrectly searches for "sub-words" instead of only prefixes, and so creates false positives (and unnecessary work).
Also note that every time that you do:
(sub == searchWord)
That this checks all j characters, even though we're only interested in whether the new jth character is a match.
Another bug, which effects your performance and your couts is that you're not handling mismatches:
if (sub == searchWord)
...is never false, so the only way to exit the inner loop is to keep increments j till the end of the array, so sub ends up being large.
A way to fix your second bug is to replace your inner loop like so:
if (sentence.substr(i, i + searchWord.length()) == searchWord)
return count;
and finally, to fix all bugs:
int isPrefixOfWord (const string & sentence, const string & searchWord)
{
if (sentence.length() < searchWord.length())
return -1;
const size_t i_max = sentence.length() - searchWord.length();
for (size_t i = 0, count = 1; ; ++count)
{
// flush spaces:
while (sentence[i] == ' ')
{
if (i >= i_max)
return -1;
++i;
}
if (sentence.substr(i, searchWord.length()) == searchWord)
return count;
// flush word:
while (sentence[i] != ' ')
{
if (i >= i_max)
return -1;
++i;
}
}
return -1;
}
Note that substr provides a copy of the object (it's not just a wrapper around a string), so this takes linear time with respect to searchWord.length(), which is particularly bad the word within sentence is smaller.
We can improve the speed by replacing
if (sentence.substr(i, searchWord.length()) == searchWord)
return count;
...with
for (size_t j = 0; sentence[i] == searchWord[j]; )
{
++j;
if (j == searchWord.size())
return count;
++i;
}
Others have shown nice applications of the libraries that help solve the problem.
If you don't have access to those libraries for your assignment, or if you just want to learn how you could modularise a problem like this without loosing efficiency, then here's a way to do it in c++11 without any libraries (except string):
bool IsSpace (char c)
{
return c == ' ';
}
bool NotSpace (char c)
{
return c != ' ';
}
class PrefixFind
{
using CharChecker = bool (*)(char);
template <CharChecker Condition>
void FlushWhile ()
{
while ((m_index < sentence.size())
&& Condition(sentence[m_index]))
++m_index;
}
void FlushWhiteSpaces ()
{
FlushWhile<IsSpace>();
}
void FlushToNextWord ()
{
FlushWhile<NotSpace>();
FlushWhile<IsSpace>();
}
bool PrefixMatch ()
{
// SearchOngoing() must equal `true`
size_t j = 0;
while (sentence[m_index] == search_prefix[j])
{
++j;
if (j == search_prefix.size())
return true;
++m_index;
}
return false;
}
bool SearchOngoing () const
{
return m_index + search_prefix.size() <= sentence.size();
}
const std::string & sentence;
const std::string & search_prefix;
size_t m_index;
public:
PrefixFind (const std::string & s, const std::string & sw)
: sentence(s),
search_prefix(sw)
{}
int FirstMatchingWord ()
{
const int NO_MATCHES = -1;
if (!search_prefix.length())
return NO_MATCHES;
m_index = 0;
FlushWhiteSpaces();
for (int n = 1; SearchOngoing(); ++n)
{
if (PrefixMatch())
return n;
FlushToNextWord();
}
return NO_MATCHES;
}
};
In terms of speed: If we consider the length of sentence to be m, and the length of searchWord to be n, then original (buggy) code had O(n*m^2) time complexity. But with this improvement we get O(m).

Sorting given text alphabetically w/o additional library

My homework was to write an application that sorts given text in alphabetically order. To do so, I was allowed only to use 'vector', 'string' and 'iostream' library.
I succeed but now struggling with strange problem - while I'm trying to sort a short text, everything works well but with longer inputs program seems to get into infinity loop or efficiency problem. Eg in text
"Albert Einstein 14 March 1879 – 18 April 1955 was a German-born theoretical physicist who developed the theory of relativity one of the two pillars of modern physics alongside quantum mechanics His work is also known[...]"
everything works great until "mechanics" phrase. After adding this, or any other word, program is running eternally like I mentioned before.
I'm afraid that I have to paste whole code in this case (please forgive).
#include <iostream>
#include <string>
#include <vector>
int compare(std::string first, std::string second){
int flag = 1;
int i;
if (first.size() <= second.size()){
for (i = 0; i<first.size(); ++i ){
if (first[i] == second[i]){
continue;}
else if (first[i] > second[i]){
flag = 0;
break;}
else {
break;}}}
else {
for (i = 0; i<second.size(); ++i ){
if (first[i] == second[i]) {
continue;}
else if (first[i] > second[i]){
flag = 0;
break;}
else {
break;}
}
int m = second.size() - 1;
if (first[m] == second[m]){
flag = 0;}}
return flag;}
int main() {
std::vector<std::string> text;
std::string word;
std::string tmp;
while(std::cin >> word){
text.push_back(word);}
int mistakes, m = 1;
while(m) {
mistakes = 0;
for (int index = 1; index < text.size() ; ++index){
if (!(compare(text[index-1], text[index]))){
tmp = text[index];
text[index] = text[index-1];
text[index-1] = tmp;
mistakes += 1;}}
m = mistakes;}
for (auto element: text){
std::cout << element << " ";}}
I would love to hear how to fix it and why exactly this problem appears - at least time of execution doesn't grow with lenght of input, but more like "work/doesn't work", what is unlike to efficency issues.
You had missed some conditions because of which your while loop running infinitely. For example:
Your mistakes variable on whose value your while loop executes never becomes 0, if the very first pair of words are in wrong order. Negative test case would be : "ball apple". In this case your code runs infinitely.
In your compare method because of following line of code test case like this "Apple ball" were giving wrong answers. Here first[m] = second[m] = l , thus according to your condition it will return false and swap them. It will swap "Apple" with "Ball" which is wrong.
int m = second.size() - 1;
if (first[m] == second[m]){
flag = 0;
}
You also need to handle the cases where there will be comparison between upper and lower case words. For example: "Month also". In this case answer should be "also Month". So before comparing two string you should bring them to same case and then compare.
Number comparison case where 1874 should come after 18. (you can add this)
Following is the corrected code.
#include <iostream>
#include <string>
#include <vector>
#include <cctype>
int compare(std::string first, std::string second){
// this is to handle the comparison of two words with mixed case(upper/lower) of letters.
// earlier solution failed for comparison between 'Month' and 'a'
for(int i=0;i<first.size();i++){
first[i] = tolower(first[i]);
}
for(int i=0;i<second.size();i++){
second[i] = tolower(second[i]);
}
int flag = 1;
int i;
if (first.size() <= second.size()){
for (i = 0; i<first.size(); ++i ){
if (first[i] == second[i]){
continue;}
else if (first[i] > second[i]){
flag = 0;
break;}
else {
break;}}}
else {
for (i = 0; i<second.size(); ++i ){
if (first[i] == second[i]) {
continue;}
else if (first[i] > second[i]){
flag = 0;
break;}
else {
break;}
}
}
return flag;}
int main() {
std::vector<std::string> text;
std::string word;
std::string tmp;
while(std::cin >> word){
text.push_back(word);}
// bubble short
for(int i=0;i<(text.size()-1);i++){
for(int j=0;j<(text.size()-1-i);j++){
if (!(compare(text[j], text[j+1]))){
tmp = text[j];
text[j] = text[j+1];
text[j+1] = tmp;
}
}
}
for (auto element: text){
std::cout << element << " ";}}

I am currently trying to save a set of integers in a int array, by redefining string into numbers, then store it in the array

I am trying to convert input text/numbers (string), which will include any characters, but I want to separate the numbers from the characters and store them into an integer array, once it is converted from a string.
I believe the problem is where the string is converting to an integer by use of stoi(), but I cannot seem to spot the problem.
Currently, the code accepts any input and turns it into a string, the string is then checked character by character, and all the numbers without separation with comma or space is added together, once a comma or space, or any other character separates the number, the number as a whole is added to the array, and then continues to check the string for more numbers.
Any ideas?
Input Example1: 12, 13, 15
Input Example2: 12 13 15
Input Example3: 12ab13cd15ef
Result in integer array: 0[12] 1[13] 2[15]
These numbers will be used in the specific order, by using the numbers within the array.
#include<iostream>
#include<string>
#include <sstream>
using namespace std;
int main()
{
string datainput, str1, str3;
cin >> datainput;
int n = 0, raycount = 0, c;
int myray[10];
while (datainput[n])
{
if (datainput[n] == ('0') || datainput[n] == ('1') || datainput[n] == ('2') || datainput[n] == ('3') || datainput[n] == ('4') ||
datainput[n] == ('5') || datainput[n] == ('6') || datainput[n] == ('7') || datainput[n] == ('8') || datainput[n] == ('9'))
{
str1 = datainput[n];
str3 += str1;
}
else
{
c= stoi(str3);
c >> myray[raycount];
raycount++;
}
n++;
}
cout << myray[0] << endl;
cout << myray[1] << endl;
cout << myray[2] << endl;
cout << myray[3] << endl;
system("pause");
return 0;
}
I see quite a few issues with your code.
Prior to C++11, while (datainput[n]) has undefined behavior once n reaches the end of the string.
The way you are checking for numeric digits can be greatly simplified using std::isdigit(), or even just a simple range check using the >= and <= operators.
You are not correctly accounting for numbers that are separated by other characters, or when the last number in the string is at the very end of the string.
The statement c >> myray[raycount]; needs to be changed to myray[raycount] = c; instead. And you are not breaking your loop if raycount reaches the max capacity of myray[].
You are not resetting str3 back to an blank string after converting it with std::stoi(). You just keep appending new digits to the end of previous digits with no break in between numbers.
With that said, try something more like this instead:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string datainput, str3;
cin >> datainput;
int myray[10];
int raycount = 0;
bool gettingDigits = false;
for (int n = 0; n < datainput.size(); ++n)
{
char ch = datainput[n];
//if (isdigit(ch))
if (ch >= '0' && ch <= '9')
{
if (!gettingDigits)
{
str3 = "";
gettingDigits = true;
}
str3 += ch;
}
else
{
if (gettingDigits)
{
myray[raycount] = stoi(str3);
raycount++;
str3 = "";
gettingDigits = false;
if (raycount == 10) break;
}
}
}
if (gettingDigits && (raycount < 10))
{
myray[raycount] = stoi(str3);
raycount++;
}
for (int n = 0; n < raycount; ++n)
cout << myray[n] << endl;
system("pause");
return 0;
}
Live Demo
Alternatively:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string datainput, str3;
cin >> datainput;
int myray[10];
int raycount = 0;
string::size_type start = datainput.find_first_of("0123456789");
string::size_type end;
while (start != string::npos)
{
end = datainput.find_first_not_of("0123456789", start+1);
if (end == string::npos)
{
str3 = datainput.substr(start);
myray[raycount] = stoi(str3);
raycount++;
break;
}
str3 = datainput.substr(start, end-start);
myray[raycount] = stoi(str3);
raycount++;
if (raycount == 10) break;
start = datainput.find_first_of("0123456789", end+1);
}
for (int n = 0; n < raycount; ++n)
cout << myray[n] << endl;
system("pause");
return 0;
}
Live Demo
So, you want to segregate numbers and characters into different arrays.
In if block, you are checking for characters, so, I suspect stoi() wouldn't work.
Better typecast it to an integer.
int temp[10];
if (datainput[n] == ('0') || ...) {
temp[n] = int(datainput[n]);
}
This way your temp array would contain the numbers.