I only want to loop through certain Ascii characters and not all are directly next to each other . For example I only want to loop from char '1 to 7' and then from char '? to F'. I dont want to loop through '8 to >' . I have this for loop but this will include the char I don't want.
for (char i = '1'; i < 'H'; i++)
How should I modify it to only loop through what I want?
Looping from 1 to 7 is straight-forward, since the arabic numerals ('0' to '9') are required to continguous and increasing values by all C and C++ standards.
for (char c = '1'; c <= '7'; ++c)
or (a more common style)
for (char c = '1'; c < '8'; ++c)
The problem with trying to loop through your second set of ASCII characters ('?' to 'F') is that there are character sets other than ASCII - in which the order of characters is different. For example, in ASCII, '?' is one less than '#', but that is not guaranteed for other character sets. Instead, create a string with the characters you want to loop over, and iterate over the string. For example;
const std::string characterset = "?#ABCDEF";
for (char c : characterset) // option 1, C++11 and later
{
// do something with c
}
for (auto c : characterset) // option 2, C++11 and later (type deduction)
{
// do something with c
}
// Option 3 (all C++ standards)
for (std::string::const_iterator it = characterset.begin(), end = characterset.end();
it != end; ++it)
{
char c = *it;
// do something with *it or c (it is an iterator that references a character)
}
will loop over your second set of characters.
If you want to do it all in a single loop, then change the character set. For example, a modified version of Option 1 above might be;
const std::string characterset = "1234567?#ABCDEF";
This is a more general approach that doesn't rely on your implementation (host system, compiler, library) supporting the ASCII character set (or compatible).
Each character has a fixed ASCII value associated with it. You can refer to any character with that particular ASCII value. You can just skip the characters you do not want with an 'if' condition. You will find all the ASCII values here. Referring to your example, if you want to skip the characters from '?' to 'F', the code might look something like this:
#include <iostream>
using namespace std;
int main()
{
for (char i = '1'; i < 'H'; i++)
{
if(i>=63 && i<=70)
// 63 is the ASCII value for '?'
// 70 is the ASCII value for 'F'
{
// skipping the ASCII values we do not need
continue;
}
cout << i << "";
}
return 0;
}
Create a set containing the characters you want to loop over and loop over that set.
For example :
#include <iostream>
#include <stdexcept>
#include <string>
#include <set>
// character_set.h
//-------------------------------------------------------------------------
// To be able to easily input a character range we need a helper struct
struct character_range_t
{
// have this destructor so a character range can be used in brace initialization.
character_range_t(const char f, const char t) :
from(f),
to(t)
{
if (to < from) throw std::invalid_argument("to must be larger or equal to from");
}
char from;
char to;
};
//-------------------------------------------------------------------------
// helper function to combine multiple character ranges into on set
// input is a compile time array of ranges
template<std::size_t N>
auto make_character_set(const character_range_t(&ranges)[N])
{
// I chose a set because all elements must be unique and set does that.
std::set<char> set;
// loop over all input ranges
for (std::size_t n = 0; n < N; ++n)
{
// and for each range add the characters in the range to the set
for (char c = ranges[n].from; c <= ranges[n].to; ++c) set.insert(c);
}
return set;
}
// main.cpp
//-------------------------------------------------------------------------
// #include "character_set.h"
int main()
{
auto set = make_character_set({{'1','7'},{'?','F'}});
// use range based for loop to loop over all characters in the set
for (const char c : set)
{
std::cout << c << " ";
}
}
Related
Basically I need to check if the characters found in second string can make the first string. The program works, however I have this problem that it doesn't take the character order in mind.
For example if I input:
UMC UniverseCeeMake ==> Yes
but it should input No because UMC != UCM, how can I make it check the character order aswell? can someone assist?
#include <iostream>
#include <string>
using namespace std;
const int MAX = 256;
bool canMakeStr2(string str1, string str2)
{
int count[MAX] = {0};
for (int i = 0; i < str1.length(); i++)
count[str1[i]]++;
for (int i = 0; i < str2.length(); i++)
{
if (count[str2[i]] == 0)
return false;
count[str2[i]]--;
}
return true;
}
int main()
{
int n;
string str1;
string str2;
cin>>n;
for(int i =0;i<n;i++){
cin >> str1 >> str2;
if(str1.length()<=10000 && str2.length()<=10000)
if (canMakeStr2(str2, str1))
cout << "Yes";
else
cout << "No";
}
return 0;
}
As Fabian has alread stated. You approach with counting letters will not work. You will never cover the sequence.
You need to select a different approach. The most easy one is to use the std::strings existing find function.
So, you will go over all characters in the given character set in the correct sequence with a simple range based for loop. Then you can use the find function to check, if the character is existing in the other string.
To ensure the sequence, you must not search always from the beginning, but from the last poasition (+1) where a character was found. This will keep the ensure the sequence.
Example:
UMC UniverseCeeMake
Search for the 'U' starting from the beginning
'U' Found at position 0. Increment start position to 1
Search for 'M' staring from position 1
'M' found at position 11 (already behind the 'C'). Increment start position to 12
Search for a 'C' starting at position 12
Cannot be found --> Result will be "No"
This can be implemented very easyly:
#include <iostream>
#include <string>
bool canMakeStr(std::string toBeChecked, std::string characterSet) {
// Result of function. We assume that it will work
bool result{ true };
// position, where we find a charcted in the string to be checked
size_t position{};
// Go through all characters from the given character set
for (const char c : characterSet) {
// Look, where this character has been found
position = toBeChecked.find(c, position);
// If we could not find the character in the string to be checked
if (position == std::string::npos) {
// Then the result is false
result = false;
break;
}
else {
// Character was found. Now, we implement the solution to check for the sequence
// We will not start to search again at the beginning, but after the just found character
// This will ensure that we keep the sequence
++position;
}
}
return result;
}
int main()
{
// Read the number of test cases
unsigned int numberOfTestCases; std::cin >> numberOfTestCases;
// Work on all test cases
while (numberOfTestCases--) {
// Read the 2 strings
std::string characterSet, toBeChecked; std::cin >> characterSet >> toBeChecked;
// And check for the result
if (canMakeStr(toBeChecked, characterSet))
std::cout << "Yes\n";
else
std::cout << "No\n";
}
return 0;
}
I'm trying to write a program that looks at the last letter of each word in a single string and determines if it ends in y or z and count it.
For example:
"fez day" -> 2
"day fyyyz" -> 2
Everything I've looked up uses what looks to be arrays, but I don't know how to use those yet. I'm trying to figure out how to do it using for loops.
I honestly don't know where to start. I feel like some of my smaller programs could be used to help this, but I'm struggling in trying to figure out how to combine them.
This code counts the amount of words in a string:
int words = 0;
bool connectedLetter;
for (auto c : s)
{
if (c == ' ')
{
connectedLetter = false;
}
if ( c != ' ' && connectedLetter == false)
{
++words;
connectedLetter = true;
}
and it might be useful to try and figure out how to get the code to see separate words.
I've used this program to count the amount of vowels in the entire program:
int vowels{0};
for (auto c : s)
{
if (c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u'
|| c == 'A' || c == 'E' || c == 'I' || c == 'O' || c == 'U')
{
++vowels;
}
}
and then I've done a small program to see every other letter in a string
auto len = s.size();
for (auto i = 0; i < len; i = i + 2)
{
result += s.at(i);
}
I feel like I know the concepts behind it, but its configuring it together which is stopping me
You may also use existing C++ functions that are dedicated to do, what you want.
The solution is to take advantage of basic IOstream functionalities. You may know that the extractor operator >> will extract words from an stream (like std::cin or any other stream) until it hits the next white space.
So reading words is simple:
std::string word{}; std::cin >> word;
will read a complete word from std::cin.
OK, we have a std::string and no stream. But here C++ helps you with the std::istringstream. This will convert a std::string to a stream object. You can then use all iostream functionalities with this stringstream.
Then, for counting elements, following a special requirement, we have a standard algorithm from the C++ library: std::count_if.
It expects a begin and an end iterator. And here we simply using the std::istream_iterator which will call the extractor operator >> for all strings that are in the stream.
WIth a Lambda, given to the std::count_if, we check, if a word meets the required condition.
We will get then a very compact piece of code.
#include <iostream>
#include <sstream>
#include <string>
#include <algorithm>
#include <iterator>
int main() {
// test string
std::string testString{ "day fyyyz" };
// We want to extract words from the string, so, convert string to stream.
std::istringstream iss{ testString };
// count words, meeting a special condition
std::cout << std::count_if(std::istream_iterator<std::string>(iss), {},
[](const std::string& s) { return s.back() == 'y' || s.back() == 'z'; });
return 0;
}
Of course there are tons of other possible solutions.
Edit
Pete Becker asked for a more flexible solution. Also here C++ offers a dedicated functionality. The std::sregex_token_iterator.
Here we can specify any word pattern with a regex and the simply get or count the matches.
An even simpler piece of code is the result:
#include <iostream>
#include <string>
#include <vector>
#include <iterator>
#include <regex>
const std::regex re{ R"(\w+[zy])" };
int main() {
// test string
std::string s{ "day, fyyyz, abc , zzz" };
// count words, meeting a special condition
std::cout << std::vector(std::sregex_token_iterator(s.begin(), s.end(), re), {}).size();
return 0;
}
If you're not going to use an array (or something similar, like a string) it's probably easiest to just use two ints. For simplicity, let's call them current and previous. You'll also need a count, which you'll want to initialize to 0.
Start by initializing both to EOF.
Read a character into current.
If current is a space or EOF (well, anything you don't consider part of a word), and previous is z or previous is y, increment count.
If current is EOF, print out count, and you're done.
Copy the value in current into previous.
Go back to step 2.
std::string is much smarter than many people realize. In particular, it has member functions find_first_of, find_first_not_of, find_last_of, and find_last_not_of that are very helpful for simple parsing. I'd approach it like this:
std::string str = "fez day"; // for example
std::string targets = "yz";
int target_count = 0;
char delims = ' ';
std::string::pos_type pos = str.find_first_not_of(delims);
while (pos < str.length()) {
pos = str.find_first_of(delims, pos);
if (pos == std::string::npos)
pos = str.length();
if (targets.find(str[pos-1] != std::string::npos)
++target_count;
pos = str.find_first_not_of(delims, pos);
}
std::cout << target_count << '\n';
Now, if I need to change this to accommodate comma-separated words, I just change
char delims = ' ';
to
std::string delims = " ,";
or to
const char* delims = " ,"; // my preference
and if I need to change the characters that I'm looking for, just change the contents of targets. (In fact, I'd use const char* targets = "xy"; and search with std::strchr, which reduces overhead a bit, but that's not particularly important.)
I am looking to replace the elements of character string with integer elements. I want to replace A with 1, B with 2, C with 3 and D with 4.
How can I do it efficiently?
#include <iostream>
#include <string>
#include <algorithm>
int main()
{
std::string str = "ABCDDCBA";
std::replace(str.begin(), str.end(), 'A', '1'); // Replacing
std::replace(str.begin(), str.end(), 'B', '2');
std::replace(str.begin(), str.end(), 'C', '3');
std::replace(str.begin(), str.end(), 'D', '4');
// ...
std::cout << str << std::endl; // displaying
return 0;
}
Your method is quite efficient for replacing an arbitrary character with another arbitrary character.
However, currently you replace continuous latin alphabet with continuous integer digits, so you can take advantage of the fact that ASCII representations are also contiguous:
for(char& c : str)
c += '1' - 'A';
Of course, this depends on the native character encoding to represent contiguous latin alphabet with contiguous values, such as ASCII does. It also depends on the digits being represented contiguously, but that is mandated by the standard.
Furhtermore, this method currently has no check for replaced character, and will change all encountered characters. This is not an issue with your input string, but if you intend to only replace some types of characters and leave others untouched, then you'll need to add a condition check.
Or you can try if input string only contains caps alphabet in ASCII format
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
int main()
{
std::string str = "ABCDDCBA";
for(int i=0;i<str.size();i++)
{
str[i]=str[i]-'A'+'0';
}
std::cout << str << std::endl; // displaying
return 0;
}
Presumably you mean do the replacement in one traversal? There are flashy C++ Standard Library ways of doing this, or you could even solve it with std::regex. But exploiting the overloaded [] operator on the std::string class will be hard to beat in terms of performance and is clear.
for (std::size_t i = 0; i < str.size(); ++i){
switch (str[i]){
case 'A':
str[i] = '1';
break;
case 'B':
/*etc*/
}
}
If you are transforming more than a handful of characters (I took your question literally that you only wanted to map A, B, C, and D), then consider defining a const char[] array that describes the transformation; relying on the values of particular characters is not strictly portable C++.
A funny way to do that would be to use the ASCI value of each char:
by exemple: int('A') = 65, int('B') = 66 so you just have to do a boucle with
val = int(c) - 64;
(Works only if you have maj char)
One proposal in O(n)
void MyReplaceFunction(char& c)
{
static const int delta='A'-'1';
if(c>='A' && c<='Z')
{
c-=delta;
}
}
std::for_each(str.begin(), str.end(), MyReplaceFunction);
Is there a method that checks for these cases? Or do I need to parse each letter in the string, and check if it's lower case (letter) and is a number/letter?
You can use islower(), isalnum() to check for those conditions for each character. There is no string-level function to do this, so you'll have to write your own.
Assuming that the "C" locale is acceptable (or swap in a different set of characters for criteria), use find_first_not_of()
#include <string>
bool testString(const std::string& str)
{
std::string criteria("abcdefghijklmnopqrstuvwxyz0123456789");
return (std::string::npos == str.find_first_not_of(criteria);
}
It's not very well known, but a locale actually does have functions to determine characteristics of entire strings at a time. Specifically, the ctype facet of a locale has a scan_is and a scan_not that scan for the first character that fits a specified mask (alpha, numeric, alphanumeric, lower, upper, punctuation, space, hex digit, etc.), or the first that doesn't fit it, respectively. Other than that, they work a bit like std::find_if, returning whatever you passed as the "end" to signal failure, otherwise returning a pointer to the first item in the string that doesn't fit what you asked for.
Here's a quick sample:
#include <locale>
#include <iostream>
#include <iomanip>
int main() {
std::string inputs[] = {
"alllower",
"1234",
"lower132",
"including a space"
};
// We'll use the "classic" (C) locale, but this works with any
std::locale loc(std::locale::classic());
// A mask specifying the characters to search for:
std::ctype_base::mask m = std::ctype_base::lower | std::ctype_base::digit;
for (int i=0; i<4; i++) {
char const *pos;
char const *b = &*inputs[i].begin();
char const *e = &*inputs[i].end();
std::cout << "Input: " << std::setw(20) << inputs[i] << ":\t";
// finally, call the actual function:
if ((pos=std::use_facet<std::ctype<char> >(loc).scan_not(m, b, e)) == e)
std::cout << "All characters match mask\n";
else
std::cout << "First non-matching character = \"" << *pos << "\"\n";
}
return 0;
}
I suspect most people will prefer to use std::find_if though -- using it is nearly the same, but can be generalized to many more situations quite easily. Even though this has much narrower applicability, it's not really a lot easier to user (though I suppose if you're scanning large chunks of text, it might well be at least a little faster).
You could use the tolower & strcmp to compare if the original_string and the tolowered string.And do the numbers individually per character.
(OR) Do both per character as below.
#include <algorithm>
static inline bool is_not_alphanum_lower(char c)
{
return (!isalnum(c) || !islower(c));
}
bool string_is_valid(const std::string &str)
{
return find_if(str.begin(), str.end(), is_not_alphanum_lower) == str.end();
}
I used the some info from:
Determine if a string contains only alphanumeric characters (or a space)
Just use std::all_of
bool lowerAlnum = std::all_of(str.cbegin(), str.cend(), [](const char c){
return isdigit(c) || islower(c);
});
If you don't care about locale (i.e. the input is pure 7-bit ASCII) then the condition can be optimized into
[](const char c){ return ('0' <= c && c <= '9') || ('a' <= c && c <= 'z'); }
If your strings contain ASCII-encoded text and you like to write your own functions (like I do) then you can use this:
bool is_lower_alphanumeric(const string& txt)
{
for(char c : txt)
{
if (!((c >= '0' and c <= '9') or (c >= 'a' and c <= 'z'))) return false;
}
return true;
}
IF a string may include several un-necessary elements, e.g., such as #, #, $,%.
How to find them and delete them?
I know this requires a loop iteration, but I do not know how to represent sth such as #, #, $,%.
If you can give me a code example, then I will be really appreciated.
The usual standard C++ approach would be the erase/remove idiom:
#include <string>
#include <algorithm>
#include <iostream>
struct OneOf {
std::string chars;
OneOf(const std::string& s) : chars(s) {}
bool operator()(char c) const {
return chars.find_first_of(c) != std::string::npos;
}
};
int main()
{
std::string s = "string with #, #, $, %";
s.erase(remove_if(s.begin(), s.end(), OneOf("##$%")), s.end());
std::cout << s << '\n';
}
and yes, boost offers some neat ways to write it shorter, for example using boost::erase_all_regex
#include <string>
#include <iostream>
#include <boost/algorithm/string/regex.hpp>
int main()
{
std::string s = "string with #, #, $, %";
erase_all_regex(s, boost::regex("[##$%]"));
std::cout << s << '\n';
}
If you want to get fancy, there is Boost.Regex otherwise you can use the STL replace function in combination with the strchr function..
And if you, for some reason, have to do it yourself C-style, something like this would work:
char* oldstr = ... something something dark side ...
int oldstrlen = strlen(oldstr)+1;
char* newstr = new char[oldstrlen]; // allocate memory for the new nicer string
char* p = newstr; // get a pointer to the beginning of the new string
for ( int i=0; i<oldstrlen; i++ ) // iterate over the original string
if (oldstr[i] != '#' && oldstr[i] != '#' && etc....) // check that the current character is not a bad one
*p++ = oldstr[i]; // append it to the new string
*p = 0; // dont forget the null-termination
I think for this I'd use std::remove_copy_if:
#include <string>
#include <algorithm>
#include <iostream>
struct bad_char {
bool operator()(char ch) {
return ch == '#' || ch == '#' || ch == '$' || ch == '%';
}
};
int main() {
std::string in("This#is#a$string%with#extra#stuff$to%ignore");
std::string out;
std::remove_copy_if(in.begin(), in.end(), std::back_inserter(out), bad_char());
std::cout << out << "\n";
return 0;
}
Result:
Thisisastringwithextrastufftoignore
Since the data containing these unwanted characters will normally come from a file of some sort, it's also worth considering getting rid of them as you read the data from the file instead of reading the unwanted data into a string, and then filtering it out. To do this, you could create a facet that classifies the unwanted characters as white space:
struct filter: std::ctype<char>
{
filter(): std::ctype<char>(get_table()) {}
static std::ctype_base::mask const* get_table()
{
static std::vector<std::ctype_base::mask>
rc(std::ctype<char>::table_size,std::ctype_base::mask());
rc['#'] = std::ctype_base::space;
rc['#'] = std::ctype_base::space;
rc['$'] = std::ctype_base::space;
rc['%'] = std::ctype_base::space;
return &rc[0];
}
};
To use this, you imbue the input stream with a locale using this facet, and then read normally. For the moment I'll use an istringstream, though you'd normally use something like an istream or ifstream:
int main() {
std::istringstream in("This#is#a$string%with#extra#stuff$to%ignore");
in.imbue(std::locale(std::locale(), new filter));
std::copy(std::istream_iterator<char>(in),
std::istream_iterator<char>(),
std::ostream_iterator<char>(std::cout));
return 0;
}
Is this C or C++? (You've tagged it both ways.)
In pure C, you pretty much have to loop through character by character and delete the unwanted ones. For example:
char *buf;
int len = strlen(buf);
int i, j;
for (i = 0; i < len; i++)
{
if (buf[i] == '#' || buf[i] == '#' || buf[i] == '$' /* etc */)
{
for (j = i; j < len; j++)
{
buf[j] = buf[j+1];
}
i --;
}
}
This isn't very efficient - it checks each character in turn and shuffles them all up if there's one you don't want. You have to decrement the index afterwards to make sure you check the new next character.
General algorithm:
Build a string that contains the characters you want purged: "##$%"
Iterate character by character over the subject string.
Search if each character is found in the purge set.
If a character matches, discard it.
If a character doesn't match, append it to a result string.
Depending on the string library you are using, there are functions/methods that implement one or more of the above steps, such as strchr() or find() to determine if a character is in a string.
use the characterizer operator, ie a would be 'a'. you haven't said whether your using C++ strings(in which case you can use the find and replace methods) or C strings in which case you'd use something like this(this is by no means the best way, but its a simple way):
void RemoveChar(char* szString, char c)
{
while(*szString != '\0')
{
if(*szString == c)
memcpy(szString,szString+1,strlen(szString+1)+1);
szString++;
}
}
You can use a loop and call find_last_of (http://www.cplusplus.com/reference/string/string/find_last_of/) repeatedly to find the last character that you want to replace, replace it with blank, and then continue working backwards in the string.
Something like this would do :
bool is_bad(char c)
{
if( c == '#' || c == '#' || c == '$' || c == '%' )
return true;
else
return false;
}
int main(int argc, char **argv)
{
string str = "a #test ##string";
str.erase(std::remove_if(str.begin(), str.end(), is_bad), str.end() );
}
If your compiler supports lambdas (or if you can use boost), it can be made even shorter. Example using boost::lambda :
string str = "a #test ##string";
str.erase(std::remove_if(str.begin(), str.end(), (_1 == '#' || _1 == '#' || _1 == '$' || _1 == '%')), str.end() );
(yay two lines!)
A character is represented in C/C++ by single quotes, e.g. '#', '#', etc. (except for a few that need to be escaped).
To search for a character in a string, use strchr(). Here is a link to a sample code:
http://www.cplusplus.com/reference/clibrary/cstring/strchr/