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;
}
Related
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';
}
}
Trying to determine whether an index entry of a vector of strings is a letter or number. I am trying to use isdigit(), but it won't work because a suitable conversion can't be made using isdigit(stof(eq[i]))
Essentially, if I find that it is a letter, I want to change that value to 0.
#include string
#include vector
using namespace std;
vector <string> eq;
eq[0] = "a";
eq[1] = "3.5";
eq[2] = "7.5";
for (int i = 0; i < eq.size(); i++)
{
try {
isdigit(stof(eq[i]));
throw(eq[i]);
}
catch (exception e) {
cout << "eq[i] is not a number" << endl;
eq[i] == "0";
cout << "eq[i] = " << eq[i] << endl;
}
}
The question is, how could I assess if an index value is a letter, and then if it is, replace that letter with a zero?
How about just having a check as
if(eq[i].size() == 1 && std::isalpha(eq[i][0])) {
eq[i] = "0";
}
Would that work for your case?
EDIT: In case you have something like eq[3] = "abc"; i.e. entire strings rather just single letters, then something like this could be done:
if(
std::any_of(eq[i].cbegin(), eq[i].cend(), [](char c) {
return std::isalpha(c);
})
) {
eq[i] = "0";
}
Here's the documentation for std::any_of
Firstly, as #Peter notified, eq has size zero on creation, and assigning to eq[0], eq[1], and eq[2], cause undefined behaviors. This can be solved by using std::push_back().
Secondly, as #Jerry Jeremiah mentioned, isdigit() check if character is a decimal digit, so I don't see a point using that with stof(), which convert a string to a float.
This is the code that I modified from yours:
#include <string>
#include <vector>
#include <iostream>
using namespace std;
int main()
{
vector <string> eq;
//sample data
eq.push_back("a");
eq.push_back("3.5");
eq.push_back("7.5");
eq.push_back("5");
eq.push_back("xyz");
for (int i = 0; i < eq.size(); i++)
{
try
{
stof(eq[i]);
}
catch (exception e)
{
eq[i] = "0";
}
cout << "eq[" << i << "]" << " = " << eq[i] << endl;
}
}
Result:
eq[0] = 0
eq[1] = 3.5
eq[2] = 7.5
eq[3] = 5
eq[4] = 0
Also, it might be more practical to use the second parameter of stof() (as #Jerry Jeremiah noted), and use if statement instead of try-catch (as #Peter noted).
*Note: Running on Code::Blocks 20.03, g++ 6.3.0, Windows 10, 64 bit.
*More info:
stof() : https://www.cplusplus.com/reference/string/stof/
std::push_back() : https://www.cplusplus.com/reference/vector/vector/push_back/
isdigit() : https://www.cplusplus.com/reference/cctype/isdigit/
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.
I'm trying to write a program that first checks if a name is in a vector and if not then adds it to the vector. My code seems to have difficulties with parsing, at least that's what I get out of it. I tried changing the string to a char but it did not help me much.
#include <iostream>
#include <vector>
#include <string>
bool isinVector(std::string uElement, std::vector<std::string> uArray)
{
for (unsigned int i = 0; i <= sizeof(uArray); i++) {
if (uArray[i] == uElement) {
return true;
}
else {
return false;
}
}
}
int main()
{
bool trigger = false;
while (!trigger) {
std::vector<std::string> names;
names.push_back("Bart");
std::string newName;
getline(std::cin, newName);
if (isinVector(newName, names))
{
std::cout << "true" << std::endl;
trigger = true;
}
else
{
std::cout << "false" << std::endl;
names.push_back(newName);
for (int i = 0; i <= sizeof(names); i++) {
std::cout << names[i] << std::endl;
}
}
}
}
I made some adjustments to your code, removing your isinVector function and using a lambda inside the main function instead. In the future please provide a concise question and example.
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using std::vector;
using std::string;
using std::cout;
using std::cin;
using std::endl;
using std::find_if;
int main(){
bool trigger = false;
while (!trigger) {
vector<string> names;
names.push_back("Bart");
string newName;
getline(cin, newName);
if(find_if(names.begin(), names.end(), [newName] (const string& name){
return !name.compare(newName);
}) != names.end()){
cout << "true" << endl;
trigger = true;
}
else{
cout << "false" << endl;
names.push_back(newName);
for (size_t i = 0; i < names.size(); i++) {
cout << names.at(i) << endl;
}
}
}
return 0;
}
The code uses std::find_if to check if the element exists in the vector. If std::find_f does not return the iterator to uArray.end() Then the element exists. Also your for loop used sizeof which is incorrect, use the vector.size method. And you were looping until <= , it should be < uArray.size() And it's safer to access elements in the vector through the .at method rather than an index [] since the .at will throw an out_of_range exception.
Among the things wrong in the updated post.
Improper use of sizeof
Reinventing a standard algorithm
Lack of error checking
Consider the tasks you're trying to accomplish. You want to:
Initialize a starting vector containing the name Bart
Continuously read new names. For each new name read:
a. Check to see if it is already in the vector.
if it is present terminate the read loop
else add it to the vector, and print the entire vector
This sequence of operations can be accomplished with stepwise refinement.
Step 1. Read names
First, you need to be able to continuously read names:
#include <iostream>
#include <string>
int main()
{
std::string name;
while (std::getline(std::cin, name))
std::cout << name << '\n';
}
Simple enough. Running this will echo any strings you type, one at a time, separated by newlines.
Step 2. Accumulate names in a vector
Next, we need to add a vector to hold the strings we're reading, with an initial population of the name "Bart". For this pass we'll be just putting every string we read into the vector
#include <iostream>
#include <vector>
#include <string>
int main()
{
std::vector<std::string> names = { "Bart" };
std::string name;
while (std::getline(std::cin, name))
{
names.emplace_back(name);
for (auto const& s : names)
std::cout << s << ' ';
std::cout.put('\n');
}
}
In addition to what was done prior, we're now accumulating strings in the vector, including duplicates, and reporting the vector content after each name read. This gets us closer to our stated goal.
Step 3: Conditional loop exit based on duplicate detection
Now we need to check for duplicates, and terminate the loop once it happens. We can do this using std::find. The final code is below:
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
int main()
{
std::vector<std::string> names = { "Bart" };
std::string name;
while (std::getline(std::cin, name))
{
if (std::find(names.begin(), names.end(), name) != names.end())
break;
names.emplace_back(name);
for (auto const& s : names)
std::cout << s << ' ';
std::cout.put('\n');
}
}
That's it. This is a simple task, but it lends itself nicely to an example of how you break a multi-part task down to manageable objectives , then build it in pieces.
Hope you found it useful.
Now my code looks like this:
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
bool isinVector (std::string uElement, std::vector<std::string> uArray) {
bool invector = false;
std::vector<std::string>::iterator it = std::find(uArray.begin(),
uArray.end(),uElement);
if(it != uArray.end()){
invector = true;
}
return invector;
}
int main(){
bool trigger = false;
std::string name;
std::vector<std::string> names = { "Bart" };
while (std::getline(std::cin, name)){
if (isinVector(name, names)) {
std::cout << "true" << std::endl;
break;
}
else
{
std::cout << "false" << std::endl;
names.emplace_back(name);
}
}
return 0;
}
and it works, thanks a lot guys!
The valid charaters are
// ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_/
#include <iostream>
#include <string>
using namespace std;
int main();
{
bool bIsValid = true;
// test characters
string strCheck("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_/");
string s("foo#?+baa") ; // should bring a "false" because of the "#?+" characters
string::const_iterator it = strCheck.begin();
// this is NOT a clever soulution has anybody a better idea ?
while (s.find(*it) != string::npos)
{
++it;
if(!s.find((*it))
{
bIsValidKey = false;
break;
}
}
cout << "Is Valid: " << bIsValid << endl ;
}
My problem is how can a get the first charater after the iteratorpoint to compare
with the allowed charactes. I need something like (*it).first_charater_after to
solve the problem.
Dos anybody has an other idea to check that in the string only exists a defined
number of charaters?
Use string::find_first_not_of?
Try this:
#include <iostream>
#include <string>
#include <regex>
using namespace std;
int main()
{
bool bIsValid = true;
string s("GHHbaa111__") ; // Add/remove other characters
regex r("^[[:alnum:]_]*$");
if (regex_match(s,r)) {
cout << "Valid string" << endl;
} else {
cout << "Invalid string" << endl;
}
}
#include <iostream>
#include <string>
int main() {
bool bIsValid = true;
// test characters
std::string strCheck("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_/");
std::string s("foo#?+baa") ; // should bring a "false" because of the "#?+" characters
if (s.find_first_not_of(strCheck) != std::string::npos)
bIsValid = false;
std::cout << "Is Valid: " << bIsValid << std::endl ;
}