problems in member function - c++

#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.

Related

How can I make function that take a string and return a char array

I want to return an array of chars and this is the code
char convert(string user){
int n = user.length();
char char_array[n+1];
strcpy(char_array,user.c_str()) ;
return char_array;
}
You cannot return an array from a function. You can return a pointer to the first element of such array. Good news is: That function already exists. It is the std::string::c_str method.
void foo(const char*); // <- legacy, cannot modify, must pass c-string
std::string x{"Hello World"};
foo( x.c_str() );
In your code, this char char_array[n+1]; is not valid standard C++. See here for details:
Why aren't variable-length arrays part of the C++ standard?
Moreover you attempt to return a pointer to a local array. Once the function ends the arrays lifetime has passed and the pointer is of no use. More on that here:
Can a local variable's memory be accessed outside its scope?
Last (and least) you declared the function to return a char when you wanted a char*. However, fixing that won't really help due to the last point.

what is the difference between string a="hello" and string a=(char *)"hello" in c++?

What is the difference between these two string initializations in c++?
i get the same output in both the programs.
Program 1
void main(){
string a = "hello";
cout<<a;
}
program 2
void main(){
string a = (char *)"hello";
cout<<a;
}
"hello" is a string literal. Its type is
const char[N], where N is the size of the string [...] including the null terminator.
So in this case, the type is const char[6]. Note the const.
Now std::string can be constructed (constructor 5 in the link) from a const char*. Again, note the const.
In C++, you can pass a non-const object into a function that expects a const. In your case, your cast (char *) removes the const, but then immediately puts the const back on in the constructor call.
So basically, no difference. They will compile to exactly the same thing.
A few additional notes:
casting away const-ness is very dangerous. If you had actually tried to change anything in the char array, your program would have had Undefined Behaviour.
using namespace std; is widely considered to be bad practice.
void main() is not a valid signature for the main function; it must return an int.
Using C-style casts in C++ can also be considered a bad practice - it is harder to spot in code, and C++ provides safer equivalents for more specific situations: const_cast, static_cast, dynamic_cast, and (the most dangerous) reinterpret_cast.
Nothing actually, that additional char * type casting is not needed.
In both the cases copy initialization is done.
string (const char* s);
read more on copy initialization
std::string is a typedef for a specialization of basic_string class templated on a char (objects that represent sequences of characters).
The expression string a = "hello" corresponds to a stream of characters whose size is allocated statically.
Short, simple and typesafe std::cout is a typedef of ostream class templated on standard objects (provides support for high-level output operations).
cout means "the standard character output device", and the verb << means "output the object".
cout << a; sends the string like a stream to the stdout.
char * are special pointers to a constant character, they point to ASCII strings e.g.:
const char * s = "hello world";
The expression (char *)"hello" corresponds to a char * pointer, where you are casting away const, but then the constructor immediately puts the const back on the call.
cout, therefore, will print a string because it has a special operator for char * wich it will treat as a pointer to (the first character of) a C-style string that outputs strings.
char* or const char*, cout will treat the operand as a pointer to (the first character of) a C-style string, and prints the contents of that string:

How can a char variable parameter take in a string?

Assume a function with one parameter of const char* type. When I use a string when calling that function, nothing goes wrong! I would expect that you could only input characters included in the ASCII, for example c or dec 68, but it seem otherwise. Take a look at the code below...
void InitFunction(const char* initString)
{
std::cout << initString;
}
int main()
{
InitFunction("Hello!");
}
When you run the code, no problem, warnings, or errors appear. I did some more testing on this as you can see from the following...
void InitFunction(char initString)
{
std::cout << initString;
}
int main()
{
InitFunction("Hello!"); // compiler error on this line
}
This compiles with an error since Hello! cannot be converted into char. I tried another test, but instead used const char as the function parameter type. The code still compiles with an error. But when I add * to the function parameter type, then everything compiles fine! It appears to me that the const is also necessary.
To my understanding of pointers, the function is asking for a pointer, and the pointer is identified as being a character. But this raises three problems for me.
First, Hello! is not in the form of a pointer. I would expect at least to have to use the reference operator (&).
Second, Hello! is not a char type.
And third, why do we need to include the const?
Am I missing something here? Do pointers and characters work in ways that I don't know?
"Hello!" is a const char array of characters. Arrays are treated like a pointer, they decay to a pointer when used in a function call as an argument. The C++ standard specifies this in order to be compatible with the way that the C language standard specifies arrays are to be treated.
By the way this array decay to a pointer happens with other cases where an array is being used where a pointer or the address operator could be used such as an assignment statement. See also Arrays are Pointers?
So "Hello!" will be put into the argument list of InitFunction() as a pointer which points to where the compiler has stored the array of characters with the terminating zero character added. When the compiler generates the code for the function call, the pointer to the array of characters used as an argument to the function is const char *, a pointer to a char which is const and should not be changed.
When you have the function prototype as InitFunction(const char *), the compiler is fine with a function call such as InitFunction("Hello!");. What you are doing is providing a const char * that points to "Hello!".
However if you remove the const then since "Hello!" is a const the compiler complains. The compiler complains because a const variable is being used in a function call whose argument list is non-const indicating that the function may change what the pointer is pointing to. Since "Hello!" is not supposed to be changed, since it is const, the compiler issues an error.
If you remove the asterisk, change const char * to const char, then since "Hello!" is a char array which the compiler then decays into a pointer to the first element of the array, the compiler complains as you are trying to use a pointer for an argument that is not a pointer. In this alternative the problem is the actual data type, char versus char * is the problem.
The following lines of code would also be acceptable:
const char *p = "Hello!"; // create a pointer to an series of characters
char x1[] = "Hello!"; // create an array of char and initialize it.
char *p2 = x1; // create a pointer to char array and initialize it.
char *p3 = x1 + 2; // create a pointer to char array and initialize it with address of x1[2].
InitFunction (p); // p is a const char *
InitFunction (x1); // x1 decays to a char *
InitFunction (p2); // p2 is a char *
InitFunction (p3); // p3 is a char *
InitFunction (x1 + 3); // called with address of x1[3].
Note also C++ has an actual character string type, string, that results in a dynamic character text string whose underlying physical memory layout normally includes a pointer to an array of characters. The C style array of characters that is labeled a string is not the same thing as the C++ string type.
the function is asking for a pointer
Correct.
and the pointer is identified as being a character
No, a pointer is a not a character. A pointer is a pointer. This pointer points to one or more characters, i.e. an array of characters. And that's exactly what your string literal is.
First, Hello! is not in the form of a pointer.
Yes, it is. The string literal "Hello!" has type const char[7] and this decays to a pointer.
I would expect at lest to have to use the reference operator (&).
That's the address-of operator. You don't always need it to get a pointer. Example: this.
Second, Hello! is not a char type.
No, but each constituent character is.
And third, why do we need to include the const?
Because the string literal "Hello!" has type const char[7]. Dropping the const would violate const-correctness and is therefore not permitted.
This throws an error since Hello! cannot be converted into char.
That's right. A char is one byte. The string "Hello!" is not one byte. It is a string.
A C-string is typically/conventionally/usually provided in const char* form.
You should read the chapter in your book about this subject as it's a fundamental of the language. It has nothing to do with ASCII (text encodings are irrelevant to storing a sequence of bytes).

Pointer in C/C++

I have code:
char* s="abc";
I have a question, what's datatype of a variable in this code?
datatype of s is int
s is string?
So, if datatype of s is int, why cout<<s is "abc"?
The type of s is what the variable is declared to be, nothing else. It is pointer to char, or char*. It points to the first element of a read-only char array, which is why it should really be const char*. In fact, the conversion to char* is deprecated in C++.
The data type is char * (character pointer). It internally contains an integer (the size depends on the processor architecture that you are targeting). It shows up as "ABC" because the << operator is overloaded to display character pointers as strings. If you want to see the integer value, cast it to void *.
Let's ratiocinate.
If s had type int when its declaration would contain type specifier int or some typedef name (a user defined alias for int) that equivalent to int. For example
int s;
or
typedef int MyPersonalType;
MyPersonalType s;
The same way if s had type std::string it would be declared like
std::string s;
Neither the first nor the second is used in the declaration of s.
s is declared like
char* s;
So it has type char * that is it is a pointer to character. Moreover s is initialized by a string literal
char* s="abc";
In this case s is initialized by the address of the first character of the string literal.
So when you use statement
std::cout << s;
this string literal is outputed.
Take into acccount that this record
char* s="abc";
is valid in C. In C++ you have to specify also qualifier const
const char* s="abc";
because string literals are immutable.
"abc" is a literal consisting of the three characters a, b, and c followed by a null terminator.
It can be assigned to a const char*. You can also assign it to a char* but that is dangerous since you cannot modify the contents of the literal.
cout contains an overload that will track along the input pointer until it reaches the null terminator; outputting the characters as it goes.
So, s is modelling a sting of characters.

Should I cast arrays to pointers when passing them to variadic functions like printf?

Can I pass an array to printf directly:
char text[1024] = "text";
printf("%s", text);
Or should I explicitly cast it to a char pointer:
char text[1024] = "text";
printf("%s", (char*) text);
I'm asking because I thought maybe it copies the array elements directly into the va_list instead of putting just a pointer to the first element.
Yes, you can pass an array directly. Exactly, name of array represents address of the array which makes no difference with char *.
(char*)text and text hardly make any difference in this example! Base address of an array decays into a pointer when passed as a function argument.
In fact, even if text was not a char array, still it would hardly make any difference to printf because it is a variable argument function
int printf(const char *format, ...);
and all it cares is about the first argument. Logic might go wrong but printf doesn't care!
Short answer, yes, arrays in C _are_a pointer to their first element. (Edit: Longer answer, well, actually, arrays in C are identifiers or labels which are just names, but when used as part of an expression that doesn't preface them with & or sizeof they get converted into or otherwise evaluated as pointers).
Even longer answer: You see, functions can't really receive an array as an argument, but the compiler has to send them something, so it sends them a pointer. Thus the first sentence should probably start with "As far as functions like printf() are concerned..."
Some functions purport to take an array, but that's just an illusion. These two functions are the same.
func(char *a);
func(char a[]);
The C FAQ entry below goes into more detail about the subtle differences between arrays and pointers:
char a[] = "this";
char *b = "that";
a[0] generates completely different code than b[0] yet they are roughly equivalent in that the subscripting operator [] gives us the expected result.
Interestingly, the format specifier "%s\n" is also passed to printf() as a pointer.
http://www.lysator.liu.se/c/c-faq/c-2.html
Isn't an array/arrayname always a pointer to the first element in C?
Except when it is the operand of the sizeof or unary & operator, or is a string literal being used to initialize another array in a declaration, an expression of type "N-element array of T" will be replaced by an expression of type "pointer to T" whose value is the address of the first element of the array.
When you write
printf("%s", text);
the expression text is replaced by a new expression of type char * whose value is &text[0], and this pointer value is what gets passed to printf. This means you don't have to cast the argument. It also means that you cannot pass an array expression as a function parameter and have the called function receive it as an array type. The conversion happens before the function is called.
names of pointers and arrays are exchangeable. (Besides the memory allocation)
When you have
char *a = "abcdef";
char b[5];
You could write
char z = a[2]; // 'c'
char x = *b;
char y = *(b+2);
But you can't do
b ++;
You may consider array b as char * const b as a unmodifyable pointer