I'm trying to figure out how to use this function. I found it on the web and apparently it checks if you have a space in your string. So it's not working out for me. I've figured out that I'm not even getting into the if statement that I need to.
for (i=0;i < marks.length();i++)
{
if (isdigit(marks[i]))
{
floatMARK = 1;
}
else
{
charMARK = 1;
}
}
if (floatMARK == 1)
{
printf("were in.");
for (i=0;i < marks.length();i++)
{
if (isspace(marks[i]))
{
multiMARK = 1;
printf("WE HAVE A SPACE!!");
}
}
}
Anyone know what I'm doing wrong? If you need me to clarify anything, let me know.
All that is very unnecessary to just test if a string has a space in it. This is all you need:
#include <ctype.h>
bool hasspace = std::find_if(str.begin(), str.end(), ::isspace) != str.end();
:: is the scope resolution operator specifying that isspace is a global function, not the similarly-named std::isspace, and find_if is a function inside std::. If you use using namespace std; then you don't need std:: but you do still need the plain ::.
The find_if function takes an iterator to the beginning of the string, an iterator to the end of the string, and a function that takes an argument and returns some value convertible to a bool. find_if iterates from the first iterator to the second iterator, passing each value of the current item to the function you gave it, and if the function returns true, find_if returns the iterator that caused the function to return true. If find_if goes through to the end and the function never returns true, then it returns an iterator to the end of the range, which in this case is str.end().
That means that if find_if returns str.end(), it got to the end of the string without isspace returning true, which means there was no space characters in the string. Therefore, you can test the result of find_if against str.end(); If they are unequal (!=), that means there was a space in the string, and hasspace is true. Else, hasspace is false.
here is another way, if the above version seems strange, or it's above your knowledge
if(marks[i] == ' ') {
cout<<"Space found!";
}
Related
using std::filesystem, how can I tell that the directory_entry is the end of a directory_iterator?
here's an example of what I'm trying to do:
auto it = fs::directory_iterator(path);
for (const auto &i : it) {
if (i == it.back()) { // this works with `vector`s but not with `directory_iterator`
doSomethingWith(i); // call this function only on the last entry.
}
}
From docs -
If the directory_iterator reports an error or is advanced past the last directory entry, it becomes equal to the default-constructed iterator, also known as the end iterator. Two end iterators are always equal, dereferencing or incrementing the end iterator is undefined behavior.
However, the issue is incrementing directory_iterator invalidates all previous values.
So, one possible solution is to use the post-increment operation to find the last directory_entry.
auto it = fs::directory_iterator(path);
for (auto i = fs::begin(it); fs::begin(i) != fs::end(it); ) {
auto entry = *(i++);
if (fs::begin(i) == fs::end(it)) { // sugercoat of `i == fs::directory_iterator{}`
doSomethingWith(entry); // this is the last directory entry
} else {
doSomethingElse(entry); // non-last entry
}
}
You can use std::filesystem::end. See the docs here:
https://en.cppreference.com/w/cpp/filesystem/directory_iterator/begin
But in your example, you shouldn’t need to explicitly check as the loop will end correctly on its own.
A default constructed directory_iterator is the end iterator. See entry one in the constructor list: https://en.cppreference.com/w/cpp/filesystem/directory_iterator/directory_iterator
I'm trying to convert .fsp files to strings but new .fsp file is very abnormal. It contains some undesirable characters that I want to delete from string. How can I make it?
I have tried to search char in string and delete them but I dont know how to make it.
The string looks like this:
string s;
s = 144˙037˙412˙864;
and I need to make it just like that
s = 144037412864;
So I except result like this:
string s = 144037412864;
Thank you for help.
We can use the remove-erase idiom to remove unnecessary characters from the string! There's a function in <algorithm> called remove_if. What remove_if does is it removes elements that match some predicate. remove_if returns a iterator pointing to the new end of the container after all elements have been removed. I'll show you how to write a function that does the job!
#include <algorithm>
#include <string>
void erase_ticks(std::string& s) {
// Returns true for characters that should be removed
auto condition = [](char c) { return c == '`'; };
// Removes characters that match the condition,
// and returns the new endpoint of the string
auto new_end = std::remove_if(s.begin(), s.end(), condition);
// Erases characters from the new endpoint to the current endpoint
s.erase(new_end, s.end());
}
We can use this in main, and it works just as expected!
#include <iostream>
int main() {
std::string s("123`456`789");
std::cout << s << '\n'; // prints 123`456`789
erase_ticks(s);
std::cout << s << '\n'; // prints 123456789
}
This problem has two parts, first we need to identify any characters in the string which we don't want. From your use case it seems that anything that is not numeric needs to go. This is simple enough as the standard library defines a function std::isdigit (simply add the following inclusion "#include <locale>") which takes a character and returns a bool which indicates whether or not the character is numeric.
Second we need a way to quickly and cleanly remove all occurrences of these from the string. Thus we can use the 'Erase Remove' idiom to iterate through the string and do what we want.
string s = "123'4'5";
s.erase(std::remove_if(s.begin(), s.end(), [](char x)->bool {return !std::isdigit(x);}), s.end());
In the snippit above we're calling erase on the string which takes two iterators, the first refers to where we want to begin to delete from and the second tells the call where we want to delete to. The magic in this trick is actually all in the call to remove_if (include "#include <algorithm>" for it). remove_if actually works by shifting the elements (or characters) of string forward to the end of the string.
So "123'4'5'" becomes "12345'''", then it returns an iterator to where it shifted these characters to which is then passed to erase to tell it remove the characters starting here. In the end we're left with "12345" as expected.
Edit: Forgot to mention, remove_if also takes a predicate here I'm using a lambda which takes a character and returns a bool.
I am reading a Data Structures and Algorithms book and there is a case study on recursion, specifically a parser that uses recursive descent. I'm a bit new to C++ (I'm learning it on the side and as I go with Stanley B. Lippman's C++ Primer 5th edition).
I'm a bit stuck on code and am trying to make sense of it. Is what I've written at the bottom (bulleted points) accurate descriptions of what is happening in the functions? I would post the header, but it's a bit too long, you can probably find it online if you search "Data Structures
and Algorithms in C++ by Adam Drozdek - interpreter.h".
double Statement::findValue(char* id) {
IdNode tmp(id);
list<IdNode>::iterator i = find(idList.begin(), idList.end(), tmp);
if (i != idList.end())
return i->value;
else
issueError("Unknown variable");
return 0;
}
void Statement::processNode(char* id, double e) {
IdNode tmp(id, e);
list<IdNode>::iterator i = find(idList.begin(), idList.end(), tmp);
if (i != idList.end())
i->value = e;
else
idList.push_front(tmp);
}
findValue()
Looks for a value for a certain variable
Uses an iterator i so that it can traverse the list
Looks for tmp using find()
If i doesn't equal the value at the end of the list, return it
Other wise, the variable cannot be found
processNode()
Processes nodes by using an iterator i
Looks for a variable that matches tmp
Finds the variable and sets it's value to the value of e
Other wise, store variable on to idList to be evaluated later
Define a function that accepts a pointer to char (likely it's an array) and returns a double:
double Statement::findValue(char* id) {
Create a temporary (will die at 'return') of type IdNode based on that pointer:
IdNode tmp(id);
Use a (std:: I guess, but it could be any function with the same features) function that looks for tmp inside the container idList. The result is an interator i, which must be of the same type of that one used by the container:
list<IdNode>::iterator i = find(idList.begin(), idList.end(), tmp);
Check if something is found. idList.end() means "one past end", beyond the last item in the container:
if (i != idList.end())
Return the member value (which is part of IdNode) for the item found. If value is not a double then convert to it.
return i->value;
Otherwise, call issueError function.
else
issueError("Unknown variable");
Exit function, returning a double with value = 0:
return 0;
}
Same, but: this function accepts two parameters and returns nothing:
void Statement::processNode(char* id, double e) {
Same, but: IdNode constructor uses two parameters:
IdNode tmp(id, e);
Same
list<IdNode>::iterator i = find(idList.begin(), idList.end(), tmp);
Same
if (i != idList.end())
Now, modify the item found. Just update value member:
i->value = e;
Otherwise, add tmp, insert it at the very begining of idList container.
else
idList.push_front(tmp);
Exit function:
}
Your understanding is mostly right. I'll describe it statement by statement
in somewhat more precise terms.
double Statement::findValue(char* id) {
IdNode tmp(id);
This constructs a variable named tmp using the string passed in. (Well, I presume id is a string. In C, it's common to pass a pointer to the beginning of a zero-terminated array of characters when you want to pass a string. In C++, the same thing was common, but it's becoming less common now that we have better string and range types in the standard library. But not every char * is a string. It might just be a pointer to a single character. Here though, the context strong suggests it's a string.)
list<IdNode>::iterator i = find(idList.begin(), idList.end(), tmp);
Uses the std::find algorithm to search the range of elements from the beginning of the idList to the end for an element that equals tmp.
Note the idList.end() is an iterator that indicates the actual end of the list rather than the last item in the list. You can think of it as one element beyond the last element in the list. Iterator ranges (and array indices) in C and C++ are typically inclusive of the first value and exclusive of the second. So find will start with the first element and continue up to (but not through) the end of the list.
It's not shown here, but I assume there's an overload for operator==(const idNode &, const idNode &) that returns true if the names of the two idNodes match, regardless of whether the value fields match.
If there's no match in the range, then std::find is going to return the end iterator. If there is a match, it's going to return an iterator that references the matching element. So ...
if (i != idList.end())
return i->value;
else
issueError("Unknown variable");
This returns the value field of the match (if there is one) or it calls issueError if there isn't.
return 0;
}
In the latter case, assuming issueError returns and doesn't terminate the program or throw an exception, the function will return a value of 0 (which, because the return type is a double, will be implicitly converted to 0.0).
processNode is nearly identical except that it sets the value in the found node rather than returning it.
I can't get my head around this. I'm trying to remove all occurrences of a certain character within a string until the string becomes empty. I know we can remove all character occurrences from an std::string by using the combination of string::erase and std::remove like so:
s.erase(remove(s.begin(), s.end(), '.'), s.end());
where the '.' is the actual character to be removed. It even works if I try to remove certain characters. Now let's consider the following string: 'abababababababa'. What I'm trying to achieve is to reduce this string to ashes be removing all 'a's for startes, which will leave me with a couple of 'b's. Then remove all those 'b's which will leave me with an empty string. Of course this is just a part of my task but I could narrow it down for this problem. Here's my naive approach based on the upper combination of functions:
string s = "abababababababa";
while (!s.empty()) {
...
s.erase(remove(s.begin(), s.end(), s[0]), s.end());
...
}
Of course it doesn't work, I just can't seem to find out why. By debugging the application I can see how the "s" string is being modified. While the s.erase... works perfectly if I set a character constant for remove's third parameter it fails if I try to use char variables. Here's what the s string looks like after each iteration:
Removing[a] from [abababababababa] Result: baaaaaaa
Removing[b] from [baaaaaaa] Result: a
Removing[a] from [a] Result: -
While I expected 2 operations until a string should become empty - which works, if I hardcode the letters by hand and use s.erase twice - it actually takes 3 iteration. The most frustrating part however is the fact that, while I'm removing 'a' in the first iteration only the first 'a' is removed and all other 'b'.
Why is this happening? Is it the cause of how erase / remove works internally?
You have undefined behavior.
You get the results you get because std::remove takes the value to remove by reference, once s[0] has been removed, what happens to the reference to it then?
The simple solution is to create a temporary variable, assign e.g. s[0] to it, and pass the variable instead.
The behavior of function remove() template is equivalent to:
template <class ForwardIterator, class T>
ForwardIterator remove (ForwardIterator first, ForwardIterator last, const T& val)
{
ForwardIterator result = first;
while (first!=last) {
if (!(*first == val)) {
*result = move(*first);
++result;
}
++first;
}
return result;
}
As you see, the function will move the element different with val to the front of the range.
so in your case "ababababab",
if you call remove() like you did, the original s[0] is 'a', but it will be instead by 'b' during the remove(), the remaining code will remove the 'b', so the result is not right.
Like Joachim say, assign s[0] to a temporary variable.
the code is reference from http://www.cplusplus.com/reference/algorithm/remove/?kw=remove
I'm having a beginner problem:
bool _isPalindrome(const string& str)
{
return _isPalindrome(str.begin(), str.end()); // won't compile
}
bool _isPalindrome(string::iterator begin, string::iterator end)
{
return begin == end || *begin == *end && _isPalindrome(++begin, --end);
}
What am I doing wrong here? Why doesn't str.begin() get type checked to be a string::iterator?
Update: Better version:
bool BrittlePalindrome::_isPalindrome(string::const_iterator begin, string::const_iterator end)
{
return begin >= end || *begin == *(end - 1) && _isPalindrome(++begin, --end);
}
Assuming that you have a declaration of the second function before the first function, the main issue is that you are passing the strings by const reference.
This means that the only overloads of begin() and end() that you have access to are the const versions which return std::string::const_iterator and not std::string::iterator.
The convention for iterators is that the end iterator points one beyond the end of a range and is not dereferencable - certainly if you pass str.end() as the end parameter. This means that *begin == *end is not valid, you need to decrement end once first. You are also going to have an issue with ranges with odd numbers of elements. By doing ++begin and --end with no further checking your iterators may cross over in the recursion rather than triggering the begin == end condition.
Also note that for maximum portability, global identifiers shouldn't start with an underscore.
str.begin() is non-const, while the argument str is const.
You can either change the iterator-accepting method to accept const_iterators, or you can change the string-accepting method to accept a non-const string.
Or you could cast away str's const-ness, but that would be a patent Bad Idea TM.
(I would also parenthesize your return statement on the iterator-accepting method to make your intent more clear, but that's neither here nor there.)
As previously mentioned your iterators need to be constant iterators, but there's something else wrong with your algorithm. It works fine if you have a string of odd length, but do you see what happens when your string is even length? Consider the palindrome:
aa
Your algorithm will pass in an iterator pointing to the front and to the end. All's good, then it will go to the next level, and all will still be good, but it won't end. Because your first condition will never be true. You need to check not only if begin==end but if begin+1==end or begin==end-1 if you prefer. Otherwise you're iterators are going to be upset.
What error are you getting?
Have you tried this?
bool _isPalindrome(string::const_iterator begin, string::const_iterator end)
replace iterator by const_iterator
swap function definitions
decrement end
Code:
bool isPalindrome(string::const_iterator begin, string::const_iterator end)
{
return (begin == end || begin == --end ||
*begin == *end && isPalindrome(++begin, end));
}
bool isPalindrome(const string& str)
{
return isPalindrome(str.begin(), str.end());
}
You haven't declared the second function before calling it in the first function. The compiler can't find it and thus tries to convert str.begin() (string::iterator) into a const string &. You can move the first function behind the second function.