Populating a c-string array using a pointer - c++

For my homework assignment I have to write a function that uses a char pointer to populate a c-string array. The overall goal of the assignment is to get familiar with dynamic memory allocation. I am not familiar with this topic so it may have something to do with that. This would be easy except the function is required to be const, therefore I cannot increment the pointer and set each value in the array equal to the pointer.
I've tried using a for loop however because the function is const it will not let me increment read-only values.
Here is my function so far:
const char* MyString::c_str() const {
char c_str[m_size];
c_str = *m_buffer;
return c_str;
}
m_buffer is a char* that points to a sentence.
m_size is the size of the pointer.

Related

Converting string in char array in CPP

I am working on a project and I am stuck at this for a while.
I have to pass to the "write" function a char array.I tried to convert the "data" curenty string to char arrays using https://www.techiedelight.com/convert-std-string-char-cpp/ but i get only errors
error: request for member ‘c_str’ in ‘data’, which is of pointer type ‘const string*’ {aka ‘const std::__cxx11::basic_string<char>*’} (maybe you meant to use ‘->’ ?)
char* c[] = const_cast<char*>(data.c_str());
void LCD::print(const std::string* data)
{
for (int i = 0; i < strlen(data); i++)
write(data[i]);
}
const std::string*
It's hardly ever a good idea to pass a std::string pointer into a function. I recommend not doing such thing. How to replace it depends on your intentions. Reference to const is a typical default choice if you're passing a single string.
strlen(data)
The strlen function does not accept an argument of type const std::string*. This program is ill-formed.
If you want the length of a std::string, you can use the size member function.
write(data[i]);
Here, you're using subscript operator to access the ith std::string object within an array of std::string objects pointed by data.
The strlen usage and the description imply that there is only one string involved which contradicts this array iteration.
error: request for member ‘c_str’ in ‘data’, which is of pointer type ‘const string*’ {aka ‘const std::__cxx11::basic_string<char>*’}
(maybe you meant to use ‘->’ ?)
char* c[] = const_cast<char*>(data.c_str());
The error message explains what you did wrong. data is a pointer. Pointers don't have member functions. You tried to call the member function c_str of the pointer which doesn't exist.
The error message also suggests the likely solution. If you indirect through the pointer (using the indirecting member access operator ->) to access the pointed string, then you will access the c_str member function of the string. std::string does have such member function.
There's another bug in the quoted code. You're trying to use the returned pointer to initialise an array of pointers c. That's not possible. There's only one pointer returned, and it doesn't make much sense to create an array of one elements in this case.
I have to pass to the "write" function a char array
I suspect that you actually mean, you have to pass a pointer to first element of a null terminated char array. It can be done like this:
std::string data = ...;
write(data.c_str());
It's so trivial, that I wouldn't recommend writing a function for this purpose.
The problem is that strlen accepts a const char* while you're supplying a const string*. You can solve this by using the size() member function of std::string as follows:
void print(const std::string* data)
{
for (int i = 0; i < (*data).size(); i++)//first we dereference the pointer named data then call the size() member function on pointed string object
write((*data)[i]); //first we dereference the pointer named data then access the ith element of the pointed string object
}

Can a pointer be decleared as void storing chars?

char* pointer = new char [5];
strcpy_s(pointer,4, "foo");
I am not fully understanding how pointers work. In my understanding the variable pointer is supposed to store the starting address of the new allocated string of chars. If so why is it important that the pointer is a char since its only storing an address.
why can't i just type
void* pointer = new char [5]
Thanks.
the pointer needs to know the size of its element, thanks to it you can use [] operator to reach a certain element of the array, how else would it know how much memory it has to move to get to the n-th element? If you could declare a pointer to any type as void, then it would have to automatically deduce the type it points to. Consider this piece of code:
char* pointer = new char[5];
pointer[3] = 'a';
for void* this would not be possible. I suppose that the strcpy_s function expects the first parameter as char*, not void* and that is the reason why your code doesn't compile. Pointer itself just allows you to know where some variable/array or even function is in memory, but when you specify pointer's type it gives it more flexibility.

problems in member function

#include <iostream>
#include <cstring>
using namespace std;
class student {
int roll_no;
char name[56];
public:
void setdata(int roll_no_in, const char* name_in) {
roll_no = roll_no_in;
strcpy(name, name_in);
}
void outdata() {
cout << "rollno is " << roll_no << endl << "name is " << name << endl;
}
};
int main() {
student s1;
s1.setdata(12, "robin");
s1.outdata();
return 0;
}
i have some doubts in this program
how can we store strings into pointer like above program storing the string robin into char *name_in since pointers are used only to store address.Can we store even strings?
why should i add const in the method function set data if i don't use
that then it shows me error. It is optional right?
why can't i use char name_in[34] in the place of char *name_in in the setdata method function?
C strings are arrays of char. When you pass an array as a function argument, it's converted to a pointer to the first element.
The const modifier indicates that the function will not modify the contents of name_in. Since string literals are constants, you need this to permit the function to be called with a literal argument.
You can. But since the function doesn't actually have a limit on the size of the string it will accept, that would be misleading. Declaring a parameter as an array with a length is treated just like declaring it as a pointer; the length you specify is ignored. Note: This is only true for the first dimension; when passing a multi-dimensional array, you can omit the first dimension's length, but need to specify all the other dimensions.
how can we store strings into pointer like above program storing the string johnson into char *name_in since pointers are used only to store address.
You're not storing it in name_in, you're storing it into name, which is an array. name_in is a pointer to the array passed to the function; the array is automatically converted to a pointer when passed to a function. (More generally, a pointer can point to the start of an array, and be used to access the array; C-style functions like strcpy do exactly that.)
In idiomatic C++, you'd use a class rather than this dangerous mucking about with pointers and arrays:
std::string name;
name = name_in;
why should i add const in the method function set data if i dont use that then it shows me error.
I assume you mean in const char * name_in. You're passing a pointer to a string literal, which is constant; and the language doesn't allow you to take a non-constant pointer to a constant object.
It is optional right?
Before C++11, it was optional; leaving it out was merely a very bad idea. Now it's mandatory.
why can't i use char name_in[34] in the place of char *name_in in the setdata method function
You can; as a function argument, both are equivalent. Again you'll need const to be able to pass a string literal or other constant string. It would be somewhat misleading though, implying that name_in is an array, of a particular size, when neither are guaranteed.
Again, this is C++, so std::string is almost certainly a better option than either.
*how can we store strings into pointer like above program storing the string johnson into char name_in since pointers are used only to store address.Can we store even strings?
You are actually storing pointer to the base address of the string. You can use this pointer to traverse whole string.
why should i add const in the method function set data if i dont use that then it shows me error
"Ravi" is a string literal which is stored in memory which is read only. So, if you try to pass this literal to function accepting char *, it would be the violation of the constraint compiler is trying to establish.
*why can't i use char name_in[34] in the place of char name_in in the setdata method function?
You are passing pointer to char to this function, so you have to use pointer to char to accept it. However, arrays , when passed to function as argument decays to a pointer.

what the differences between char** and char*[]

Recently, I need to declare a string array, so I wrote down the following statement:
const char** directories = {"cricket_batting", "cricket_bowling", "croquet", "tennis_forehand", "tennis_serve", "volleyball_smash"};
However, g++ showed me the error:
error: scalar object ‘directories’ requires one element in initializer
So I changed the statement to this:
const char* directories[] = {"cricket_batting", "cricket_bowling", "croquet", "tennis_forehand", "tennis_serve", "volleyball_smash"};
This time, it was right. But I can't exactly know the difference between char** and char[].
= {...};
Initialisation of this form is known as list-initialization.
const char**
This type is a "pointer to pointer to const char".
const char*[]
This type is an "array of pointer to const char".
Simply put, you cannot initialise a pointer with list-initialization. You can initialise an array with list-initialization; it initializes each of the elements in the array with the items in the braced list.
The reason comes down to what exactly you get from a declaration. When you declare a const char**, all you get is a single pointer object. It's a const char**, which is a pointer promising to point at a pointer to const char. Nonetheless, all you actually have is the outer pointer. You can't then initialise this as though it's an array, since you only have one pointer. Where exactly are you going to store the elements of the initialization list? There is no array of pointers in which you can store them.
However, when you declare a const char*[], what you get is an array of pointers. The size of the array is determined by the size of the list because you have omitted it.
The former is a pointer to a pointer to const char while the latter is an array to pointer to const char. The latter is the correct way to initialize an array of strings.
You would need to allocate memory using new to set up char** , for you can't simply initialize pointers with { }.
When you write int a[] we are making an array of integers. Similarly when you write const char* directories[] you are creating an array of char* pointers. Now each char* can point to a char or a string as in your case. This creates individual string constants and assigns the base address of each to the corresponding pointer in the array
char **directories is pointer to a pointer and you can't assign value to a pointer using { .. }

Cannot convert from 'T[N][2]' to 'T[][2]'

I have an API taking some options:
void init_api(const char* options[][2]);
I am allowed to pass a NULL pointer for no options, alternatively, an options array such as this can be passed:
const char* some_options[][2] = { {"opt1", "val1"},
{"opt2", "val2"},
{0,0}
};
This works without problems:
...
init_api(some_options);
... or ...
init_api(NULL);
...
However, this fails to compile:
const char* my_options[][2] = NULL; // error C2440: 'initializing' : cannot convert from 'int' to 'const char *[][2]'
if(...) {
my_options = some_options; // error C2440: '=' : cannot convert from 'const char *[4][2]' to 'const char *[][2]'
}
init_api(my_options); // no error here
What is going on here? Can someone explain this?
To declare an empty array of array of pointers to const char, you should use:
const char* my_options[][2] = {};
You need to declare a pointer to an array of pointers to const char instead. I recommend using a typedef to simplify the syntax.
typedef const char* array_of_two_cstring[2];
array_of_two_cstring* my_options = NULL;
if (...) {
my_options = some_options;
}
init_api(my_options);
In C++ (it is herited from C), array can be implicitly converted to pointer (only once though, that is char[] is compatible with char* but char[][] is compatible with char*[] but not `char**). However, the variable cannot be reassigned. So here you need to use a pointer instead of an array.
The init_api option accepts NULL as a parameter because for the compiler, its prototype is void init_api(char const* (*)[2]) (the first array degenerated into a pointer), and NULL is a valid pointer.
The compiler must know the array size.
If you omit the size of the array (ie: using []) you need to initialize the array with the definition, in order to let the compiler count how many items that array will contain.
Moreover you are assigning a pointer (NULL) to an array: const char *x[][2] is an array of two pointers to const char.
Edit:
In C++ (as in C), arrays can decay into pointers when you use them (with three exceptions which are not interesting here).
When you pass an array to a function expecting an array, what happens is that you actually pass a pointer to the array, since the array decays; you cannot pass an array by value in C or C++.
For this reason you can pass NULL to your function; the function parameter will be NULL, and if you try to access the array within your function (options[0]) your application will crash: you'll be dereferencing an invalid pointer.
You cannot however set your array variable to NULL, since it's not a pointer, it's an array: it will only decay when you'll use it in an expression.
const char* options[][2]
is an array of const char* pointers. You can't assign a pointer to an array.
A parameter declared as being an array of type T[N] or T[] becomes actually a parameter of type T*. Same is done for functions (a parameter declared as R(Params) becomes actually a parameter of type R(*)(Params...)).
Such transformation however is not done for other declarations. The reason it's done for function by-value parameters is that there is no way in C to actually copy an array directly (that is, to actually copy its contents) and it doesn't make sense to try and copy a function either, so such parameters are transformed in a way that conveys their purpose in a meaningful way.
So while you are initializing a pointer in the function parameter case, you are trying to initialize an array in the other case.