Method get a string - c++

I am trying to make a get method in a class medicine to get the description.
As I know of that in C++, there is no data type "String" like in Java, therefore I need to make an array of char to save the description. I couldn't find a way to make a method with return type "array of chars", I use a pointer like the following.
class Medicine {
public:
char description[100] = "testing";
char *getDescription() {
char *p_description;
char *p_subDescription = (char*)malloc(100 * sizeof(char));
strcpy(p_subDescription, description);
p_description = p_subDescription;
free(p_subDescription);
return p_description;
}
};
I have a question: is there any other way I can do to make the code shorter? I feel like this is too much work just for a method to get a string.
Thank,

If you want this to be static (class-specific), the easiest way I can think of is a static, public property:
class Medicine {
public:
static const std::string description;
};
const std::string Medicine::description = "testing";

You have to decided on your flavour of C++. If you want "C with classes", C++ very close to C, then you should be passing strings about as char *s to memory allocated with malloc. Your code is nearly correct (however you free memory then return it), but most people write a little function called strdup (in fact it's often provided, which means ironically it's best to call it mystrdup() to avoid collisions)
char *mystrdup(char *str)
{
char *answer = malloc(strlen(st) +1);
if(answer)
strcpy(answer, str);
return answer;
}
If you are writing a more modern version of C++, use the std::string class. It isn't especially efficient and it's widely criticised for being over-desinged, but it's standard. It does memory management for you, and it's easy to create one.

You can use std::string like this
class Medicine {
public:
char description[100] = "testing";
std::string getDescription() {
return description;
}
};

Related

C++ invalid conversion from 'const char*' to char*

I am new to C++. I have an exercise about constructor with const char* parameter.
class Book
{
private:
char* title;
}
public:
Book (const char* title)
{
this->title = title;
}
When I code the constructor like that, I receive error cannot convert const char to char*.
I tried using
strcpy(this->title, title);
then, it run, but I don't get the expected result.
Can anyone help me.
Thank you very much.
You are doing an exercise, did the course you are following not explain what you are supposed to do?
I would guess that this is an exercise in dynamic memory allocation and what you are expected to do is use strcpy after you have allocated some memory so that you have somewhere to copy the string to. Like this
this->title = new char[strlen(title) + 1];
strcpy(this->title, title);
You need to allocate one extra char because C style strings are terminated with an additional nul byte.
But any C++ programmer who was doing this for real (instead of it being a learning exercise) would use a std::string as paxdiablo says.
C++ doesn't let you easily change a const char * into a char * since the latter has no restrictions on how you can change the data behind that pointer.
If you're doing C++, you should be avoiding char * (legacy C) strings as much as possible. By all means take them as parameters if you must, but you should be turning them into C++ strings at the earliest opportunity:
class Book {
private:
std::string m_title;
public:
Book (const char *title) {
m_title = title;
}
};
The one thing you don't want to become is a C+ developer, that strange breed that never quite made the leap from C across to the C++ way of thinking :-)
And, actually, if a given book is never expected to change its title, you're better off making it constant and initialising it, rather than assigning to it, something like:
#include <iostream>
#include <string>
class Book {
public:
Book (const char* title): m_title(title) {};
void Dump() { std::cout << m_title << "\n"; }
private:
const std::string m_title;
};
int main() {
Book xyzzy("plugh");
xyzzy.Dump();
}

Use a string as a char

I have been given this definitions, the function should return what is in info->phrase. However info->phrase can contain a string in which case I can only make it return the first char on info->phrase. Is there a way to make a string compatible with the char type? I am new to c++.
struct rep_info {
int num;
char *phrase;
};
I´ve tried few thing but get type errors, this was my latest attempt
char *phrase_info(rep_info info) {
char text[std::strlen(info->phrase) + 1];
text = info->phrase;
return text;
}
Since you said you have been given these definitions, let's fix the problem with the current setup first. Looking at your function, you are trying to copy into this local array (incorrectly I might add), and return this local variable. There are a number of things wrong with this, including the syntax and the fact that the local variable is destroyed when the function exits.
If you just need to get the value of the phrase member variable, the simplest solution would be to just access the member variable directly and return it:
char *phrase_info(rep_info info) {
return info.phrase; //since info is not a pointer, use the '.' accessor
}
If you mean to pass a pointer to the function, you would re-write it like this:
char *phrase_info(rep_info *info) {
return info->phrase;
}
But it seems like you feel the need to copy the contents of info->phrase into a new memory space? If so, then you would do something like this where you first allocate new memory and return this buffer:
char *phrase_info(rep_info *info) {
char *buf = new char[std::strlen(info->phrase) + 1];
std::strcpy(buf,info->phrase); //copies info->phrase into buf
return buf;
}
You would then need to use delete on the returned memory value to clean up the memory allocated by new, otherwise you will have a memory leak.
Overall, all the above solution would potentially solve the problem given some parameters you haven't made clear. To round this out, this should be written more like:
class rep_info {
private:
int num;
std::string phrase;
public:
rep_info(int n, std::string p) : num(n), phrase(p) {}
std::string get_phrase() { return phrase; }
// other functions
};
//later in the code
rep_info info(...);
info.get_phrase();
Ideally, you would wrap these member variables into their own object with corresponding member functions that can get and set these values. Moreover, for handling strings in C++, std::string is the preferred option for storing, copying, modifying, etc. strings over the older char * C-style string.

Implementing a String class with implicit conversion to char* (C++)

It might not be advisable according to what I have read at a couple of places (and that's probably the reason std::string doesn't do it already), but in a controlled environment and with careful usage, I think it might be ok to write a string class which can be implicitly converted to a proper writable char buffer when needed by third party library methods (which take only char* as an argument), and still behave like a modern string having methods like Find(), Split(), SubString() etc. While I can try to implement the usual other string manipulation methods later, I first wanted to ask about the efficient and safe way to do this main task. Currently, we have to allocate a char array of roughly the maximum size of the char* output that is expected from the third party method, pass it there, then convert the return char* to a std::string to be able to use the convenient methods it allows, then again pass its (const char*) result to another method using string.c_str(). This is both lengthy and makes the code look a little messy.
Here is my very initial implementation so far:
MyString.h
#pragma once
#include<string>
using namespace std;
class MyString
{
private:
bool mBufferInitialized;
size_t mAllocSize;
string mString;
char *mBuffer;
public:
MyString(size_t size);
MyString(const char* cstr);
MyString();
~MyString();
operator char*() { return GetBuffer(); }
operator const char*() { return GetAsConstChar(); }
const char* GetAsConstChar() { InvalidateBuffer(); return mString.c_str(); }
private:
char* GetBuffer();
void InvalidateBuffer();
};
MyString.cpp
#include "MyString.h"
MyString::MyString(size_t size)
:mAllocSize(size)
,mBufferInitialized(false)
,mBuffer(nullptr)
{
mString.reserve(size);
}
MyString::MyString(const char * cstr)
:MyString()
{
mString.assign(cstr);
}
MyString::MyString()
:MyString((size_t)1024)
{
}
MyString::~MyString()
{
if (mBufferInitialized)
delete[] mBuffer;
}
char * MyString::GetBuffer()
{
if (!mBufferInitialized)
{
mBuffer = new char[mAllocSize]{ '\0' };
mBufferInitialized = true;
}
if (mString.length() > 0)
memcpy(mBuffer, mString.c_str(), mString.length());
return mBuffer;
}
void MyString::InvalidateBuffer()
{
if (mBufferInitialized && mBuffer && strlen(mBuffer) > 0)
{
mString.assign(mBuffer);
mBuffer[0] = '\0';
}
}
Sample usage (main.cpp)
#include "MyString.h"
#include <iostream>
void testSetChars(char * name)
{
if (!name)
return;
//This length is not known to us, but the maximum
//return length is known for each function.
char str[] = "random random name";
strcpy_s(name, strlen(str) + 1, str);
}
int main(int, char*)
{
MyString cs("test initializer");
cout << cs.GetAsConstChar() << '\n';
testSetChars(cs);
cout << cs.GetAsConstChar() << '\n';
getchar();
return 0;
}
Now, I plan to call the InvalidateBuffer() in almost all the methods before doing anything else. Now some of my questions are :
Is there a better way to do it in terms of memory/performance and/or safety, especially in C++ 11 (apart from the usual move constructor/assignment operators which I plan to add to it soon)?
I had initially implemented the 'buffer' using a std::vector of chars, which was easier to implement and more C++ like, but was concerned about performance. So the GetBuffer() method would just return the beginning pointer of the resized vector of . Do you think there are any major pros/cons of using a vector instead of char* here?
I plan to add wide char support to it later. Do you think a union of two structs : {char,string} and {wchar_t, wstring} would be the way to go for that purpose (it will be only one of these two at a time)?
Is it too much overkill rather than just doing the usual way of passing char array pointer, converting to a std::string and doing our work with it. The third party function calls expecting char* arguments are used heavily in the code and I plan to completely replace both char* and std::string with this new string if it works.
Thank you for your patience and help!
If I understood you correctly, you want this to work:
mystring foo;
c_function(foo);
// use the filled foo
with a c_function like ...
void c_function(char * dest) {
strcpy(dest, "FOOOOO");
}
Instead, I propose this (ideone example):
template<std::size_t max>
struct string_filler {
char data[max+1];
std::string & destination;
string_filler(std::string & d) : destination(d) {
data[0] = '\0'; // paranoia
}
~string_filler() {
destination = data;
}
operator char *() {
return data;
}
};
and using it like:
std::string foo;
c_function(string_filler<80>{foo});
This way you provide a "normal" buffer to the C function with a maximum that you specify (which you should know either way ... otherwise calling the function would be unsafe). On destruction of the temporary (which, according to the standard, must happen after that expression with the function call) the string is copied (using std::string assignment operator) into a buffer managed by the std::string.
Addressing your questions:
Do you think there are any major pros/cons of using a vector instead of char* here?
Yes: Using a vector frees your from manual memory management. This is a huge pro.
I plan to add wide char support to it later. Do you think a union of two structs : {char,string} and {wchar_t, wstring} would be the way to go for that purpose (it will be only one of these two at a time)?
A union is a bad idea. How do you know which member is currently active? You need a flag outside of the union. Do you really want every string to carry that around? Instead look what the standard library is doing: It's using templates to provide this abstraction.
Is it too much overkill [..]
Writing a string class? Yes, way too much.
What you want to do already exists. For example with this plain old C function:
/**
* Write n characters into buffer.
* n cann't be more than size
* Return number of written characters
*/
ssize_t fillString(char * buffer, ssize_t size);
Since C++11:
std::string str;
// Resize string to be sure to have memory
str.resize(80);
auto newSize = fillSrting(&str[0], str.size());
str.resize(newSize);
or without first resizing:
std::string str;
if (!str.empty()) // To avoid UB
{
auto newSize = fillSrting(&str[0], str.size());
str.resize(newSize);
}
But before C++11, std::string isn't guaranteed to be stored in a single chunk of contiguous memory. So you have to pass through a std::vector<char> before;
std::vector<char> v;
// Resize string to be sure to have memor
v.resize(80);
ssize_t newSize = fillSrting(&v[0], v.size());
std::string str(v.begin(), v.begin() + newSize);
You can use it easily with something like Daniel's proposition

C++: Efficiently adding integers to strings

I know how to add integers to strings, but I'm not sure I'm doing it in an efficient matters. I have a class where I often have to return a string plus an integer (a different integer each time), in Java I would do something like
public class MyClass {
final static String S = "MYSTRING";
private int id = 0;
public String getString() {
return S + (id++);
}
}
But in C++ I have to do;
class MyClass {
private:
std::string S; // For some reason I can't do const std::string S = "MYSTRING";
int id;
public:
MyClass() {
S = "MYSTRING";
id = 0;
}
std::string getString() {
std::ostringstream oss;
oss << S << id++;
return oss.str();
}
}
An additional constraint: I don't want (in fact, in can't) use Boost or any other librairies, I'll have to work with the standard library.
So the thing is; the code works, but in C++ I have to create a bunch of ostringstream objects, so it seems inefficient. To be fair, perhaps Java do the same and I just don't notice it, I say it's inefficient mostly because I know very little about strings.
Is there a more efficient way to do this ?
std::ostringstream is the "standard" way to do this in C++. You might be able to make something more efficient via some custom coding, or laboriously comparing the performance of ostringstream, itoa, and sprintf on all the systems where you'll be deploying this program, but it's probably not worth the effort.
I'd say the real problem with the std::ostringstream solution is not about efficiency. The real problem is that the code just looks too complicated.
I know you don't want to use Boost, but if you look at Herb Sutter's The String Formatters of Manor Farm, you could just copy the (very tiny) definition of the lexical_cast<>() template into your program. Then your code would look like this:
std::string getString() {
return S + lexical_cast<std::string>(id++);
}
Whether this is more efficient than your existing solution depends on a lot of factors (how well your compiler inlines template instantiations, for example), but it definitely looks cleaner.
I'm pretty sure you can do the following:
class MyClass
{
private:
const std::string S; // For some reason I can't do const std::string S = "MYSTRING";
int id;
public:
MyClass() :
S( "MYSTRING" )
{
id = 0;
}
}
Thats totally off the top of my head and untested though so I'm fully expecting tonnes of down votes :D hehehe
To add to the other answers:
... the code works, but in C++ I have to create a bunch of ostringstream objects, so it seems inefficient. To be fair, perhaps Java do the same and I just don't notice it, ...
Java does in fact do exactly the same thing; + with Strings is syntactic sugar for StringBuffer.append(), so these do the same thing:
String f = "foo";
f += "bar" + "baz";
String f = "foo";
f = StringBuffer(f).append("bar").append("baz");
You are right, ostringstream generally add overhead.
This is more efficient, and IMO is more idiomatic...
std::string adder() {
static int i;
char buf[32];
snprintf(buf, sizeof(buf), "MYSTRING%i", i++);
return buf;
}

How can I prevent the need to copy strings passed to a avr-gcc C++ constructor?

In the ArduinoUnit unit testing library I have provided a mechanism for giving a TestSuite a name. A user of the library can write the following:
TestSuite suite("my test suite");
// ...
suite.run(); // Suite name is used here
This is the expected usage - the name of the TestSuite is a string literal. However to prevent hard-to-find bugs I feel obliged to cater for different usages, for example:
char* name = (char*) malloc(14);
strcpy(name, "my test suite");
TestSuite suite(name);
free(name);
// ...
suite.run(); // Suite name is used here
As such I have implemented TestSuite like this:
class TestSuite {
public:
TestSuite(const char* name) {
name_ = (char*) malloc(strlen(name) + 1);
strcpy(name_, name);
}
~TestSuite() {
free(name_);
}
private:
char* name_;
};
Putting aside the issue of failing to deal with memory allocation failures in the constructor I'd prefer to simply allocate the pointer to a member variable like this:
class TestSuite {
public:
TestSuite(const char* name) : name_(name) {
}
private:
const char* name_;
};
Is there any way I can change the interface to force it to be used 'correctly' so that I can do away with the dynamic memory allocation?
What if you provide two overloaded constructors?
TestSuite(const char* name) ...
TestSuite(char* name) ...
If called with a const char*, then the constructor could make a copy of the pointer, assuming that the string will not go away. If called with a char*, the constructor could make a copy of the whole string.
Note that it is still possible to subvert this mechanism by passing a const char* to the constructor when the name is in fact dynamically allocated. However, this may be sufficient for your purposes.
I should note that I have never actually seen this technique used in an API, it was just a thought that occurred to me as I was reading your question.
Documentation. For example,
/**
* Test suite constructor.
* #param name test suite name cstring, shared
*/
TestSuite(char const *name) {
// ...
A shared pointer implies that the pointed object must be alive during the lifetime of this object.
Well, you can use a std::string that will take care of all memory allocation
class TestSuite {
public:
TestSuite(const std::string &name):name_(name) {
}
~TestSuite() {
}
private:
std::string name_;
};
Edit :
If it is the call to malloc() that you want to avoid you could do this :
class TestSuite {
public:
TestSuite(const char *name){
memcpy(name_, name, min(16, strlen(name));
}
private:
char name_[16];
};
This will waste some memory however, which can be an issue on embedded platforms.
Have a char name[XYZ] member of your TestSuite (with an XYZ large enough to comfortably display the name) and use strncpy to copy the string (with a maximum length of XYZ-1).
Why are you using char* and malloc when you have the nice C++ string class which can takes a string literal or a char* in its constructor ?
Are you able to use std::string? You could have it as std::string name_ and have the STL take care of the memory allocation for you..
class TestSuite {
public:
TestSuite(const char* name) : name_(name) {}
~TestSuite() {}
private:
std::string name_;
};
Don't forget to include <string>.
Reference