Hi I am working on a project where I access info from a file and then put it into an array of objects then manipulate the data in the object from a options from a menu. The problem I am currently having is that one of the options in the menu is to add a new element to the object. The project states that I must use an array of objects so I can't just use a vector the class that I'm putting the array into to resize it uses a temporary dynamic array for the object then deleting the original array.
Here's what the class looks like
class Info
{
private:
string name;
double money;
public:
Info(){
name="";
money=0;
}
void Setname(string n){
name=n;
}
void Setmoney(double m){
money=m;
}
string GetName()const{
return name;
}
double GetMoney()const{
return money;
}
};
now that was just a sample of the class the actual class has equations with it to alter the money variable but for the purpose of this question this is all that is needed. Now here is the function where I am having the problem
void Addinfo(Info in [], int & size){
string newname;
double newmoney;
cout<<"What name are you going to use?"<<endl;
cin>>newname;
cout<<"Now How much money do you have currently"<<endl;
cin>>newmoney;
Info *temp= new Info[size+1];
for(int index=0; index<size;index++){
temp[index].Setname(in[index].GetName());
temp[index].Setmoney(in[index].GetMoney());
}
delete []in;
temp[size].Setname(newname);
temp[size].Setmoney(newmoney);
in=temp;
size=size+1;
}
Now when I run the program everything runs fine until I try using this function in which the data in the arrays gets corrupts. Am I supposed to make the in Info variable a new dynamic array that can hold the can hold all the info then use another for loop to put the variables into the new dynamic array or I am supposed to do something else. Also remember that I must use arrays for this. Also when deleting a dynamic array am I supposed to make the former array equal to zero after deleting or is that something else?
When you have a function with a type valueName[] array parameter then you just pass the address of that array parameter to the function. The calling function has the ownership of that array. Besides the function signature you always have to consider a contract between the caller and the called function that defines the ownership of the data passed by pointer.
Your function AddInfo gets an array passed by pointer and the calling function expects that the data is available after the function call. So the function violates the contract when you delete []in.
Your function uses a parameter in as (local) variable when you assign a new value with in=temp;. That's legal. But you can't expect that the changed local variable has any effect to the caller. With the current function signature is possible to call the function in this way:
Info infos[5];
Addinfo(&info[3], 2);
Obviously it makes no sense to modify &info[3]. When your contract shall allow adding some data to the array you need a signature that allows changing a pointer. One example would be:
void Addinfo(Info*& in, int& size, string newname, double newmoney)
{
Info *temp= new Info[size+1];
for(int index=0; index<size;index++){
temp[index].Setname(in[index].GetName());
temp[index].Setmoney(in[index].GetMoney());
}
temp[size].Setname(newname);
temp[size].Setmoney(newmoney);
delete []in;
in = temp;
size=size+1;
}
void Addinfo(Info*& in, int& size)
{
string newname;
double newmoney;
// input data
cout<<"What name are you going to use?"<<endl;
cin>>newname;
cout<<"Now How much money do you have currently"<<endl;
cin>>newmoney;
// TODO: data validation.
// add data to array
Addinfo(in, size, newname, newmoney);
}
I have factored out the change of the array from the input. This allows a more simple testing of that function.
Related
I need to create a matrix calculator, for that I think the best is to create functions for +,-,*,/.
But a lot of troubles come with this idea.
I create a calloced array like:
int **matrix = NULL;
matrix=calloc(cols,sizeof(int*));
for(int i=0;i<cols;i++) {
matrix[i]=calloc(rows,sizeof(int*));
}
For now I want to create a function where I want to work with this array.
void addition(int **array,int rows, int cols){
// ** some algoritm here**
return (the result of addition stored in 2D array);
}
I also tried to google the problem, but I didn't underestand the solutions. What I need to explain the way how to pass the array to function, just for reading.
After that I need to return some pointer to new array created as the result of addition. I will probably create the new array in the function.
But If I wanted to write something in array created in main, how to pass and use it in the function?
I'm new to using smart pointers, I'm trying to create the same but I have errors.
class data{
private:
int ID;
public:
void setID(int a){
ID=a;
}
int getID(){
return ID;
}};
int main(){
data d*;
d=new data[30];
for(int i=0;i<30;i++){
(p+i)->setID(i);
}}
I try with:
shared_ptr<data> sp( new data[30]);
for(int i=0;i<30;i++){
sp->setID(i)[i];
}
Error:invalid types 'void[int]' for array subscript|
shared_ptr<data> sp( new data[30]);
for(int i=0;i<30;i++){
(sp+i)->setID(i);
}
Error: No match for 'operator+' (operand types are 'std::shared_ptr' and 'int')|
how can i do the same?
The issue is you're trying to add i to sp, instead of to the pointer that is managed by sp. What you want to do is use get() to get the stored pointer first:
for (int i = 0; i < 30; i++) {
sp.get()[i].setID(i);
}
If you use C++17, there's also operator[] which you could use.
However, you've got another problem (and operator[] wouldn't work because of it). You are storing the result of new[] in a std::shared_ptr which expects to manage a pointer returned by new. Your construction of sp should actually be:
std::shared_ptr<data[]> sp(new data[30]);
Otherwise you'll get undefined behavior, because sp is going to call delete on the address returned by new data[30], whereas it needs to use delete[]. Here's a bunch more info about the constructors of std::shared_ptr.
Side notes:
Please provide a minimal, complete, and verifiable example for your questions.
Are you sure you need std::shared_ptr? Won't std::unique_ptr work? std::unique_ptr is basically as fast as a raw pointer, whereas std::shared_ptr is slower.
I have my own implementation of C hash_map_t struct that I can use as below?
// string value allocator
allocator_t *str_value_allocator;
allocator_init(&str_value_allocator, string_allocate_handler, string_deallocate_handler);
str_hash_map_init(&str_hash_map, str_value_allocator, 5);
str_hash_map_put(str_hash_map, test_key, test_val, strlen(test_val));
str_hash_map_get(str_hash_map, test_key, NULL)
str_hash_map_remove(str_hash_map, test_key)
str_hash_map_free(str_hash_map);
I would like to use this hash map in function like below:
void handle_keyboard_input(char **tokens, size_t num_tokens) {
char *virtual_key_name = strtok(tokens[1], " ");
size_t num_flags = 0;
char **modifier_flags = str_split(tokens[2], ", ", &num_flags);
// map virtual_key_name (char *) to virtual_key code (int)
// foreach modifier flag (char *) map to modifier flag code (int)
}
I can create 2 hash_maps for key_name -> key_code mapping and flag_name -> flag_code mapping. The problem is that I don't want to create this flag each time the request handler function is called but have only one data structure instance from first call of the function and in successive function invocations I want to reuse this data structure (data store) already created.
My hash_map is created on the heap so there isn't possibility to allocate it like the array somewhere inside library source code file.
In Java or even C++ I could create some Singleton pattern or static member but such concept is not available in C language. Probably I could create this hash_map at program startup somewhere at the beginning of program but how could I pass reference to library used by the program.
My recent idea was to use static hash_map_t variable inside my handle_keyboard_input function and somehow initialised it only when it is NULL (the first function call), and if variable isn't NULL in successive calls just reuse previously initialised hash_map_t structure.
What will be the best approach to this problem?
UPDATE
Could I use such code?
static str_hash_map_t *virtual_keys_map = NULL;
static str_hash_map_t *modifier_flags_map = NULL;
if (virtual_keys_map == NULL) {
virtual_keys_map_init(&virtual_keys_map);
}
if (modifier_flags_map == NULL) {
modifier_flags_map_init(&modifier_flags_map);
}
Since this appears to be a library, you have several options:
You can make your library more "object oriented" and force the user to do the proper instantiation. For example, you would have your ADT struct defined as KeyboardHandler, and then your handle_keyboard_input would look something like this instead:
void KH_handle_input(KeyboardHandler self, char **tokens, size_t num_tokens);
Which means the caller is now responsible for doing the instantiation of that single part:
// caller must get the ADT instance at some point, and you don't care when
KeyboardHandler kh = KH_init();
KH_handle_input(kh, some_tokens, num_tokens);
// some other part can be initialized later
MouseHandler mh = MH_init();
MH_handle_input(mh, some_tokens, num_tokens);
It's possible to create a library initializer for both Windows and POSIX dlls. So you can let this be done automatically instead.
Otherwise, it seems like you will have to make this "check" anytime your functions want to use this potentially-uninitialized hash tables (perhaps it's a single function, but anyway). In which case, I would at least refactor it into a separate function:
void handle_keyboard_input(char **tokens, size_t num_tokens) {
initialize_hashes_if_needed();
// ...and then the rest of the function
}
The reasoning is that you don't want to have to modify several functions if you decide there is something else that needs to be malloced.
Yes, code above cause that pointers will be initialised just once (or if you set them to NULL, condition will be true and it will init again) and stay in memory even if you get outside of function.
The lifetime of function static variables begins the first time the program flow encounters the declaration and it ends at program termination - in other words they are global variables.
Also the name of this variable is only accessible within the function, and has no linkage.
Still need to take great care if you think you need a globally-accessible variable. Read here.
static str_hash_map_t *virtual_keys_map = NULL;
static str_hash_map_t *modifier_flags_map = NULL;
if(virtual_keys_map == NULL) {
virtual_keys_map_init(&virtual_keys_map);
}
if(modifier_flags_map == NULL) {
modifier_flags_map_init(&modifier_flags_map);
}
I have a structure of structures which is global. I am using functions to change the data of the structure.
In general I manipulate the structure easily (e.g. send it to a function).
My problem is that now I have a function that changes the data of the structure, but it also has to call another function. And this is my problem.
In general my structure is the: "name".
I have a pointer: name_ptr->name[i]....
In case of a function I am passing it like this:
find_max = calc_max(i, &name_ptr);
and this function id declared as:
int find_max(int x, vectname **pr)
So inside the function I am working like this:
(*pr)->name[i]...
If I am into the function and I want to sent this pointer to another function how can I call it?
In simple words you have an array of structures and to your first function you get the pointer to the array.
So either you can use:
int find_max(int x, vectname **pr)
{
// method - 1 (if your second function is intreseted only in changing the nth structure instance of the array )
SecondFunc( &pr[n]);
// method - 2 (if your second function is intreseted in changing the any structure instance of the array )
SecondFunc( pr );
}
Your question is quite cryptic but i'll give it a shot:
int find_max(int x, vectname **pr)
{
...
another_function(x, pr);
...
}
I have multiple void functions that relies on the each individual output of the functions since there are multiple variables (that are the same throughout the code), where each functions' output will be "stored" to them and be passed to another.
So, I decided to make those variables into global variables by making them static .... right after all the necessary #include... codes.
I was able to utilize all functions (14 functions in total,all void) by only calling four of them (Each functions, after processing its own function, passes the result into another function and after series of passing, only four of them are needed to be called in int main())
Now, I created another void function that requires the global variables as its parameter since that void function relies on the data that all the other functions "copied and put" into the global variables declared earlier. (Which I found is not working, since I heard that storing data into global variables is not possible.)
Can anyone teach me if there is any other way to create series of functions which requires output of each individual functions?
I checked if the variables were stored properly, so I tried using printf method right after the #3 process. I found out nothing gets printed when I expected a value from the struct data to be printed.
Ex:
typedef struct database{
//... variables
}data;
typedef struct itembase{
//... variables
}item;
static data user1;
static data user2;
static data *pointer[10000];
static item *pointer2[10000];
static item current[10000]; //Shares same value of the bracket with *pointer2
static data sectionA[1][10000];
static data sub_section[3][10000];
static int datacounter = 0; //..will be put inside the bracket of *pointer
static int itemcounter = 0; //..will be put inside the bracket of *pointer2
static int typenum = 0; ..will be put inside the first bracket of all the sections and subsections
static int section_count = 0; //..will be put inside the second bracket of all sections
static int sub_section_count[3] = {0}; //..will be put inside the second bracket of all sub_sections. The [3] will be the value of the typenum.
void load_data() // Accepts User's input and store them into struct data's variable using singly-linked list
{
//.... All data will be stored to *pointer[datacounter]
binarycheck(pointer[datacounter]->encoding,*pointer,datacounter);
//.... The `typedef struct` of data contains 12 variables. After storing 12 variables, datacounter will be ++ and the program will still continue to accept input from the user
}
void load_item()
{
//.... All item will be stored to *pointer2[itemcounter]
memcpy(¤t[itemcounter],pointer2[itemcounter],sizeof(item));
}
void binarycheck(data encoding,data *pointer,int datacounter)
{
if ((encoding&128)==128){
typenum = 3;
memcpy(§ionA[typenum][section_count],pointer,sizeof(data));
sub_sectionA[typenum][sub_section_count[typenum]] = sectionA[typenum[section_count];
section_count++;
sub_section_count++;
}
}
void askitem(data user)
{
// Tried putting `printf(" %s User1 Data#1",user1.firstdata);` and it works perfectly fine.
// Ask for user's selection on item
// If the item is found, then the content of that item will modify the data of the variable of `user`
}
void askinput(data user)
{
int whattype = 0;
int whatsub = 0;
printf("What type do you want?: \n);
scanf("%d",&whattype);
if (whattype == 1)
{typenum = 1;}
printf("What Sub type do you want?: \n);
scanf("%d",&whatsub);
if (whatsub == 1)
{ user = sub_sectionA[typenum][sub_section_count[typenum]];}
askitem(user);
}
void final_print(data user, data user2)
{
printf("%d\n",user.Adata);
printf("%d\n",user2.Adata);
}
int main()
{
load_data();
load_item();
askinput(user1);
//Tried putting `printf(" %s User1 Data#1",user1.firstdata);` but nothing shows.
askinput(user2);
//Nothing shows
final_print(user1,user2); //Nothing shows
}
Take a look at this function:
void askinput(data user)
Here you pass user by value to the function. When you pass by value, the function receives a copy of the variable. Changes that you make inside the body of that function only affect the copy. They are not visible to the caller's variable.
Instead you need to pass a reference. In C that means passing a pointer to a variable:
void askinput(data *user)
Inside the body of the function you need to de-reference the pointer to access members. So you use -> rather than . to refer to members.
And when you call the function you need to pass a pointer to the variable. So the call becomes:
askinput(&user1);
Frankly I do not understand why you are using global variables here at all. It's generally preferable to pass parameters otherwise you do find yourself struggling to keep track of which different version of the variable you are meant to be working on.
Finally, you have written your entire program and trying to debug this specific problem in the context of the entire program is confusing you. You really should have cut this down to a 10 or 20 line simple reproduction. Being able to do that in the future will make life much easier for you.