I have a string S consisting of N letters 'a' or 'b'. This should return true when all occurrences of 'a' are before all occurrences of 'b' and return false otherwise.
b does not need to occur in S and a does not need to occur in S
For example
S='aabbb' returns true
S = 'ba' returns false
S = 'aaa' returns true
S= 'b' returns true
S='abba' returns false
this is my solution but it displays 1 extra true. I don't know why.
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
vector <string> vec;
int n;
string item;
int contora=0,contorb=0;
cout<<"n: ";
cin>>n;
cout << "Enter a string: ";
for(int i=0;i<= n;i++){
getline(cin, item);
//cin>>item;
vec.push_back(item);
}
for (int j=0; j <= n; j++) {
cout << vec[j];
}
cout<<endl;
for (auto of:vec) {
if (of.find("ba") != std::string::npos)
cout << "false";
else
cout<<"true";
}
return 0;
}
Wording it differently, you're trying to check if there are any characters in the string that come after a. If the answer is no, your function will return true, and false otherwise.
bool HasCorrectOrder(char prefix_char, char suffix_char, std::string_view str) {
if (str.empty()) {
return true;
}
// Run through all the preceeding characters.
int index = 0;
while (str[index] == prefix_char && index < str.size()) {
++index;
}
// At this point, if we've reached the end of the string, that means there are
// no characters after the preceeding character. So we can return true.
if (index == str.size()) {
return true;
}
// As there are more characters left, they should all be equal to the
// suffix_char in order for the ordering to be correct.
while (str[index] == suffix_char && index < str.size()) {
++index;
}
return (index == str.size());
}
Running a quick check:
void RunTest() {
std::vector<std::string> test_strings = {"aabbb", "ba", "aaa", "b", "abba"};
for (std::string_view str : test_strings) {
std::cout << "S = " << str << " returns "
<< (HasCorrectOrder(/*prefix_char=*/'a',
/*suffix_char=*/'b', str) ? "true" : "false")
<< std::endl;
}
}
returns:
S = aabbb returns true
S = ba returns false
S = aaa returns true
S = b returns true
S = abba returns false
Adding some debug output to the code shows a couple of issues:
The first for loop reads in n+1 strings, while we are expecting the user to enter only n strings. The second for loop also prints n+1 strings, although that's not a problem, because the vector contains n+1 elements.
Due to mixing both std::cin >> and std::getline for reading user input, the first string read with std::getline is empty. You would need whether to:
use std::getline for all the user input readings (and, for n, convert the string to a number), or
flush the input buffer with cin.ignore after the std::cin >>, as explained in this answer.
The code below fixes those two issues and adds some debug output (it also follows a few best practices such as, not using namespace std;, defining variables next to their first use, value-initializing local variables, and using block braces even for one-line blocks).
[Demo]
#include <iostream> // cin, cout
#include <limits>
#include <string> // getline
#include <vector>
int main() {
int n{};
std::cout << "n: ";
std::cin >> n;
std::cout << n << "\n\n";
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
std::vector<std::string> vec{};
for (int i = 0; i < n; i++) {
std::cout << "Enter a string: ";
std::string item{};
std::getline(std::cin, item);
std::cout << "item: " << i << ": '" << item << "'\n";
vec.push_back(item);
}
std::cout << "\n";
for (auto& of : vec) {
std::cout << "'" << of << "': ";
if (of.find("ba") != std::string::npos) {
std::cout << "false\n";
} else {
std::cout << "true\n";
}
}
}
// Outputs:
//
// n: 5
//
// Enter a string: item: 0: 'aabbb'
// Enter a string: item: 1: 'ba'
// Enter a string: item: 2: 'aaa'
// Enter a string: item: 3: 'b'
// Enter a string: item: 4: 'abba'
//
// 'aabbb': true
// 'ba': false
// 'aaa': true
// 'b': true
// 'abba': false
For this particular case, you could also use std::is_partitioned. This algorithm tells you if all the elements of a range that satisfy a given predicate appear before all the elements that don't (see here). The predicate would check if a character is equal to 'a'.
[Demo]
#include <algorithm> // is_partitioned
#include <cstring> // strlen
#include <fmt/core.h>
int main() {
for (auto&& s : { "aabbb", "ba", "aaa", "b", "abba" }) {
fmt::print("'{}': {}\n", s, std::is_partitioned(s, s + strlen(s),
[](unsigned char c) { return c == 'a'; }));
}
}
After fixing the loop logic, here is another simple solution you could use, with the is_sorted algorithm:
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
int main() {
// ...
for (auto of : vec)
std::cout << std::boolalpha << std::ranges::is_sorted(of);
}
This compiles with C++20 support, and it works because strings are ranges of characters, for which an operator< is defined. It happens to be the case that 'a' < 'b', so this simple expression is all you need.
You just need to find "ba" occurrences.
C++ string type already provides such function. Complexity is linear on string length O(n)
#include <iostream>
#include <string>
void checker(const std::string S)
{
if (S.find("ba") != std::string::npos) {
std::cout << "false" << '\n';
} else {
std::cout << "true" << '\n';
}
}
Related
Relatively new to c++.
Having trouble understanding an issue I am having with the compare() function returning 1 instead of 0.
I have a program which reads a text file containing an arbitrary number of questions and answers for a quiz. It is formatted as such:
Q: How many days in a week?
A: seven
I have three files, main.cpp, Quiz.cpp, and Quiz.h:
main.cpp:
#include <iostream>
#include <vector>
#include <fstream>
#include <algorithm>
#include <ctime>
#include <cstdlib>
#include "Quiz.h"
using namespace std;
int main(int argc, char* argv[]){
srand(unsigned(time(0)));
vector<Quiz> quizVector;
ifstream inputQuiz;
inputQuiz.open(argv[1]);
string q, a;
int questionCount = 0;
if(inputQuiz.is_open()){
getline(inputQuiz, q);
getline(inputQuiz, a);
while(!inputQuiz.eof()){
Quiz *instance = new Quiz(q, a);
quizVector.push_back(*instance);
questionCount++;
getline(inputQuiz, q);
getline(inputQuiz, a);
}
}
random_shuffle(quizVector.begin(), quizVector.end());
string userInput;
for(int i = 0; i < questionCount; i++){
cout << quizVector[i].getQuestion() << endl;
cout << "A: ";
getline(cin, userInput);
if(quizVector[i].getAnswer().compare("A: " + userInput) == 0){
cout << "Correct." << endl;
}
else{
cout << "Incorrect." << endl;
}
}
return 0;
}
Quiz.cpp:
#include <string>
#include "Quiz.h"
int Quiz::score = 0;
std::string Quiz::getQuestion(){
return question;
}
std::string Quiz::getAnswer(){
return answer;
}
Quiz.h:
#ifndef QUIZ_H
#define QUIZ_H
class Quiz{
private:
std::string question {""};
std::string answer {""};
public:
Quiz() = default;
Quiz(std::string q, std::string a) : question {q}, answer {a} {}
std::string getQuestion();
std::string getAnswer();
};
#endif
My problem lies within main.cpp:
for(int i = 0; i < questionCount; i++){
cout << quizVector[i].getQuestion() << endl;
cout << "A: ";
getline(cin, userInput);
if(quizVector[i].getAnswer().compare("A: " + userInput) == 0){
cout << "Correct." << endl;
}
else{
cout << "Incorrect." << endl;
}
}
When I input the correct answer corresponding to each question, compare() does not return 0, but consistently returns 1. There are no leading or trailing spaces at the start or ends of each line in the text file. Am I misunderstanding how getline() or compare() works? Is it something else? Any help is appreciated!
I see a number of problems with this code:
std::random_shuffle() is deprecated in C++14 and removed in C++17, use std::shuffle() instead.
you are not validating that argv contains an input parameter before using it.
Your use of eof() in the while loop is wrong. For instance, if the last question/answer pair in the file is terminated by EOF instead of a line break, getline() will still return the question/answer to you, but it will also set the eofbit flag on the stream, which will cause eof() to return true and thus you will skip saving the last pair into the vector. The stream is not technically in a failed state yet in this situation (see the diagram at https://en.cppreference.com/w/cpp/io/basic_ios/eof), so you shouldn't skip the last pair if it terminates with EOF rather than a line break.
Your while loop is leaking memory.
you don't need questionCount at all, use quizVector.size() instead. Or better, a range-for loop.
you don't really need to use compare() at all, you can use operator== instead. But, if you do use compare(), you should take into account that it is case-sensitive (as is operator==). You should also take advantage of the fact that compare() lets you specify an index to start comparing from, so you can ignore the A: prefix in the stored answer (alternatively, you could just strip off the Q: and A: prefixes when storing the question/answer in Quiz's constructor). Otherwise, you can use your compiler's strcmpi() function instead (if it offers one).
Try something more like this instead:
#include <iostream>
#include <vector>
#include <fstream>
#include <algorithm>
#include <random>
#include <cctype>
#include "Quiz.h"
using namespace std;
string toLowercase(string s) {
transform(s.begin(), s.end(), s.begin(),
[](unsigned char c){ return tolower(c); }
);
return s;
}
int main(int argc, char* argv[]){
if (argc < 2){
cerr << "Please specify a file to open!" << endl;
return 0;
}
ifstream inputQuiz(argv[1]);
if (!inputQuiz.is_open()) {
cerr << "Can't open the file!" << endl;
return 0;
}
vector<Quiz> quizVector;
string q, a, userInput;
while (getline(inputQuiz, q) && getline(inputQuiz, a)) {
quizVector.emplace_back(q, a);
}
random_device rd;
mt19937 g(rd());
shuffle(quizVector.begin(), quizVector.end(), g);
for(auto &quiz : quizVector){
cout << quiz.getQuestion() << endl;
cout << "A: ";
getline(cin, userInput);
userInput = toLowercase(userInput);
a = toLowercase(quiz.getAnswer());
if (a == ("a: " + userInput)) {
// or:
// if (a.compare(2, string::npos, userInput) == 0) {
// or, if you strip off "A:" beforehand:
// if (a == userInput) {
cout << "Correct." << endl;
}
else {
cout << "Incorrect." << endl;
}
}
return 0;
}
I need to write a program that gives the results of arithmetic operations for large positive integers. There are 4 basic operations to consider: addition (+), subtraction (-), multiplication (*) and division of integers (/). The first line of the standard input contains a single integer Z that determines the number of tests defined in the upcoming lines. Each test occupies one line of the standard input and contains a record of one arithmetic action, i.e., two strings of digits separated by an action operator (without additional spaces). The digit sequences are no more than 256 characters long. That's what I wrote to this moment:
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
int Z;
string operacja(256,'\0');
cin >> Z;
vector <string> operacje;
for (int i = 0; i < Z; i++)
{
cin >> operacja;
operacje.push_back(operacja);
}
cout << "" << endl;
for(auto it = begin(operacje); it != end(operacje); ++it)
{
if (find_if(operacje.begin(), operacje.end(), [](const string& str) { return str.find("+") != std::string::npos; }) != operacje.end())
{
cout << "+" << endl;
}
else if (find_if(operacje.begin(), operacje.end(), [](const string& str) { return str.find("-") != std::string::npos; }) != operacje.end())
{
cout << "-" << endl;
}
else if (find_if(operacje.begin(), operacje.end(), [](const string& str) { return str.find("*") != std::string::npos; }) != operacje.end())
{
cout << "*" << endl;
}
else if (find_if(operacje.begin(), operacje.end(), [](const string& str) { return str.find("/") != std::string::npos; }) != operacje.end())
{
cout << "/" << endl;
}
}
return 0;
}
When I run the code I get this:
3
124/5
678-7
8/454545
-
-
-
I'm supposed to get this:
3
124/5
678-7
8/454545
/
-
/
Can somebody please help me fixing this?
Do it like this
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
vector <string> operacje;
operacje.push_back("124/5");
operacje.push_back("678-7");
operacje.push_back("8/454545");
for (const string& str: operacje)
{
if (str.find("+") != string::npos)
{
cout << "+" << endl;
}
else if (str.find("-") != string::npos)
{
cout << "-" << endl;
}
else if (str.find("*") != string::npos)
{
cout << "*" << endl;
}
else if (str.find("/") != string::npos)
{
cout << "/" << endl;
}
}
return 0;
}
Just iterate through the strings in the vector and check for the wanted characters. find_if is like a loop in itself and you weren't using the outer for loop at all. The result was that the operation was the same thing each time, as it started at the beginning of the vector every time.
Note this approach does have a fatal flaw, as - could be used to mean negative instead of subtract. So 5 * -3. Would do the wrong thing.
string a = MwZwXxZwDwJrBxHrHxMrGrJrGwHxMrFrZrZrDrKwZxLrZrFwZxErMrXxArZw;
Assume i have this data in my string . I want to record how many M , Z , X , D , J (including those capital letters i didn't mentions ) in in string how can do it ? My friends say use vector can do it but i does not really know how to use vector is there any alternative way to do it .
I tried using for loops to do and find the M , and reset the pointer to 0 to continue find the next capital value , but not sure is there any easier way to do it .
first I'll show you a 'easier' way to me.
#include <iostream>
#include <map>
using namespace std;
int main(int argc, const char * argv[]) {
string str = "MwZwXxZwDwJrBxHrHxMrGrJrGwHxMrFrZrZrDrKwZxLrZrFwZxErMrXxArZw";
map<char,int> map;
for (int i=0; i<str.length(); i++) {
char ch = str[i];
if (isupper(ch)) {
map[ch] ++;
}
}
for (auto item : map) {
cout<<item.first<<':'<<item.second<<endl;
}
return 0;
}
you'll only need to use 1 loop to solve your problem.
the 'isupper(int _c)' is a function from the standard library, it can tell you wether a character is a capital letter.
the 'map' is a data structure from the standard library too, it can do key-value storage for you.
this program outputs this:
A:1
B:1
D:2
E:1
F:2
G:2
H:3
J:2
K:1
L:1
M:4
X:2
Z:8
is this what you want?
Use regex.
using namespace std;
// regex_search example
#include <iostream>
#include <string>
#include <regex>
int main ()
{
std::string s ("MwZwXxZwDwJrBxHrHxMrGrJrGwHxMrFrZrZrDrKwZxLrZrFwZxErMrXxArZw;");
std::smatch m;
std::regex e ("[A-Z\s]+");
map<string,int> map;
std::cout << "Target sequence: " << s << std::endl;
std::cout << "Regular expression: [A-Z\s]+" << std::endl;
std::cout << "The following matches and submatches were found:" << std::endl;
while (std::regex_search (s,m,e)) {
for (auto x:m)
{
//cout << x << " ";
map[x.str()] ++;
}
//cout << std::endl;
s = m.suffix().str();
}
for (auto item : map) {
cout<<item.first<<':'<<item.second<<endl;
}
return 0;
}
The most direct translation of "loop through the string and count the uppercase letters" into C++ I can think of:
#include <iostream>
#include <map>
#include <cctype>
int main()
{
string a = "MwZwXxZwDwJrBxHrHxMrGrJrGwHxMrFrZrZrDrKwZxLrZrFwZxErMrXxArZw";
std::map<char, int> count;
// Loop through the string...
for (auto c: a)
{
// ... and count the uppercase letters.
if (std::isupper(c))
{
count[c] += 1;
}
}
// Show the result.
for (auto it: count)
{
std::cout << it.first << ": " << it.second << std::endl;
}
}
Here's my code:
#include <iostream>
using namespace std;
string moveString(string t, int index)
{
for (int i=index; t[i]!=NULL;i++)
{
t[i]=t[i+1];
}
return t;
}
string delChars(string t)
{
for (int i=0; t[i]!=NULL; i++)
{
if (t[i]>'a' && t[i]<'z')
{
moveString(t, i);
}
else if (t[i]>'A' && t[i]<'Z')
{
moveString(t, i);
}
}
return t;
}
int main()
{
int numberOfSpaces;
string t;
cout << "Text some word: "; cin>>t;
cout<<delChars(t);
return 0;
}
First function moveString should (in theory) take down every single character from a string by 1 index down (starting from given index) - to remove 1 character. The rest is pretty obvious. But:
Input: abc123def
Output: abc123def
What am I doing wrong?
And a additional mini-question: Acutally, what's the best way to "delete" an element from an array? (array of ints, chars, etc.)
Logic Stuff is right but his answer is not enough. You shouldn't increase i after move. Since the i.th character is removed and i points to the next character now.
string delChars(string t)
{
for (int i=0; t[i]!=NULL; )
{
if (t[i]>'a' && t[i]<'z')
{
t = moveString(t, i);
}
else if (t[i]>'A' && t[i]<'Z')
{
t = moveString(t, i);
}
else
i++;
}
return t;
}
moveString takes t by value and you're not assigning its return value, so it doesn't change t in delChars. So, make sure the next thing you learn are references.
Apart from that, I don't know what to tell about t[i] != NULL (if it is undefined behavior or not), but we have std::string::size to get the length of std::string, e.g. i < t.size(). And if you havet[i + 1], the condition should then be i + 1 < t.size().
Whatever, don't play with it like with char arrays, leaving the string with previous size. You can pop_back the last (duplicate) character after shifting the characters.
It's worth mentioning that it can be done in one line of idiomatic C++ algorithms, but you want to get your code working...
What am I doing wrong?
Not using standard algorithms
Actually, what's the best way to "delete" an element from array? (array of ints, chars, etc.)
By using the standard remove-erase idiom:
#include <iostream>
#include <string>
#include <algorithm>
#include <iomanip>
#include <cstring>
int main()
{
using namespace std;
auto s = "!the 54 quick brown foxes jump over the 21 dogs."s;
cout << "before: " << quoted(s) << endl;
s.erase(std::remove_if(s.begin(),
s.end(),
[](auto c) { return std::isalpha(c); }),
s.end());
cout << "after: " << quoted(s) << endl;
return 0;
}
expected output:
before: "!the 54 quick brown foxes jump over the 21 dogs."
after: "! 54 21 ."
I'm not allowed to use standard algorithms
Then keep it simple:
#include <iostream>
#include <string>
#include <algorithm>
#include <iomanip>
#include <cstring>
std::string remove_letters(const std::string& input)
{
std::string result;
result.reserve(input.size());
for (auto c : input) {
if (!std::isalpha(c)) {
result.push_back(c);
}
}
return result;
}
int main()
{
using namespace std;
auto s = "!the 54 quick brown foxes jump over the 21 dogs."s;
cout << "before: " << quoted(s) << endl;
auto s2 = remove_letters(s);
cout << "after: " << quoted(s2) << endl;
return 0;
}
Beginner C++ student here, first ever programming class. I am trying to put together a program that will identify if a string is all lower case or not. I got as far as the code below. However, I need to account for spaces " ". If there is a space in the string that is input by the user, the program is suppose to return that it is not all lower case. Example:
input: abc def
return: The string is not lower case.
Would any of you ever so kindly advise what would be the best way to account for this in the code below?
NOTE: I know I have 'included' some extra header files, but that is because this is going to be part of another program and this is just an excerpt to get things running.
Thank you so very much all!!
#include <fstream>
#include <iostream>
#include <string>
#include <cstdlib>
#include <algorithm>
#include <cctype>
#include <iomanip>
using namespace std;
bool die(const string & msg);
bool allLower(const string & l);
int main() {
string l;
cout << "\nEnter a string (all lower case?): ";
cin >> l;
if (allLower(l) == true)
{
cout << "The string is lower case." << endl;
}
else
{
cout << "The string is not lower case." << endl;
}
}
bool allLower(const string & l) {
struct IsUpper {
bool operator()(int value) {
return ::isupper((unsigned char)value);
}
};
return std::find_if(l.begin(), l.end(), IsUpper()) == l.end();
}
bool die(const string & msg){
cout << "Fatal error: " << msg << endl;
exit(EXIT_FAILURE);
}
You could use a good old fashion for-loop.
bool allLower(const std::string & l)
{
for(unsigned int i = 0; i < l.size(); i++)
{
if(l[i] == ' ')
{
return false;
}
else if(isalpha(l[i]))
{
if(isupper(l[i]))
return false;
}
}
return true;
}
Note that if you feed it in something like "2" it will return true. You could add a final else statement that returns false if you so desire.
You can check to see if a character is alphabetic using the function std::isalpha() prior to using std::isupper() or std::islower() to checking whether all letters within your string are uppercase/lowercase, etc
A range-based for loop would be clearer than indices IMO
bool allLower(const std::string &l)
{
for (auto c : l)
{
if ((c == ' ') ||
(std::isalpha(c) && std::isupper(c)))
{
return false;
}
}
return true;
}