Related
Why my compiler(GCC) doesnt implicitly cast from char** to const char**?
Thie following code:
#include <iostream>
void print(const char** thing) {
std::cout << thing[0] << std::endl;
}
int main(int argc, char** argv) {
print(argv);
}
Gives the following error:
oi.cpp: In function ‘int main(int, char**)’:
oi.cpp:8:12: error: invalid conversion from ‘char**’ to ‘const char**’ [-fpermissive]
oi.cpp:3:6: error: initializing argument 1 of ‘void print(const char**)’ [-fpermissive]
Such a conversion would allow you to put a const char* into your array of char*, which would be unsafe. In print you could do:
thing[0] = "abc";
Now argv[0] would point to a string literal that cannot be modified, while main expects it to be non-const (char*). So for type safety this conversion is not allowed.
#Fred Overflow's link to the FAQ is a complete answer. But (sorry Marshall) it's not the most clear explanation. I don't know if mine is more clear, but I hope so.
The thing is, if p is a char* pointer, then it can be used to modify whatever it's pointing at.
And if you could obtain a pointer pp that points to p, but with pp of type char const**, then you could use pp to assign to p the address of a const char.
And with that, you could then use p to modify the const char. Or, you would think you could. But that const char could even be in read-only memory…
In code:
char const c = 'a';
char* p = 0;
char const** pp = &p; // Not allowed. :-)
*pp = &c; // p now points to c.
*p = 'b'; // Uh oh.
As a practical solution to your code that does not compile, …
#include <iostream>
void print(const char** thing) {
std::cout << thing[0] << std::endl;
}
int main(int argc, char** argv) {
print(argv); // Dang, doesn't compile!
}
just do …
#include <iostream>
void print( char const* const* thing )
{
std::cout << thing[0] << std::endl;
}
int main( int argc, char** argv )
{
print( argv ); // OK. :-)
}
Cheers & hth.,
Note, that although
void dosmth(const char** thing);
int main(int argc, char** argv) {
dosmth(argv);
is forbidden, you can and should do
void dosmth(const char* const* thing);
int main(int argc, char** argv) {
dosmth(argv);
Which is probably what you wanted anyway. The point here is that thing now refers to a const char* array which is itself immutable and which referenced values char are themselves immutable.
So, for a "look at it, but do not change it" scenario, const char* const* is the type to use.
Note: I used the more common (but in my opinion inferior) standard of trying to write the const modifier as left as possible. Personally, I recommend writing char const* const* instead of const char* const* as it is hugely more concise that way.
Because it might allow us to modify a constant value. Read here to understand why: http://c-faq.com/ansi/constmismatch.html
I have a static method inside my class, which I use for a callback.
Inside this callback I want to add a value to result.
This seems not to be possible because of the recast(?).
Is there a way to access the member variable result and add values to it after recasting, or do I need to think of a different way?
MyClass.h
class MyClass
{
public:
vector<string> result;
static int c_CB(void *data, int argc, char **argv, char **azColName);
int Callback(int argc, char **argv, char **azColName);
void Do(string query);
}
MyClass.cpp
void MyClass:Do(string query)
{
sqlite3_exec(this->dbResource, query.c_str(), this->c_CB , NULL, &this->errorMsg);
}
int MyClass::c_CB(void *NotUsed, int argc, char **argv, char **azColName)
{
MyClass* bar = reinterpret_cast<MyClass*>(NotUsed);
// after reinterpret cast, it does not work
//bar->result.insert(bar->result.end(), "foo");
// function call works
return bar->Callback(argc, argv, azColName);
}
int MyClass::Callback(int argc, char **argv, char **azColName)
{
cout << "working" << endl;
}
main.cpp
int main()
{
MyClass* cl = new MyClass();
cl->Do("something");
}
The documentation states that the fourth argument to sqlite3_exec is passed as the first argument of the callback.
Currently you are passing NULL, which you then cast to a MyClass* and attempt access the object, which results in undefined behaviour.
Use this as the fourth argument in place of NULL.
It seems you are trying to access a non-static member function from a static member callback function c_CB.
You were able to call a member function Callback but nothing from the class is accessible, but if I'm correct, the compiler just interpreted Callback as a static function.
If you actually breakpoint inside this function, you can see that none of your member variables actually have a memory address. And the current class, this is null
I'm not sure if the cout << statement still works or if its causing the problem
This is a possible solution to your issue, although it may not be the best one.
class MyClass
{
public:
vector<string> result;
static int c_CB(void *data, int argc, char **argv, char **azColName);
int Callback(int argc, char **argv, char **azColName);
void Do(string query);
void MemberFunction()
{
cout << "working" << endl;
}
static MyClass* currentClass; //Add a static class pointer and assign your class address to it before firing the callback.
}
MyClass* MyClass::currentClass = NULL;
void MyClass:Do(string query)
{
sqlite3_exec(this->dbResource, query.c_str(), this->c_CB , NULL, &this->errorMsg);
}
int MyClass::c_CB(void *NotUsed, int argc, char **argv, char **azColName)
{
MyClass* bar = reinterpret_cast<MyClass*>(NotUsed);
// after reinterpret cast, it does not work
//bar->result.insert(bar->result.end(), "foo");
// function call works
return bar->Callback(argc, argv, azColName);
}
int MyClass::Callback(int argc, char **argv, char **azColName)
{
currentClass->MemberFunction();
}
int main()
{
MyClass* cl = new MyClass();
MyClass::currentClass = this;
cl->Do("something");
}
I want to convert unsigned const char * to char const * for passing into strcpy function
Please suggest some method
(const char *) my_signed_char
In C++ there are more idiomatic ways to cast this, but since you are using strcpy you are not programming idiomatic C++ it seems.
This works for me; is it what you had in mind?
#include <stdio.h>
#include <string.h>
int main(int argc, char ** argv)
{
const char foo[] = "foo";
unsigned const char * x = (unsigned const char *) foo;
char bar[20];
strcpy(bar, (const char *)x);
printf("bar=[%s]\n", bar);
return 0;
}
Note that if you are instead trying to pass the (unsigned const char *) pointer into strcpy's first argument, then you are probably trying to do something you shouldn't (and the compiler is right to flag it as an error); because strcpy() will write into the memory pointed to by its first argument, and a const pointer is a pointer whose data should not be written to.
In ANSI C I believe it should just work e.g.:
#include <string.h>
int main() {
const char *s="test";
unsigned const char *d = s;
char dest[1000];
strcpy(dest,d);
}
You could try adding a cast:
#include <string.h>
int main() {
const char *s="test";
unsigned const char *d = s;
char dest[1000];
strcpy(dest,(const char *) d);
}
I am getting an error while writing a constructor which has some arguments to be passed. Searched previous threads but I am not getting it cleared.
Here is my code :
#include<stdio.h>
#include<iostream>
#include<stdlib.h>
using namespace std;
int curr_state;
//int signal[3],trans_in[7],trans_fin[7],trans_sig[7];
class state_machine
{
private :
int start,end;
public :
state_machine(const int Q[],const int signals[],const int trans[][10][10],const int start,const int end);
// int mystate();
int run();
int get_signal( );
int get_state();
int change_state();
};
state_machine::state_machine(const int Q[],const int signals[],const int trans[][10][10],const int start,const int end)
{
}
int main(int argc, char * argv[])
{
state_machine s;
int Q[5]={1,2,3,4,5};
int signals[3]={0,1,2};
int trans[][3][1]={{1,0,2},{1,1,0},{1,2,0},{2,0,3},{2,1,0},{2,2,0},{3,0,5},{3,1,4},{3,2,2},{4,0,2},{4,1,0},{4,2,0},{5,0,0},{5,1,0},{5,2,0}};
int start=1,end=5;
//s.state_machine(Q,signals,trans,start,end);
}
Getting output as :
state_machine.cpp: In function ‘int main(int, char**)’:<br>
state_machine.cpp:27:16: error: no matching function for call to ‘state_machine::state_machine()’<br>
state_machine.cpp:21:1: note: candidates are: state_machine::state_machine(const int*, const int*, const int (*)[10][10], int, int)<br>
state_machine.cpp:8:1: note: state_machine::state_machine(const state_machine&)
The constructor for state_machine expects an int trans[][10][10]. This must be matched by the type of the trans array in main.
You must change your main to
int main(int argc, char * argv[])
{
int Q[5]={1,2,3,4,5};
int signals[3]={0,1,2};
int trans[][10][10]={{1,0,2},{1,1,0},{1,2,0},{2,0,3},{2,1,0},{2,2,0},{3,0,5},{3,1,4},{3,2,2},{4,0,2},{4,1,0},{4,2,0},{5,0,0},{5,1,0},{5,2,0}};
int start=1,end=5;
state_machine s(Q,signals,trans,start,end);
return 0;
}
Although the initializer list for trans doesn't fit the required type.
Your 3D arrays sizes that you specified needs to match exactly, which it does not. As the error says it is expecting const int (*)[10][10]
if int trans[][3][1] became int trans[][10][10] this error will go away
First of all you cannot create state_machine s; as no body for ctor w/o parameters are available.
Secondly, you need to call last line as state_machine s(Q,signals,trans,start,end);
Thirdly, 3rd parameter passing for ctor is incorrect. for 3d array, indexes should match. make int trans[][3][1] to int trans[][10][10] or vice-versa.
I'm trying to pass a two-dimensional array to the numOfStudents function, but Visual Studio is giving me an error saying:
no instance of overloaded "numOfStudents" matches the argument list
I've been trying everything and I can't find a solution.
#include <stdio.h>
#include <cstring>
//Prototypes
int unsigned numOfStudents(char **namesArray, int *, FILE *);
void printArrays(char **namesArray, int *marksArray, int loopCounter);
int unsigned minMark(int);
int unsigned maxMark(int);
int unsigned averageMark(int);
//Two constants used later to create array of characters
const int MAX_SIZE = 10;
const int NAME_LENGTH = 30;
int main()
{
// Declaring array which will hold all names from file
char namesArray[MAX_SIZE][NAME_LENGTH];
int unsigned studentNumber = 0;
int loopCounter = 0;
int marksArray[MAX_SIZE]; //Array will hold the marks of students, it needs to be same size as the previous array
FILE *file; //creating pointer to a file
file = fopen("names.txt", "r"); //telling the pointer where the file is and how to access it
loopCounter = numOfStudents(namesArray, marksArray, file);
//System pause - will hold console window open
getchar();
return 0;
}
int unsigned numOfStudents(int *marksArray, char **namesArray, FILE *file)
{
char tempArrayName[50]; //Temporary array to hold names
char tempArrayLastName[50]; //Temporary array to hold last names
int i = 0; //Counter
bool stop = false;
if(file == NULL)
{
printf("\nFile has been not opened correctly\n");
}
else
{
while (stop == false)
{
//Reading the file in order to get 3 separate lines which are assumed as a single record of one student
fscanf(file, "%s\n%s\n%d", tempArrayName, tempArrayLastName, &marksArray[i]);
//Following lines are compying strings from temp arrays into main array and adding a space for better readability
strcpy(namesArray[i], tempArrayName);
strcat(namesArray[i], " ");
strcat(namesArray[i], tempArrayLastName);
//Chcecking if the sentinel value was read in order to stop the loop
stop = strcmp(tempArrayName, "****");
i++; //adding the counter
//Checking if file is too big, before program will crash with an internal error
if (i == MAX_SIZE)
{
printf("ERROR!!! FILE TOO BIG TO READ!");
stop == true;
}
}
}
return i;
}
You declare numOfStudents with this argument list:
int unsigned numOfStudents(char **namesArray, int *, FILE *);
But then you define it with a different argument list:
int unsigned numOfStudents(int *marksArray, char **namesArray, FILE *file)
Note that your declaration has the char** as the first argument, but your definition has it as the second argument (and the opposite for the int*). The ordering of the arguments is very important and must match exactly, so you need to change your definition to match the declaration:
int unsigned numOfStudents(char **namesArray, int *marksArray, FILE *file)
{
....
}
2D arrays can be a pain to pass around, why dont you use std::string and pass an array (or reference to std::vector) of them around?
int unsigned numOfStudents(char **namesArray, int *, FILE *); // declaration
int unsigned numOfStudents(int *marksArray, char **namesArray, FILE *file) // definition
Check the order of the parameters in each. The definition's second param is actually declaration's 1st param. You should be good if you rectify the order
You have defined the signature of function numOfStudents as:
int unsigned numOfStudents(char **namesArray, int *, FILE *);
and you declaring the function as :
int unsigned numOfStudents(int *marksArray, char **namesArray, FILE *file)
{
---*** Your Code Here ***---
}
This is the problem that the "sequence of calling parameter" of the signature of the function and the function declaration should be same as the passing parameter. So it should be like :
int unsigned numOfStudents(char **namesArray, int *marksArray, FILE *file)
{
---*** Your Code Here ***---
}