I try to call erase() function to remove whitespaces in string for function that converts string to integer. The same code works in main() but inside function it doesn't.How can I fix it?
int convert(const string &line)
{
for (int i=0;i<line.length();i++)
{
char wh=' ';
if(line.find(wh))
line.erase(find(line.begin(),line.end(),' '));
//cout<<line[i];
}
if(line.length()==0)
return 0;
int a=line[line.length()-1]-'0';
int b=convert(line.substr(0,line.length()-1))*10;
return a+b;
}
try to pass line by value instead of const reference. The const ref can't be changed
int convert(std::string line)
Try removing const from convert().
Anything declared with const can't be modified.
Related
So I've been trying to sort a string based on the frequency of its characters. However the online judge I've been using shows me the error
Line 17: invalid use of non-static member function 'bool olution::helper(char, char)'
Why is the call to my function wrong? I have used the sort() function before, but not to strings. Is my helper() function incorrect?
class Solution {
public:
unordered_map<char,int> freq;
bool helper(char c1,char c2){
if(freq[c1]>freq[c2]) return false;
else return true;
}
string frequencySort(string s) {
for(char c:s)
{
freq[c]++;
}
sort(s.begin(),s.end(),helper);
return s;
}
};
Use a lambda to capture this:
sort(s.begin(),s.end(),[this](auto a, auto b) -> bool { return helper(a,b); });
Why is the call to my function wrong? I have used the sort() function
before, but not to strings. Is my 'helper()' function incorrect?
Because helper is member function of Solution. When you do this
sort(s.begin(),s.end(),helper);
you are basically doing this
sort(s.begin(),s.end(),this->helper);
The 3rd parameter to sort needs to be a standalone function, a predicate, a functor or a lambda. It cannnot be a non-static member of a class
This code, cleaned up, works. Note the statics
class Solution {
public:
// using thread_local so that each thread
// has its own global variable.
static thread_local std::unordered_map<char, int> freq;
static bool helper(char c1, char c2) {
return (freq[c1]<freq[c2]);
}
std::string frequencySort(std::string s)
{
freq.clear();
for (char c : s)
++freq[c];
std::sort(s.begin(), s.end(), helper);
return s;
}
};
// definition
std::unordered_map<char, int> Solution::freq;
Member functions have a hidden parameter that becomes this. You need either expose the state more widely, or write a capturing lambda
Also a Compare predicate must return false if you are comparing a value to itself, yours does not.
class Solution {
public:
string frequencySort(string s) {
unordered_map<char,int> freq;
for(char c:s)
{
freq[c]++;
}
sort(s.begin(),s.end(),[&freq](char lhs, char rhs){ return freq[lhs] < freq[rhs]; });
return s;
}
};
I have C++ class similar to this:
class A{
std::string str;
public:
A(std::string &str) : str(str){}
int cmpAt(const std::string &key) const{
return str.cmp(key);
}
int cmpAt(const char *key) const{
return str.cmp(key);
}
}
Both cmpAt methods look the same. Is there some way NOT to duplicate the method? Perhaps with template ?
You should just write a function template:
template <typename K>
int cmpAt(K const& key) const {
return str.compare(key);
}
That way, if you call cmpAt with a const char*, you can avoid the overhead of having to construct an extra std::string.
EDIT Never mind, you're out of luck:
int compare(const charT* s) const;
5 Returns: compare(basic_string(s)).
So just delete the const char* overload - it provides you nothing of extra value over the std::string const& overload. You would have to write your own compare function to avoid the extra string constructor, at which point it's not code duplication anymore.
I would use boost::string_ref or your favourite other implementation of it
class A{
std::string str;
public:
A(std::string &str) : str(str){}
int cmpAt(const boost::string_ref &key) const{
return key.compare(str) * -1;
}
}
This will not create temporary strings and you can pass string literals and std::string.
When int cmpAt(const std::string &key) is called with const char*, key will be constructed with const char*. so you can simply delete cmpAt(const char *key).
As others have correctly pointed out, in your specific case, there's no need for a non-const comparison function.
However, in the general case, you can do the following:
RetType someMethod(params...) const {
return LongAndComplexComputation(params, ...);
}
// Return type deduction is C++14.
// If you can't use C++14, only C++11, the return type should be:
// const std::remove_reference<decltype(*this)>::type *
auto cthis() const {
return this;
}
RetType someMethod(params...) {
return cthis()->someMethod(params, ...)
}
If necessary, you will have to cast away const-qualification from the return type (e.g. when you are returning a pointer inside *this), using const_cast.
I am trying to implement the functions below, but the output for foo() is a bunch of nonsense. I tried to run the debugger and didn't see any problems inside the append function. But the total variable in foo() isn't properly assigned the value "abcdef". Any ideas why?
int main()
{
cout<<"foo is"<<endl;
foo();
return 0;
}
const char* append(const char* s1, const char* s2) {
string s(s1);
s += s2;
return s.c_str();
}
void foo() {
const char* total = append("abc", "def");
cout<<total;
}
Because in append(), you returned s.c_str(); then, s is destructed, which means that the pointer returned is invalidated immediately.
Let append() return std::string to solve this issue.
std::string append(const char* s1, const char* s2) {
return std::string(s1).append(s2);
}
void foo() {
std::string total = append("abc", "def");
cout << total;
}
Undefined Behaviour. c_str is only valid for the lifetime of s (and only then if s is not modified in any way). Once append has returned, s is out of scope. Boom!
One fix is to have append return a std::string.
const char* append(const char* s1, const char* s2) {
string s(s1);
s += s2;
return s.c_str();
}
The variable s is local to the function. It is destroyed when the function returns. That means that the value that you return, s.c_str(), points to memory that has been deallocated. De-referencing that memory results in undefined behaviour.
The rule with c_str() is, loosely put, that the value it returns is guaranteed to be valid until either the string object is modified or destroyed.
Simply put, you should stop using C strings unless you need to use them for interop. Your function should be:
string append(const string& s1, const string& s2)
{
return s1 + s2;
}
You are returning a pointer from append() that is not valid when the function returns.
string s(s1);
defines a object in append(). It is destroyed when you return from the function. Hence, the returned value of s.c_str() is not valid in foo.
You can change your code to be:
string append(const char* s1, const char* s2) {
string s(s1);
s += s2;
return s;
}
void foo() {
string total = append("abc", "def");
cout<<total;
}
That should work.
return s.c_str(); : you return pointer obtained from temporary variable s.
You may fix your problem in two ways -
Return std::string by value from append.
Pass to append pointer to fill it with data -
void append(const char* s1, const char* s2, char* out) {
string s(s1);
s += s2;
strncpy(out, s.c_str(), s.size()+1);
}
void foo() {
char total[7] = {0}; //should be enough to carry appended string + '\0'
append("abc", "def", total);
cout<<total;
}
I try to make a function that can change the content of a specified char array
void change_array(char *target)
{
target="hi";
}
int main()
{
char *a[2];
change_array(a[1]);
cout<<*(a[1]);
}
But then the content of a[1] stays at 0x0(void)
First, your function has a copy of the pointer passed to it, so there is no effect seen on the caller side. If you want to modify the function argument, pass a reference:
void change_array(char*& target) { ... }
// ^
Second, you cannot/should not bind a non-const pointer to a string literal. Use const char* instead.
void change_array(const char*& target) { ... }
// ^^^^^ ^
int main()
{
const char* a[2];
change_array(a[1]);
cout<<*(a[1]);
}
When you pass an argument to a function, it's normally passed by value, meaning its value is copied. If you want to change it you have to pass it by reference. The same goes for pointers, if you want to change a pointer then you need to pass it by reference as well:
void change_array(const char*& target) { ... }
You need to pass it as a reference:
void change_array(char*&target)
{
target="hi";
}
Otherwise, you will just change the local copy of target, which won't make any difference to the value outside of the function.
Try this design instead:
std::string get_string()
{
return "hi";
}
int main()
{
std::string a[2];
a[1] = get_string();
std::cout<< a[1];
}
Salient points:
return by value
use std::string
I am stuck in the following pointer problem:
Say you have a function:
void Function (unsigned char *ubPointer)
{
ubPointer++;
}
int main (void)
{
unsigned char *PointerX;
Function( PointerX );
}
What I want is that the ++ is reflected in PointerX, without declaring it as a global variable.
Thank you very much.
In C++, pass your pointer by reference (and don't forget to specify a return type for your function):
void Function (unsigned char*& ubPointer)
// ^
{
ubPointer++;
}
This won't require any further change in the calling code. When returning from the function, the side-effects on ubPointer will be visible to the caller.
In C, you can achieve the equivalent result by passing a pointer to your pointer:
void Function (unsigned char** ubPointer)
// ^
{
(*ubPointer)++;
// ^^^^^^^^^^^^
}
This will require you to change the way you are calling your function:
int main()
{
unsigned char* p;
Function(&p);
// ^
}
Or, if you want to do it C-style
void Function (unsigned char **ubPointer)
{
(*ubPointer)++;
}
because
Function (unsigned char **ubPointer)
{
ubPointer++;
}
would be increasing the address pointed to.
void Function (unsigned char *ubPointer)
{
(*ubPointer)++;
}
int main (void)
{
unsigned char *PointerX;
Function( PointerX );
}
This is the correction