char *name[]={"Riyaz","Kapil","mayank","Ankur"};
int len=0;
len=strlen(name[1]);
cout<<"\n String 2 is "; puts(name[1]); cout<<"\n and string 3 is";puts(name[2]);
//exchange now//
char *temp;
temp=name[1];
name[1]=name[2];
name[2]=temp;
len=strlen(name[1]);
cout<<"\nExchanged string is "; puts(name[1]);
return 0;
How can I remove "deprecated conversion from string constant to 'char*'" warning in this code?
I was trying this program on array of pointers actually, so suggest some changes considering that.
Just declare the array like
const char *name[]={"Riyaz","Kapil","mayank","Ankur"};
^^^^^
Opposite to C in C++ string literals have types of constant character arrays that in expressions are converted to pointers to their first elements. Though in the both languages string literals are immutable.
Correspondingly variable temp also must be declared like
const char *temp;
Take into acount that these declarations
const char *name[]={"Riyaz","Kapil","mayank","Ankur"};
and
const char * const name[]={"Riyaz","Kapil","mayank","Ankur"};
differ.
The first array is not a constant array. Its elements can be changed and you do that in your program. While the second array is a constant array. Its elements may not be changed.
As for the program then instead of this code snippet
const char *temp;
temp=name[1];
name[1]=name[2];
name[2]=temp;
you could use standard function std::swap declared in header <utility>. For example
#include <utility>
//...
std::swap( name[1], name[2] );
Since you marked the question as C++ (not C), you may want to use convenient C++ classes to build a string array, like a std::vector<std::string>:
#include <string> // for std::string
#include <vector> // for std::vector
// Old C-style:
// const char *name[]={"Riyaz","Kapil","mayank","Ankur"};
//
// C++ style:
std::vector<std::string> names{ "Name1", "Name2", "Name3", ... };
Related
My intention is to create a char[] from the length of a char* I've already created.
I asked myself why this is not valid:
void copyStringsV2() {
const char* source = "this is my string.";
const int length = strlen(source);
const char* dest[length];
}
The compiler gives me this hint:
Severity Code Description Project File Line Suppression State
Warning C4101 'str_b': unreferenced local variable CStrings
xxx\cstrings.cpp 46
Error C2131 expression did not evaluate to a constant CStrings
xxx\cstrings.cpp 161
Error (active) E0028 expression must have a constant value CStrings
xxx\CStrings.cpp 161
May you can help me out here?
You are trying to declare a variable-length array, which is not a standard feature in C++. A fixed-length array must have its length known at compile-time. That is what the compiler error is complaining about.
If you don't know the length until runtime, you will have to allocate the copied string dynamically instead, such as via new[]:
void copyStringsV2()
{
const char* source = "this is my string.";
const int length = strlen(source);
char* dest = new char[length+1];
strcpy(dest, source);
...
delete[] dest;
}
Or std::vector, so you don't need to use new[]/delete[] directly:
#include <vector>
void copyStringsV2()
{
const char* source = "this is my string.";
const int length = strlen(source);
std::vector<char> dest(length+1);
strcpy(dest.data(), source);
...
}
But, in this case, it would be better to use std::string instead:
#include <string>
void copyStringsV2()
{
const char* source = "this is my string.";
std::string dest = source;
...
}
For starters you should use the type size_t instead of the type int in this declaration
const int length = strlen(source);
^^^
This constant is a constant of the run-time. So you may not use it in the declaration
const char* dest[length];
because here is declared a variable length array and variable length arrays (VLA) is not a standard C++ feature.
Also it is unclear why the type of elements of the array is const char * instead const char.
And moreover a constant object shall be initialized.
My intention is to create a char[]
const char* dest[length];
That's not an array of char. That's an array of pointers to const char.
Also, if you want the array to be able to fit the original null termiated string, you must include the null terminator in the length of the array so that its size is length + 1.
I asked myself why this is not valid:
The compiler gives me this hint:
expression did not evaluate to a constant
May you can help me out here?
The size of an array must be a compile time constant. length is not a constant, therefore it cannot be used as length of an array.
Length of a string cannot be calculated at compile time through a pointer to element of the string. However, if you used a reference for example, and if you used a constexpr function to get the length, and used a constexpr (const works too) variable, then you could use it as the size of an array. There is such function in the C++ standard library:
auto& source = "this is my string.";
constexpr auto length = std::char_traits<char>::length(source);
char dest[length + 1];
why this is not compilable
Because this is C++, and C++ provide a wide variety of tools already1. Your best bet will be std::string. Strings can be copied and passed around with no additional code to write.
#include <string>
int main()
{
const std::string source = "this is my string.";
const std::string dest = source;
// do something with dest
}
1) So you don't need variable length arrays, which are not part of C++.
#include <iostream>
#include <string>
using namespace std;
int main() {
string s = "hello";
cout << s[5] << endl;
return 0;
}
In the above code, if I print s[5], it correctly prints a NULL character. But if I change the code to this:
#include <iostream>
#include <string>
using namespace std;
int main() {
char[] s = {'a','b','c','d','e'};
cout << s[5] << endl;
return 0;
}
It doesn't print a NULL character but something random. If I store the string as a string or as a char*, then the behavior is in tune with what I expect.
But if I explicitly declare the character array, how does the compiler know when the array ends? Does the size of the array gets stored at compile time?
String literals and std::strings store null terminated strings.
But an array of 5 char declared like:
char s[] = {'a','b','c','d','e'};
contains only 5 char, no null terminator.
But the compiler does know the size of s. It is part of the type of s. It has no convenient .size() function like std::string, std::vector or std::array does but you can get it by doing:
sizeof(s) / sizeof(s[0])
Or more safely in C++11:
std::extent<decltype(s)>::value
Or in C++17:
std::size(s)
(demo)
Arrays have a habit of decaying to pointers though and then there is no way of getting the size, you have to keep track of it yourself. Which is why std::string, std::vector or std::array is preferred in C++.
Strings are null-terminated, and const char* are treated the same way as Strings are. When you declare a array with a size it's put on the stack and the compiler doesn't know the size. Array out-of-bounds exceptions aren't determined during compile time.
the string class in c++ has the constructor which by itself adds the null character to the string passed to it if not explicitly added. But while using char it only stores the content passed to it (i.e) if you want to have a null character you have to explicitly add in the declaration or the definition of that char.
When you do char[] s = {'a','b','c','d','e'};, it will store characters mentioned and nothing else.
if I explicitly declare the character array, how does the compiler know when the array ends?
size is determined by number of characters provided by you.
Does the size of the array gets stored at compile time?
no, the size of array is determined by memory blocks allocated to it. (It is not stored separately in memory, if that's what you meant)
And when you use this string s = "hello";, strings are always null terminated.
Your code is char s[] = {'a','b','c','d','e'};, so it will not put the \0 at the end of your char array. It will put the \0 with three methods below:
1. char s[] = {'a','b','c','d','e', '\0'};
2. char s[] = "abcde";
3. string s = "abcde";
So if you use any of the three above, you will get a NULL character.
"how does the compiler know when the array ends ?": the compiler knows how many elements the array has, from its declaration, and this information is available through the sizeof operator.
Anyway C-style arrays have virtually no size, as they are implicitly turned to pointers when passed as arguments, and their length is dropped (IMO a major flaw in the design of the C language). Overflow avoidance is your responsibility.
For this reason, you mustn't use a cout << statement if your string isn't null-terminated.
What is the difference between the line that does not compile and the line that does compile?
The line that does not compile gives this warning: deprecated conversion from string constant to 'char*'
Also, I'm aware casting (char *) on the string being passed in to the function would solve the problem, but I would like to understand why that's even necessary when the 2nd line compiles just fine.
class Student {
public:
Student( char name[] ) {
}
}
int main() {
Student stud( "Kacy" ); //does not compile
char name[20] = "Kacy"; //compiles just fine
}
The char[] signature in the parameter is exactly the same as char*. In C++, it is illegal to convert a string constant char const* (the string "Kacy") to a char* because strings are immutable.
Your second example compiles because the name is an actual array. There is no change to char*.
As a solution, change your parameter to take a const string array:
Student(char const name[]);
which again is the same as
String(char const *name);
though you're better off using std::string:
#include <string>
class String
{
public:
String(std::string name);
};
C++ string literals have type "array of n const char", which decays into const char * in your use case. The implicit conversion to char * (that is, discarding the const) you're trying is deprecated, so there's a warning. Change the type in the constructor's signature or make an explicit const-cast.
From the C++ standard:
An ordinary string literal has type "array of n const char" and static storage duration
The string
"Kacy"
is not an array of characters when the compiler produces the code. Instead, it will stash the string "Kacy" somewhere in memory, and produce a pointer to that place. So what you get is a const char * pointing at the string "Kacy\0".
If you change your constructor to:
Student(const char *nmae)
you can use it both as:
Student stud("Kacy");
and as this:
char name[20] = "Kacy";
Student stud2(name);
Note here that the compiler will generate code to FILL the array name with the characters in "Kacy", which is different from just usinv "Kacy" as an argument to the Student constructor.
I have a bit of a problem with my constructor.
In my header file I declare:
char short_name_[2];
and other variables
In my constructor:
Territory(std::string name, char short_name[2], Player* owner, char units);
void setShortName(char* short_name);
inline const char (&getShortName() const)[2] { return short_name_; }
In my cpp file:
Territory::Territory(std::string name, char short_name[2], Player* owner,
char units) : name_(name), short_name_(short_name),
owner_(owner), units_(units)
{ }
My error:
Territory.cpp: In constructor ‘Territory::Territory(std::string,
char*, Player*, char)’: Territory.cpp:15:33: error: incompatible types
in assignment of ‘char*’ to ‘char [2]’
I already figured out that char[2] <=> char* but I'm not sure how to handle this about my constructor and get/setters.
Raw arrays in C++ are kind of annoying and fraught with peril. This is why unless you have a very good reason to you should use std::vector or std::array.
First off, as others have said, char[2] is not the same as char*, or at least not usually. char[2] is a size 2 array of char and char* is a pointer to a char. They often get confused because arrays will decay to a pointer to the first element whenever they need to. So this works:
char foo[2];
char* bar = foo;
But the reverse does not:
const char* bar = "hello";
const char foo[6] = bar; // ERROR
Adding to the confusion, when declaring function parameters, char[] is equivalent to char*. So in your constructor the parameter char short_name[2] is really char* short_name.
Another quirk of arrays is that they cannot be copied like other types (this is one explanation for why arrays in function parameters are treated as pointers). So for example I can not do something like this:
char foo[2] = {'a', 'b'};
char bar[2] = foo;
Instead I have to iterate over the elements of foo and copy them into bar, or use some function which does that for me such as std::copy:
char foo[2] = {'a', 'b'};
char bar[2];
// std::begin and std::end are only available in C++11
std::copy(std::begin(foo), std::end(foo), std::begin(bar));
So in your constructor you have to manually copy the elements of short_name into short_name_:
Territory::Territory(std::string name, char* short_name, Player* owner,
char units) : name_(name), owner_(owner), units_(units)
{
// Note that std::begin and std::end can *not* be used on pointers.
std::copy(short_name, short_name + 2, std::begin(short_name));
}
As you can see this is all very annoying, so unless you have a very good reason you just should use std::vector instead of raw arrays (or in this case probably std::string).
When a function wants an array as argument, it gets a pointer to the first element of an array instead. This pointer cannot be used to initialize an array, because it's a pointer, not an array.
You can write functions that accept references to arrays as arguments:
void i_dont_accept_pointers(const char (array&)[2]) {}
The problem here is, that this array reference cannot be used to initialize another array.
class Foo {
char vars[2];
Foo(const char (args&)[2])
: vars(args) // This will not work
{}
};
C++ 11 introduced std::array to eliminiate this and other problems of arrays. In older versions, you will have to iterate through the array elements and copy them individually or use std::copy.
C++ as C holds most of the rules of C.
In case of C, always use char* to pass array because that how C looks at it. Even sizeof (short_name_) will be 8 or 4 when passed to function.
Now, you have a space of 2 bytes in variable short_name_
Constructor allocated memory for two bytes in short_name_ and you need to copy the bytes into that or use a char * pointer and assume it's size if 2.
Chapter 9 from Expert C Programming: Deep C Secrets is good read to understand it.
For simplicity this could be C style code.
#include <stdio.h>
#include <iostream>
using namespace std;
class Territory {
private:
string s;
char c[2];
public:
Territory(std::string a, char b[2] /*visualize as char *b*/) {
s = a;
c[0] = b[0]; //or use strcpy
c[1] = b[1];
}
void PrintMe() {
printf ("As string %s as char %c or %s\n",this->s.c_str(), c[0],c);
}
};
main () {
Territory a("hello", "h");
a.PrintMe();
}
Compiler tell me "incompatibles type in assignments of char* to char[32]"
this is my code:
char* generalOperations[2]={"Off","On"};
void test(){
char value[32];
switch(swapVariable){
case 0:
value=generalOperations[0]; //<==Error HERE!
break;
}
}
[Solved]:
strcpy(value,generalOperations[0]);
Use std::string instead of char* and std::array<T, N> instead of T[N]. Both are type safe (as opposed to memcpy), both are in modern C++ style and both are directly assignable using the assignment operator.
#include <array>
#include <string>
std::array<std::string, 2> generalOperations{"Off", "On"};
void test() {
std::string value;
switch(swapVariable) {
case 0: value = generalOperations[0]; break;
}
}
You can't assign arrays. You can either change the type of value to a char* or copy the content of generalOptions[0] into value. If you are going to copy the content, then you need to ensure that value has enough space to hold the content of the element in generalOperations.
Modifying a string literal is undefined behaviour, by changing the type to const char* the compiler can detect any attempt to modify one of the entries in generalOperations instead of experiencing odd behaviour at runtime:
const char* generalOperations [2]={"Off","On"};
const char* value;
Note you don't have to specify the number of elements in the array if you are initialising it:
const char* generalOperations [] = {"Off","On"};
Or, if this really is C++ you can make value a std::string instead and just assign to it which will copy the generalOperations element.
As C++ appears to really be the language and C++11 features are permitted instead of using a switch you could create a std::map that associates the int values with the std::string:
#include <iostream>
#include <string>
#include <map>
const std::map<int, std::string> generalOperations{ {17, "Off"},
{29, "On" } };
int main()
{
auto e = generalOperations.find(17);
if (e != generalOperations.end())
{
// Do something with e->second.
std::cout << e->second << "\n";
}
return 0;
}
Demo: http://ideone.com/rvFxH.
#include <string.h>
...
strcpy(value, generalOptions[0]);
You cannot assign arrays in C/C++. There are functions do to that for you. If your char array represents a C style string (i.e. a null terminated sequence of characters), then there are more specialist functions for that as well. strcpy is one of those functions.
Your assignment is wrong, since you cannot assign a char * to char array instead of using this assignment you can use strcpy().