I hope someone can help me. I'm converting a C language program to C++ in order to easily use strings but when I go to compile, I get this error:
inventory.cpp:225: warning: depreciated conversion from string constant to 'char*'
This is where the code in question:
#define FNAME "database.dat"
// test data struct
struct t_Record
{
int number;
char word[100];
//String word[];
} Record;
int main (void)
{
int Rec = 0; // record number
FILE *File;
srand(time(NULL));
File = FileOpen(FNAME);
if (!File)
{
printf("Error hommie!\n\n");
exit(-1);
}
...etc.
This is where the compiler tells me the error occurred:
File = FileOpen(FNAME);
I just don't see what is wrong...
The place where the compiler tell me to look doesn't even have a string or char associated with it??
Now I understand this error has been seen before, but my question is specific to my code.
The problem is that you are trying to convert a string literal (with type const char[]) to char*.
The place where the compiler tell me to look doesn't even have a
string or char associated with it??
Yes, it is on the top of the file:
#define FNAME "database.dat"
C++ Standard n3337 § 2.14.5/1
String literals
A string literal is a sequence of characters (as defined in 2.14.3)
surrounded by double quotes, optionally prefixed by R, u8, u8R, u, uR,
U, UR, L, or LR, as in "...", R"(...)", u8"...", u8R"(...)", u"...",
uR"* ̃(...)* ̃", U"...", UR"zzz(...)zzz", L"...", or LR"(...)",
respectively.
You can avoid the warning by casting to char*:
File = FileOpen( (char*)FNAME);
Even better modify FileOpen to accept a const char*. This will be more safe and just right as you don't intend to modify the string.
As #lizusek said, you can avoid the warning by type casting to char*, but even better would be to rewrite your code to avoid type casting. While it can work and solve a lot of headaches, it can be very dangerous if you type cast the wrong things.
Related
I have came across a situation as follows and I am getting following warning from the compiler.
Main.cpp:14:22: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
Login(USER,PASSWORD);
Here are the codes
Passwords.h
#define USER "user"
#define PASSWORD "pass"
Main.cpp
#include <iostream>
#include "Passwords.h"
using namespace std;
void Login(char* username,char* password)
{
cout << "UserName is " << username <<endl;
cout << "Password is " << password <<endl;
}
int main()
{
Login(USER,PASSWORD);
return 0;
}
One thing I decided to do was to introduce a global variables in the Passwords.h file. But I really like to know what is the best practice to solve this issue.
I hope no one will mark this as duplicate as same question is asked. I need to eliminate this warning in legitimate way and looking for a best practice as many answers for the same problem gave some hacks to turn off compiler warnings and some casting solutions.
Update
The Login function is actually a virtual function so the parameter datatypes cannot be changed from char * to const char*. I used the specific code segment for simplicity.
But I really like to know what is the best practice to solve this issue.
The best practice is to use pointers/references to const when no modification is made to the pointed object/array. You should make the following change to the parameters:
void Login(const char* username, const char* password)
Conversion from string literal to const char* is well-formed and not deprecated.
the parameter datatypes cannot be changed from char * to const char*
Your requirement excludes the best practice shown above. Given this restriction, you should not pass a string literal to the function. The options left are workarounds. The workaround that I would suggest is to create a local copy of the literal, and pass that instead:
char user[] = USER;
char pass[] = PASSWORD;
Login(user,pass);
PS. Since C++11 the conversion from string literal to char* is not only deprecated, but ill-formed instead. A compiler conforming to the current standard may refuse to compile the program.
PPS. As pointed out in the comments, storing a password within the executable as plain text (which is the way string literals are stored) is dubious from security perspective.
Given that you can't change the function signature to something more appropriate, you're stuck. Bad code forces more bad code.
In this case you need to copy the strings to something that isn't const.
int main()
{
char user[] = USER;
char password[] = PASSWORD;
Login(user,password);
return 0;
}
Just do
void Login(const char* username, const char* password)
While you are on it, replace define with constexpr.
I am trying to print the elements of a set containing strings on graphics.h console using outtext() function,but i get this error:
cannot convert 'std::string {aka std::basic_string}' to 'char*' for argument '1' to 'void outtext(char*)'|
this the piece of code that gives error:
for(i=0;i<20;i++){
for(j=0;j<20;j++){
outtext(str[i][j]);
}
}
the template for the outtext function in the graphics.h header is like this:
void outtext(char *textstring);
i have used c_str() like this:
for(i=0;i<20;i++){
for(j=0;j<20;j++){
outtext(str[i][j].c_str());
}
}
but this time it gives this error:
error: invalid conversion from 'const char*' to 'char*' [-fpermissive]|
You can try this one as well:
char *cstr = new char[21]; // just in case string length is maxed at 20, leave 1 character for '\0'
for (int i = 0; i<20; i++) {
for (int j = 0; j<20; j++) {
strcpy_s(cstr, str[i][j].length() + 1, str[i][j].c_str());
outtext(cstr);
}
}
delete[] cstr;
Just added a char* string to temporarily hold the converted std::string value. The tricky part is that char* strings normally have the terminating character \0 which std::string don't have, so you have to add 1 more character to the size of each "row" of str.
I take it this question is about the 30 years old BGI graphics library and Borland C++. The root of the problem is that this library was poorly written, as it didn't implement const correctness.
The Turbo C++ compiler did not follow anything remotely close to any C++ standard, so you are mostly out of luck. If you had a proper C++ compiler you could use const_cast, but I very much doubt this is available to you.
The only solution left is the dirty, bad way:
outtext((char*)str[i][j].c_str()); // bad practice
You should never cast away const like this in neither C nor C++.
If you can change the prototype of the output function then it is better to change void outtext(char *textstring); to void outtext(const char *textstring); because there is no need for the output function to modifiy the string. Otherwise you could use const_cast before passing to the function like outtext(const_cast<char*>(str[i][j].c_str())) or copy the string to another char* and passed the copied value.
I am getting an error while copying one string to another string using pointers.
#include<iostream>
#include<string>
using namespace std;
void String_copy(char* scr,char* des)
{
while(*scr!='\0')
{
*des= *scr;
scr++;
des++;
}
}
int main()
{
char *str1, *str2;
str1="bharath";
str2="ygftygyfrgtg";
String_copy(str1,str2);
cout<<str1<<endl;
cout<<str2<<endl;
system("pause");
return 0;
}
In below code you have undefined behaviour:
char *str1, *str2;
str1="bharath";
str2="ygftygyfrgtg";
you should assign string literals only to const* char, this also means you should not modify str and str2
you can fix above with:
char str1[] = "bharath";
char str2[] = "ygftygyfrgtg";
but you must also fix String_copy - so that it checks bounds of arrays being modified, ie. add additional parameter with max length of des, also dont forget to add '\0` at the end.
First of all ISO C++ forbids converting string constants to char* pointers.
Try something like this instead to define str1 and str2:
char str1[]="bharath";
char str2[]="ygftygyfrgtg";
Your second problem is the String_copy function, where you just check one of the strings for the terminal \0 character. Also you should add a \0 to the des string (in case it was initially longer):
Something like this will work:
void String_copy(char* scr,char* des){
while(*scr!='\0' && *des!='\0')*des++=*scr++;
*des=0;
}
Note that you can copy maximally up to the length of your shorter string, since you did not allocate more memory anywhere.
Also if it is possible you should use std::string
The two strings are different lengths but you only check for a zero terminator in one of them. Either use strings of equal length or check for the zero terminator in both (and decide what to do with the excess characters).
The problem is that "bharath" is not of type char*.
Its actually a type char const* but the language (for comapability with C) allows auto conversion between the two. If you turn on your warnings (and treat them as errors) this will not even be allowed to compiler:
> g++ -std=c++11 -Wall -Wextra -Werror sc.cpp
sc.cpp:36:10: warning: ISO C++11 does not allow conversion from string literal to 'char *' [-Wwritable-strings]
str1="bharath";
Now (that you have fixed this) you are suffering from the issue that the destination string could be shorter than src. Which will result in the same problem (writing to memory you dont own).
In the following code snippet, I am not able to understand why the error is coming on LineA , but no error in Line B ?
//Global
char strA[80] = "A string to be used for demonstration purposes";
int t=60;
int main(void)
{
strA[80] = "I am trying to modify the source"; //Line A, gives error
t=60; //Line B, no errors
}
The error is:
2 IntelliSense: a value of type "const char *" cannot be assigned to
an entity of type
"char" c:\users\hu\cplustutorial.cpp 69 12 CPLUStutorial
I am not having the char string as const, so why this error?
Compiling with MS VS 2010.
This char strA[80] = "A string to be used for demonstration purposes"; initializes your array.
This strA[80] means a single character within that array. How can you store multiple characters in a single char. Use strcpy to copy the new string.
You are trying to assign the 80th element of strA (which incidentally doesn't exist) with a const char*, not the char[] itself. Also, you tagged the question as C++, so why use char[] instead of std::string?
In C++, the type of a string literal is const char[], not plain char[], so what you are trying to do is illegal by the C++ standard, hence the error you are seeing.
In order to modify the string you will first need to copy it, either using the C library function strcpy or (better) with a std::string.
You have to understand a string of character(string literal) has a type of const char * and you are trying to store it inside a single char(char[80]). Thats why its giving you error.Check this out http://www.stackoverflow.com/questions/20294015/.
I've written the following program to match regular expressions in C++
#include <regex.h>
#include <iostream>
using namespace std;
/*
* Match string against the extended regular expression in
* pattern, treating errors as no match.
*
* return true for match, false for no match
*/
bool match(const char *string, char *pattern)
{
int status; regex_t re;
if (regcomp(&re, pattern, REG_EXTENDED|REG_NOSUB) != 0)
return false;
/* report error */
status = regexec(&re, string, (size_t) 0, NULL, 0);
regfree(&re);
if (status != 0) {
return false; /* report error */
}
return true;
}
int main()
{
string str = "def fadi 100";
bool matchExp = match(str.c_str(), "^[Dd][Ee][Ff][' '\t]+[A-z]+([,])?[''\t]+[0-9]+$");
cout << (matchExp == true ? "Match": "No match") << endl;
}
The program works fine just as expected, but when I compile the code using gcc with the -Wall -Werror arguments (Linux environment), I get a very annoying warning message saying the following:
main.cpp: In function ‘int main()’:
main.cpp:33:90: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
Is there a way to force the compiler to believe that str.c_str() is the same as char * str? if so, how?
No, there isn't. That conversion was deprecated in C++03 and is illegal in C++11; don't do it.
Deprecation of that conversion comes from the fact that string literals are read-only, hence const; accessing them using a pointer to non-const char could possibly lead to modifying const objects, hence invoking undefined behavior. The warning isn't annoying; it is meant to save you from possibly crashing your application - or worse.
Also, you are wrong in reading the warning message; it isn't about c_str(), it is about passing string literal as char *.
The only way to really fix your code is to change second parameter of your match to be const char *, not char *, and copy the passed string to a new, buffer, internal to that function (why not in main()? Because with internal buffer, you have less boilerplate on the caller's side).
I'd also like to suggest totally different solution, since the question is tagged "C++": Boost.Regex.
Is there a way to force the compiler to believe that str.c_str() is the same as char * str?
That's actually not the issue here - you are already passing str.c_str() as a const char*.
The issue is that the second parameter is (also) a string literal, but has type char*. Try changing the second parameter to const char*.
If that still raises errors (due to the regex.h functions not specifying the correct const-ness), you're going to have to do something like this in main() or match():
char pattern[] = "^[Dd][Ee]...etc";
bool matchExp = match(str.c_str(), pattern);
See here for the reason why.
The problem is that a string literal should be only assigned to a pointer of a const char, so you need to change match to take a char const* pattern (which should be possible when you pass a string literal)
Make 2 parameter of function match const char *, warning is because of it