I want to do something with string using the index and rindex function under c++17, but when I compile the program, this error poped up:
debug.cpp: In function ‘int main()’:
debug.cpp:7:27: error: invalid conversion from ‘const char*’ to ‘char*’ [-fpermissive]
7 | char* index_first = index(str,'c');
| ~~~~~^~~~~~~~~
| |
| const char*
debug.cpp:9:27: error: invalid conversion from ‘const char*’ to ‘char*’ [-fpermissive]
9 | char* index_last = rindex(str,'c');
| ~~~~~~^~~~~~~~~
| |
| const char*
Then I checked this program online, every function defines of index and rindex I saw are the same:
char* index(const char* s,int c);
char* rindex(const char* s,int c);
And heres my debug code:
#include <stdio.h>
#include <string.h>
int main()
{
const char* str = "abcdefgabcdefg";
char* index_first = index(str,'c');
printf("the first index is %ld\n",index_first - str + 1);
char* index_last = rindex(str,'c');
printf("the last index is %ld\n",index_last - str + 1);
return 0;
}
I compile it using:
g++ -o debug debug.cpp -std=c++17
I want to know why can't I do that and the right way to use index and rindex functions and (or) the right function defines please.
Heres my environment:
Ubuntu LTS 20.04 (x64)
g++ (Ubuntu 9.4.0-1ubuntu1~20.04.1) 9.4.0
Thank you for all the help.
You are trying to assign returned pointers of the type const char * that are used within the functions to pointers of the type char *
Actually the functions you are calling are declared like
const char* index(const char* s,int c);
const char* rindex(const char* s,int c);
In C++ the functions can be overloaded like
const char* index(const char* s,int c);
const char* rindex(const char* s,int c);
and
char* index(char* s,int c);
char* rindex(char* s,int c);
the same way as some other standard C functions as for example the standard C function strchr.
So you should write
const char* index_first = index(str,'c');
printf("the first index is %td\n",index_first - str + 1);
const char* index_last = rindex(str,'c');
printf("the last index is %td\n",index_last - str + 1);
The result of subtracting two pointers has the signed integer type ptrdiff_t. So you need to use the conversion specifier %td instead of %ld.
From the C Standard (7.21.6.1 The fprintf function)
7 The length modifiers and their meanings are:
t Specifies that a following d, i, o, u, x, or X conversion specifier applies to a ptrdiff_t or the corresponding unsigned integer
type argument; or that a following n conversion specifier applies to a
pointer to a ptrdiff_t argument.
Related
I can run my program in codeblock or visual studio 2015 but it doesn't work in visual studio 2017
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <string>
using namespace std;
void replacechar(char *filenguon, char ktc, char ktm)
{
fstream fs(filenguon, ios::in | ios::out);
if (!fs)
cout << "khong the tim thay" << endl;
else
{
char ch;
while (fs.get(ch))
{
if (ch == ktc)
{
int pos = fs.tellg();
pos--;
fs.seekp(pos);
fs.put(ktm);
fs.seekg(pos + 1);
}
}
}
}
int main()
{
replacechar("caua.txt", 'r', 'R');
return 0;
}
Error:
Error C2664 'void replacechar(char *,char,char)': cannot convert argument 1 from 'const char [9]' to 'char *'
Error (active) E0167 argument of type "const char *" is incompatible with parameter of type "char *"
Warning C4244 'initializing': conversion from 'std::streamoff' to 'int', possible loss of data
I can run my program in codeblock or visual studio 2015 but it doesn't work in visual studio 2017
Change
void replacechar(char *filenguon, char ktc, char ktm)
to
void replacechar(const char *filenguon, char ktc, char ktm)
The rules about string literals changed in C++11 (I think). They are const data and so any function parameter to which you pass a string literal should be declared with const.
And, as stated in the comments, change
int pos = fs.tellg();
to
auto pos = fs.tellg();
The return from tellg is not an int, by using auto you are asking the compiler to use the correct type, whatever that is.
You are not allowed to pass a const char* (in your case the string literal "caua.txt" to a function accepting a non-const char*.
Change your signature to void replacechar(const char *filenguon, char ktc, char ktm).
Two methods:
1.
void replacechar(const char *filenguon, char ktc, char ktm)
{
//TODO
}
2.
char str[]={"caua.txt";};
replacechar(str, 'r', 'R');
that should be work, "caua.txt" is const char*,it change to char* by copy one by one or const_cast<char*>
I get the following error when declaring a function:
Users/masterprogrammer/PycharmProjects/WolvesBatsRocks/c++/c++example.cpp:23:5: error: no matching function for call to 'printstats'
printstats(&x, y);
^~~~~~~~~~
/Users/masterprogrammer/PycharmProjects/WolvesBatsRocks/c++/c++example.cpp:10:6: note: candidate function not viable: no known conversion from 'const std::string *' (aka 'const basic_string<char, char_traits<char>, allocator<char> > *') to 'const std::string' (aka 'const basic_string<char, char_traits<char>, allocator<char> >') for 1st argument; remove &
void printstats(const std::string& x, int statnum);
^
/Users/masterprogrammer/PycharmProjects/WolvesBatsRocks/c++/c++example.cpp:12:6: note: candidate function not viable: no known conversion from 'const std::string *' (aka 'const basic_string<char, char_traits<char>, allocator<char> > *') to 'char *' for 1st argument
void printstats(char * x, int stat_num)
^
1 error generated.
[Finished in 0.9s with exit code 1]
[shell_cmd: g++ "/Users/masterprogrammer/PycharmProjects/WolvesBatsRocks/c++/c++example.cpp" -o "/Users/masterprogrammer/PycharmProjects/WolvesBatsRocks/c++/c++example" && "/Users/masterprogrammer/PycharmProjects/WolvesBatsRocks/c++/c++example"]
[dir: /Users/masterprogrammer/PycharmProjects/WolvesBatsRocks/c++]
[path: /anaconda3/bin:/Library/Frameworks/Python.framework/Versions/3.6/bin:/Library/Frameworks/Python.framework/Versions/3.5/bin:/Library/Frameworks/Python.framework/Versions/3.6/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin]
The function takes two inputs and I am calling it from main.
I am expecting an output which has the following formatting Strength: 7.
Here is the code:
// C program to illustrate
// call by value
#include <stdio.h>
#include <iostream>
#include <ctime> // For time()
#include <cstdlib> // For srand() and rand()
#include <string>
#include <cstring>
void printstats(const std::string& x, int statnum);
void printstats(char * x, int stat_num)
{
printf("%s: %d", x, stat_num);
}
int main(void)
{
const std::string&x = "Strength";
int y = 7;
// Passing parameters
printstats(&x, y);
return 0;
}
Your function prototype void printstats(const std::string& x, int statnum) and function definition void printstats(char * x, int stat_num) expect different parameters.
One expects a const string & as the first parameter and the other expects a char * as the first parameter.
Change both to have the same parameters and make sure your function call passes the appropriate argument(s) to the function.
You can't define an address type, but instead you can pass addresses of other variables which I think neither is what you're aiming to do.
& in method signature means call by reference which basically means inside the function the reference is used to access the actual argument used in the call.
To make it work, define a string and pass it directly.
std::string x= "Strength";
int y = 7;
printstats(x, y);
You really need to read a good introductory C++ book. It seems that you took an example from a C book, and tried to use it in C++ without understanding of what's happening.
I removed the unnecessary includes:
#include <stdio.h>
#include <string>
//Use a reference to string object instead of char pointer
void printstats(const std::string& x, int stat_num)
{
//printf is a C function that expects a C char* straing,
//so we need to convert the C++ string into it
printf("%s: %d", x.c_str(), stat_num);
}
int main(void)
{
//no need for "&" here - it's totally incorrect.
//It is an operation of taking an address of a variable.
const std::string x = "Strength";
int y = 7;
//no need for & here too
printstats(x, y);
return 0;
}
Output:
Strength: 7
Where am doing wrong in this code? I need only in char types, please don't suggest to use std::string.
#include <iostream>
#include <string.h>
using namespace std;
int main()
{
char *mystring="C:/windows";
char last_char;
last_char = mystring[strlen(mystring)-1];
cout<<"Input: " <<mystring<<endl;
if(strcmp(last_char,";")!=0)
{
strcat(mystring,";");
}
cout<<"Output: "<<mystring<<endl;
return 0;
}
Output:
Compilation error time: 0 memory: 3340 signal:0
prog.cpp: In function ‘int main()’:
prog.cpp:7:17: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
char *mystring="C:/windows";
^
prog.cpp:11:25: error: invalid conversion from ‘char’ to ‘const char*’ [-fpermissive]
if(strcmp(last_char,";")!=0)
^
In file included from prog.cpp:2:0:
/usr/include/string.h:140:12: error: initializing argument 1 of ‘int strcmp(const char*, const char*)’ [-fpermissive]
extern int strcmp (const char *__s1, const char *__s2)
Don't use strcmp, it expects a null terminated characters sequence. Instead, use direct comparison:
if (last_char == ';') ...
Also, your code invokes undefined behavior in the strcat() call. my_string was initialized with a string literal, thus, you are not allowed to modify it, since the implementation is free to place it in read-only memory (and typically will do so).
You can declare it like this instead:
char mystring[12] = "C:/windows"; // space for one more char
last_char is not a string. It is a character. You can't compare a char with string.
Try this instead
if (last_char == ';') {...}
Statement
strcat(mystring,";");
invokes undefined behavior. You can't modify a string literal as it resides in read only section of the memory.
While adding a detailed answer, I noticed that GCC does not warn the following code while Visual C++ complains.
#include <cstring>
int main()
{
const char CONSTSTR[] = "foo/bar/foobar.txt";
char *nonconst = std::strrchr (CONSTSTR, '/');
// cannot convert from 'const char *' to 'char *'
*nonconst++ = 'B';
*nonconst++ = 'A';
*nonconst++ = 'D';
}
I have tested three different GCC versions:
4.1.2 on Red Hat (Linux)
4.5.3 on Cygwin (Windows)
4.7.2 on MinGW (Windows)
But all these three GCC versions compiled this code without any warning/error:
> g++ -Wall -Wextra -pedantic -ansi test.cpp && echo "success"
success
While Microsoft compiler v16 complains:
> cl -c test.cpp
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.30319.01 for 80x86
Copyright (C) Microsoft Corporation. All rights reserved.
test.cpp
test.cpp(5) : error C2440: 'initializing' : cannot convert from 'const char *' to 'char *'
Conversion loses qualifiers
(from my office, I do not have access to ideone/codepad/... to test it using other versions)
As this code uses std::strrchr, I do not understand why GCC does not complain.
const char* strrchr( const char* str, int ch ); //the code above uses this declaration
char* strrchr( char* str, int ch );
My question: Why does g++ successfully compile this code without any warning/error? Is it a bug? a feature? a miss-configuration on my side?
Actually your g++ does not accept the conversion from 'const char *' to 'char *', it's just that on your version std::strrchr() returns a char* (incorrectly, instead of a const char*).
To verify the first part of my statement, try to compile the following on your GCC versions, I predict that all will correctly issue an error:
int main()
{
const char* p = "foo";
char* q = p; // error, invalid conversion from 'const char*' to 'char*'
}
Now for the second part, I tried to compile the following minimal code, whose actual aim is to trigger an error in order to list the declared overloads of std::strrchr:
#include <cstring>
void (*p)() = &std::strrchr; // error here, with "candidates are: ..."
int main() {}
Well, with gcc 4.7.2 the message shows the expected "all non-const" and "all const" overloads:
prog.cpp:2:21: error: no matches converting function ‘strrchr’ to type ‘void (*)()’
In file included from /usr/include/c++/4.7/cstring:44:0,
from prog.cpp:1:
/usr/include/string.h:249:1: error: candidates are: char* strrchr(char*, int)
/usr/include/string.h:255:1: error: const char* strrchr(const char*, int)
i.e. the prototypes
char* strrchr( char* , int );
const char* strrchr( const char* , int ); // Question's code will use this one (-> error)
But with gcc 4.3.2 the message was different:
prog.cpp:2: error: no matches converting function 'strrchr' to type 'void (*)()'
/usr/include/string.h:171: error: candidates are: char* strrchr(const char*, int)
/usr/include/c++/4.3/cstring:118: error: char* std::strrchr(char*, int)
i.e. the overloads were
char* strrchr( const char* , int ); // Question's code would use this one (-> no error...)
char* strrchr( char* , int );
(the second one is the C++ non-const overload; but the first one is the old C version, and should instead be the C++ const overload).
This it seems that the headers (<cstring> and/or <string.h>) were incorrect on this version, and I suspect that it's the same on yours.
Edit: I found for example a discussion, a blog post and a bug report (for strchr not strrchr but it's the same story).
This question already has answers here:
invalid conversion from ‘const char*’ to ‘char’
(2 answers)
Closed 6 years ago.
#include<stdio.h>
#include<iostream>
#include<fstream>
#include<string.h>
using namespace std;
class base {
public:
int lookup(char c);
}; // class base
int base::lookup(char c)
{
cout << c << endl;
} // base::lookup
int main() {
base b;
char c = "i";
b.lookup(c);
} // main
On Compiling above code I am getting below error :
g++ -c test.cpp test.cpp: In function ‘int main()’: test.cpp:20:10:
error: invalid conversion from ‘const char*’ to ‘char’ [-fpermissive]
Try replacing
char c = "i";
with
char c = 'i';
"i" is not a character, it's a character array that basically decays to a pointer to the first element.
You almost certainly want 'i'.
Alternatively, you may actually want a lookup based on more than a single character, in which case you should be using "i" but the type in that case is const char * rather than just char, both when defining c and in the base::lookup() method.
However, if that were the case, I'd give serious thought to using the C++ std::string type rather than const char *. It may not be necessary, but using C++ strings may make your life a lot easier, depending on how much you want to manipulate the actual values.
"i" is a string literal, you probably wanted a char literal: 'i'.
String literals are null terminated arrays of const char (which are implicitly converted to char const* when used in that expression, hence the error).
char literals are just chars