c++ accessing string index inside this pointer - c++

class X
{
private:
string DATA;
.
.
.
const string read_entry( const string & s ) { return this->(DATA[1]); } //Error
}
What's wrong with this? I'm trying to access the index of the DATA string, but I get an error when I do this->DATA[1]

There are two issues in the code snippet:
Illegal () around DATA[1]. Change return this->(DATA[1]); to return this->DATA[1];.
Wrong return type: the type of DATA[1] is char, not string.
Also, add ; after class definition.

The problem appears to be the return type of the function. The stated type is const string but indexing into a string returns a char. Try the following instead
char read_entry( const string & s ) { return this->DATA[1]; }

A few things:
the return type of your function (const string) does not match the type you are returning (char). Without knowing the purpose of this function I don't know exactly what fix to make to this.
you're passing in a string& to your function, but it isn't used in the function body. What is the purpose of that?
you don't need the explicit reference to 'this', 'return DATA[1]' is sufficient.
unless you're very certain about the length of DATA, you should use DATA.at(1) rather than DATA[1], because .at() does a range check for you. Without this you might be risking memory problems.
in future, please explain what the code is supposed to do, so we can understand why it looks the way it does.

Related

How can I send a struct of arrays into a function when using the String object?

I'm learning to code c++ and I've come to this problem:
I have this struct:
struct storeData
{
string name;
string username;
string fav_food;
string fav_color;
}data[30];
And I need to check if two usernames are equal so I made this statement:
for(i=0;i<c;i++){
if(data[c].username.compare(data[i].username)==0){
cout<<"Username already taken"<<endl;
}
}
And it works well, the problem that I have is that I'm required to make a function let's call it: isTaken that returns the error message, so I can use it whenever I need to for example delete a username so I don't have to copy/paste the code again.
So I began looking for an answer for that, many forums present a way to send the whole struct like this:
void isTaken(struct storeData *data)
which I understand but because I'm using string is not working, so I guess it's because string is an object? I'm using the library <string> I'm sorry if I'm not being that clear at the moment, I'm looking for a way to use isTaken(data[c].user); but I don't know how to declare the function, I think is also because string is not the same as C string but I'm not really sure I've been looking for a solution and could not find it.
I tried: void isTaken(struct storeData *data) but I got an error saying that I can't convert std::string to basic_string which makes sense if I'm correct about string I tried converting string into c string but could not get anywhere. I'm open to suggestions/corrections because I want to improve my code, also I could not find the answer here, so If someone's got a link to a problem like this please let me know.
Thank you so much for you time, have a good day.
Do you mean an array of structs instead of a struct of arrays?
In the example you are giving I see only an array of structs each of which has multiple string objects in it. You see, a string is a class coming from std and I wouldn't call it an array. If you want to know how to pass an array to a function, you should read about it (I'm sure you can find such a question in SO). If you want to have an array within your struct, then the struct will take care of the memory of the array, but you should definitely read about constructors.
You got an error because you are passing an string argument to a function which requires struct pointer
void isTaken(struct storeData *data);
...
isTaken(data[c].user);
but what you actually need is to have a function which takes an array of your users, its size and username you want to check
bool IsUsernameTaken(struct storeData data[], int dataSize, const string &username){
for(int i = 0; i<dataSize; i++){
if(username == data[i].username)
return true;
}
return false;
}
A C string looks like this
data
A C++ string usually looks like this
size
capacity
ptr
|
v
data
or if using short string optimization and the string is short enough
size
data
data
all are zero terminated.
Making a shallow copy a C string only cost the copy of the pointer to it. Where a copy of a might cost just copying the 3 members and possible an allocation of data, which is not ideal, therefor most C++ functions use a reference to a string making the cost equivalent to the C string.
All code is untested.
bool Find(const std::string& target);
Making a deep copy of a C string would also cost an allocation.
In C++ you have many options to do a search, for your struct it could look like this. In case your member variables are private you must use an access function
auto found = std::find(std::begin(data), std::begin(data)+c, [&target](const storeData& auser) { return auser.GetName() == target });
return (found != std::begin(data)+c);
The first two parameters are the range that is search, not including the 2nd. A lambda is used to check the name, a free function with the right declaration would also do.
std::string& GetName() { return name; }
The higher C++ protection schemes would advice adding 2 consts to that in case you don't need to change name.
const std::string& GetName() const { return name; }
Meaning the returned string cant be changed and the 2nd says it wont change anything in your class. This const version would be required as I used a const storeData& auser in the lambda to satisfy the constness of the struct.

Pass char array by reference and return modified

I have function definition lke below
void ConvertString(std::string &str)
{
size_t pos = 0;
while ((pos = str.find("&", pos)) != std::string::npos) {
str.replace(pos, 1, "and");
pos += 3;
}
}
Purpose of this function is to find & and replace it with and. function execution in fine. I written this for all generalised string at one instance I am calling this in following way
char mystr[80] = "ThisIsSample&String";
ConvertString((std::string)mystr);
printf(mystr);
In above call I am expecting console should be printed with new modified string with "and".
But some of string modification is not working , any error in function?
This code:
char mystr[80] = "ThisIsSample&String";
ConvertString((std::string)mystr);
printf(mystr);
… creates a temporary string object and passes that as argument.
Since the formal argument type is by reference to non-const, this should not compile, but Visual C++ supports it as a language extension (for class types only, IIRC).
Instead do like
string s = "Blah & blah";
ConvertString( s );
cout << s << endl;
By the way, C style casts are in general an invitation to bugs, because the basic nature of such a cast can change very silently from e.g. const_cast to reinterpret_cast when the code is maintained.
It's safe enough in the hands of an experienced programmer, like a power tool such as a chain saw can be safe in the hands of an experienced woodsman, but it's not a thing that a novice should use just to save a little work.
It's because you create a temporary std::string object (whose initial content is the content of the array mystr), and pass that temporary object by reference to the function. This temporary object is then destructed when the call id done.
Did you read some documentation of std::string and of printf?
You need
std::string mystr = "ThisIsSample&String";
ConvertString(mystr);
printf(mystr.c_str());
You obviously want to pass by reference a string variable (technically an l-value) to your ConvertString
I believe your problem is that you cast char array to string.
ConvertString((std::string)mystr);
this line creates a new variable of type std::string and passes it by reference. What you want is to convert it this way:
std::string convertedStr = (std::string)mystr;
ConvertString(convertedStr);
printf(convertedStr.c_str());
I am not very well aware of C++ pointer and reference syntax, but it's similar to this
what your are doing is not correct! you cannot should not convert a char* to a std::string with a cstyle-cast. what you should do is more like:
std::string mystr( "ThisIsSample&String" );
ConvertString(mystr);
edit:
thx for -reputation... this code isn't even compiling...
http://ideone.com/bCsmgf

How can I return a string value from a function in C++

#include <iostream>
#include <string>
using namespace std;
std::string dispCard(int card)
{
string textCard = "help";
//cout << textCard;
system("pause");
return textCard;
}
int main()
{
// Using this area to test functions for now
cout << dispCard(14);
return 0;
}
Uncommenting the cout line actually does display the value. But I cannot return the value in the string.
Honestly, I have no idea why this isn't working. I initially just wanted to use "char" but that doesn't work for some reason.
Visual Studio didn't like:
char test;
test = "help";
It underlined the "=".
For now, I just want to return a string value from a function. There's more that I need it to do, but this is the main issue right now.
Uncommenting the cout line actually does display the string. But not returning the string.
Your program both prints and returns the string, printing it again in main. The only problems I can see with your program are:
You are using system("pause") for no reason.
You are not consistent with the use of either the std:: prefix or importing the namespace. On this regard I highly suggest the std:: prefix.
You are not using the function argument.
I initially just wanted to use "char" but that doesn't work for some reason.
Well, char, as the name suggests, can only store 1 characters. In:
char test = "help";
you are trying to assign 5 characters (4 + \0) to an objects who's size can only store 1. That's the reason why your compiler complained.
I think you need to pass an int to your function and get it back in string form. To do this conversion you need something like this:
std::ostringstream stm;
stm << yourIntValue;
std::string s(stm.str());
or this:
char bf[100];
sprintf(bf, "%d", yourIntValue);
std::string s(bf);
If you put this snippet in a function then you can also accept an int parameter, convert it to a std::string and return the std::string as others have shown.
What you need to do is to declare return type of function as std::string and then return either a string object, something that can implicitly be converted to string object or something that explicitly constructs string object.
Example:
std::string foo(){
return "idkfa"; //return C-style string -> implicitly convertible to string
return {"idkfa"}; // direct initialization of returning std::string
return std::string("idkfa"); //return explicitly constructed std::string object
}
Also note that C-style strings are of type char* (C-style strings are basically an array of chars, with last element being \0, that is 0).
Your code works perfectly fine, though the the system("pause") is totally redundant and pointless and should be removed. It may in fact be confusing you.

C++ Need Help Overloading += for a MyString Class

I'm working on writing my own string class and am having trouble with overloading the += operator for a MyString being +='d to a char. I figured this would work but with no luck. Here's the implementation I tried. Any assistance on getting it to work correctly will be much appreciated.
MyString& MyString::operator +=(char c)
{
char derp[1] = {c};
strcat(value, derp);
return *this;
}
This is not going to work for several reasons:
derp is not a null-terminated array, which it has to be if you pass it as a parameter to strcat
There is no check that the buffer that value represents can actually hold more data; neither is there a facility to make sure that the buffer is always null-terminated (which again it needs to be because you are passing it to strcat)
Even if you correct the above, your string class will never be able to include the character \0 as part of a string value because that will be mistaken for a null terminator; in technical terms, your string class would not be "binary safe"; to fix this you need to drop strcat and similar functions entirely and switch to memcpy and friends
Apart from the above, overloading operator += like this allows for code such as
MyString str("foo");
foo += 80; // this compiles, but should it?
Finally, the str*** family of functions is going to get needlessly slower as your strings are getting larger (because they have to scan the string from the beginning each time in order to determine where it ends). Keeping your own length variable and switching to mem*** is going to fix this issue as well.
The use of strcat is incorrect as it requires a null terminated source string and is being provided with a buffer with no null terminator.
value will only be capable of holding a finite number of characters, and there is no attempt to increase the size of value.
Assuming value is large enough and you retain the length of the string inside your instance, I'd say:
value[size] = c;
value[size+1] = '\0';

c++ strtok in function changes original string value as parameter

when I use strtok to tokenize a c++ string, it happens a confusing problem, see the simple code below:
void a(string s){
strtok((char*)s.c_str(), " ");
}
int main(){
string s;
s = "world hello";
a(s);
cout<<s<<endl;
return 0;
}
the program outputs "world".
Shouldn't it output "world hello"? Because I pass the string as a value parameter to function a, the strtok shouldn't modify the original s...
Can anyone explain this trick.
thank you.
The problem is (char*)s.c_str(), you are casting the constness away and modified the string contents in a way that you are not supposed to. While the original s should not be modified, I pressume you may have been hit by a smart optimization that expects you to play by the rules. For instance, a COW implementation of string would happen to show that behavior.
c_str() returns a const pointer, which is a promise to the compiler that the thing being pointed at won't be modified. And then you're calling strtok which modifies it.
When you lie to the compiler, you will be punished.
That's the way strtok() works. It use the first parameter as a buffer. By casting it to a char*, you allow it to modify the string. strtok() does not known about the original std::string. It also store the string pointer in a static variable, that's why you have to call it with a null pointer the next times to continue to parse the same string.
By the way, in c++, you should use std::istringstream instead. It does not use an internal static variable, which is not thread-safe. And you can extract the parameters directly into int, double, etc like we do with cin. std::ostringstring replace sprintf().