I want to pass a struct array into a function, however, there's something wrong with how I'm passing it and I cant figure out what. I'll include the relevant code.
The Struct:
typedef struct fitbit
{
char patient[10];
} FitbitData;
Main.c:
FitbitData* data = (FitbitData*)malloc(sizeof(data) * 1450);
count = storeToksInArray(line, count, data);
function:
int storeToksInArray(char line[], int count, FitbitData* data[])
{
strcpy(data[count]->patient, strtok(line, ",")); //name
puts(data[count]->patient); }
I've already tested my code and there aren't any problems with line or count. The array works fine in my main file, but once I pass it into the function I can't get it to store the data correctly. The strcpy and puts functions work fine in main as well, so I'm 90% sure it's how I'm passing the array into the function and then using it in the function. I can also use the strtok and puts functions fine by themselves in the function, but once I try storing the token in the array, it doesn't work.
Edit: I figured it out! I removed the brackets after FitbitData data[] to get FitbitData data and then change -> to .**
int storeToksInArray(char line[], int count, FitbitData* data[])
The expression FitbitData* data[] means data is an array of pointers to FitbitData. You seem to be wanting instead a pointer to an array of FitbitData. But an array type is effectively a pointer, so you don't need to pass a pointer to it. Consider changing your function declaration to:
int storeToksInArray(char line[], int count, FitbitData data[])
It appears that data is a FitbitData pointer, and yet your function is expecting an array of FitbitData pointers. Perhaps what you want is either:
int storeToksInArray(char line[], int count, FitbitData* data)
or
int storeToksInArray(char line[], int count, FitbitData data[])
Both are equivalent in this context, it's a question of which you prefer or which seems clearer to you. Personally, I prefer the first one.
Related
I am having problems accessing a matrix and vector with variable size using malloc() realloc() functions in a subalgorithm. I have tried the following but it doesn't seem to work.
int main()
{
char nombre[50];
sprintf(nombre,"data.txt");
int **red;
int *links;
int i, j, colSize;
links = (int*)malloc(Nred*sizeof(int));
red = (int**)malloc(Nred*sizeof(int*));
for(i=0; i<Nred; i++)
{
red[i]=(int*)malloc(1*sizeof(int));
}
LeeRed(*red, *links, Nred, nombre, &colSize);
}
void LeeRed (int ***mat, int **links, int nNodes, char *nombre, int *colSize)
{
int i, j, maxSize, nodo1, nodo2;
FILE *f, *g;
f=fopen(nombre,"rt");
g=fopen("matrizPrueba.txt", "w");
maxSize=0;
/// Number of links per node starts at 0
for(i=0; i<nNodes; i++)
{
*links[i]=0;
}
//...
}
First things first, * is the dereference operator, not the create reference operator. When you pass your matrix and links to your function, you should use & instead. For example:
LeeRed(&red, &links, Nred, nombre, &colSize);
This will make all of your types match. I would be shocked if your compiler didn't warn you about this (if it's not, try recompiling with -Wall). That being said, you really shouldn't be passing a pointer to your matrix unless you plan on modifying the pointer to your matrix. You might want to do this if you were planning on reallocating the matrix for some reason, but in the function above just make your life easier and pass the pointers by value. So change your function signature to:
void LeeRed (int **mat, int *links, int nNodes, const char *nombre, int *colSize);
Also, when you access an array with a pointer, you do not need to dereference it first, so you can use links[i] instead of *links[i]. And be careful with your allocations, right now you have an Nredx1 matrix allocated, but if you reallocate any of those columns without freeing them, you'll have a memory leak on your hands. Be sure to free everything you allocate (from the bottom up, calling free(red) will not free the columns, you must do those individually).
I'm also not sure what the links variable is intended to do, but it may be redundant if you're just trying to read into a matrix. I can't help you any further without more context.
The types of the first two parameters don't match what you're passing in.
red has type int ** and links has type int *, and you're passing *red and *links which have types int * and int respectively. This differs from the int *** and int ** types that your function is expecting for these parameters.
You're also calling the function before it's been defined or declared, so it has an implicit declaration of int LeeRead() which doesn't match the actual definition.
You should pass these two parameters directly without dereferencing:
LeeRed(red, links, Nred, nombre, &colSize);
Change the parameter types to match:
void LeeRed (int **mat, int *links, int nNodes, char *nombre, int *colSize)
Change how these two parameters are used in the function accordingly, and move the function's definition to above main.
The function readFile(filename) reads the contents of the file and stores it in heap using malloc, it returns char* datatype. I want to store the content in an array in main so that I can count the words. How do I do so? This is the code:
int main()
{
char *char1;
char1 = readFile("test1.txt");
printf("%s", char1[0]); //This does not print anything
CountWords(*char1, &Alpha, &SentChk, &punct, &Words, &totalSents, &onlyVowel_e);
/*function header of CountWords: void CountWords(char ch, int *Alpha, int *SentChk, int *punct,
int *Words, int *totalSents, int *onlyVowel_e);*/
printf("%d", Words);
printf("%d", totalSents);
return 0;
}
When you call "Countwords", your arguments cant be seen by the main as they arent defined there. Even if you use them in your other funtion - this is a different scope. Maybe you could return a char*[] holding these paramaters you want to return. Or better yet, define all of those arguments in main, have your first function pass them "by reference". This way you have the values put in a place where you can access them later for your "Counwords"
Since C does not support pass by reference, and I'm developing something that cannot use heap memory, how can I make this work? I want the function call set_var_name to actually change the variables global_log instead of just a local copy. Thanks
#include <stdio.h>
struct Record
{
char type[1];
char var_name[1014];
void* var_address;
char is_out_dated[1];
};
struct Global_Log
{
struct Record records[1024];
int next_slot;
};
void set_var_name(struct Global_Log global_log, int next_slot, char* data, int size)
{
for(int i = 0 ; i < size; i++)
global_log.records[0].var_name[i] = data[i];
printf("%s\n",global_log.records[0].var_name);//here prints out "hello"
}
int main()
{
struct Global_Log global_log;
char a[6] = "hello";
set_var_name(global_log, 0, a, 6);
printf("%s\n",global_log.records[0].var_name); // here prints out nothing
return 0;
}
It seems that you are working with a copy of the struct instance, instead of a reference. Try passing a pointer of a struct as a parameter, so you can work with a reference of the instance:
void set_var_name(struct Global_Log* global_log, int next_slot, char* data, int size)
Another alternative is using a global variable, since it sounds like there won't be another instance of it.
C is a call-by-value language -- when you call a function, all arguments are passed by value (that is, a copy is made into the callee's scope) and not by reference. So any changes to the arguments in the function only affect the copy in the called function.
If you want to call "by reference", you need to do it explicitly by passing a pointer and dereferencing it in the called function.
I want to write and print some strings in a 2d array in a struct. The struct is called Router and it is in a header file, the 2d array is defined in that struct and it's called **addTab. When I try to print one line of the array using the function viewTable the program stopped working... why?
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "router.h"
#define N 8
#define M 3
#define sizeMess 5
Router *createRouter(){
Router *NewRouter=(Router*)malloc(sizeof(Router));
int i;
NewRouter->addTab=(char **) malloc(N*sizeof(char *));
for(i=0;i<N;i++)
NewRouter->addTab[i]=(char *) malloc(M*sizeof(char));
return NewRouter;
}
void viewTable(Router *r, int a){
int i,j;
for(i=0;i<N;i++){
for(j=0;j<M;j++){
printf("raw\t col\t address\t value\t\n");
printf("%d\t %d\t",i,j);
printf("%p\t",&r->addTab[i][j]);
printf("%s\t\n",r->addTab[i][j]);
}
}
}
void updateTable(Router *r, int conn, char *addr1, char *addr2){
r->addTab[conn][1]=addr1;
r->addTab[conn][2]=addr2;
}
First off: Don't cast the result of malloc.
Assuming that you want to store char* pointers in your 2D array (as the title of your question says), you will need to define it as char *** in your Router structure, like this:
typedef struct router {
char ***addTab;
} Router;
Next, you will need to change your createRouter function, so that it can store an array of char* pointers, instead of a single byte for each element, like so:
Router *createRouter(){
Router *NewRouter=malloc(sizeof(Router));
int i;
NewRouter->addTab=malloc(N*sizeof(char **));
for (i=0;i<N;i++)
NewRouter->addTab[i]=malloc(M*sizeof(char *));
return NewRouter;
}
I'm not sure how you call your updateTable function, but unless you actually fill up the entire array with char* pointers, your viewTable function will also invoke Undefined Behavior, because the printf statements will attempt to access uninitialized data. You could avoid this by using calloc instead of malloc when allocating the 2D array (or explicitly memset it), and then adding NULL checks in your viewTable function.
Finally, if you're calling updateTable with char* pointers that are not string literals or they have not been allocated on the heap, you might have further issues...
Your updateTable() doesn't work as you'd expect. You allocated memory in r->addTab[i][j] and, afterwards, assign a pointer to it (r->addTab[conn][1]=addr1). On access in viewTable, the program tries to read the memory at addr1, but most likely won't be able to read it, thus crashes.
Use a function to copy a given string to r->addTab, e.g. like so:
void router_tab_printf(Router *r, const int conn, const int i, const char *value) {
sprintf(r->addTab[conn][i], "%s", value);
}
This assumes that r->addTab[conn][i] is large enough to hold value.
you need to change your updateTable
void updateTable(Router *r, int conn, char *addr1, char *addr2){
strcpy(r->addTab[conn], addr1);
strcpy(r->addTab[conn+1 /*or something*/], addr2);
}
I have an array/pointer related problem.
I created an int array myArray of size 3. Using a function I want to fill this array.
So I'm calling this function giving her the adress &myArray of the array.
Is the syntax correct for the function declaration`? I'm handing over the pointer to the array, so the function can fill the array elements one by one.
But somehow my array is not filled with the correct values.
In Java I could just give an array to a method and have an array returned.
Any help is appreciated! Thanks!
#include <stdio.h>
int myArray[3];
void getSmth(int *anArray[]);
int main(void)
{
getSmth(&myArray);
}
void getSmth(int *anArray[])
{
for(i=0...)
{
*anArray[i] = tmpVal[i];
}
}
Remove one level of indirection:
#include <stdio.h>
int myArray[3];
void getSmth(int anArray[]);
int main(void)
{
getSmth(myArray);
}
void getSmth(int anArray[])
{
for(i=0...)
{
anArray[i] = tmpVal[i];
}
}
Also, as others have suggested, it would be a good idea to pass the size of the array into getSmth().
No, the syntax is not correct. You have an extra *, making the argument into an array of pointers.
In general, it's better to use:
void getSmth(int *array, size_t length);
since then the function can work on data from more sources, and the length becomes available which is very handy for iterating over the data as you seem to want to be doing.
You'd then call it like so:
int main(void)
{
int a[12], b[53];
getSmth(a, sizeof a / sizeof a[0]);
getSmth(b, sizeof b / sizeof b[0]);
}
Note the use of sizeof to compute (at compile-time) the number of elements. This is better than repeating the numbers from the definitions of the variables.
Right now, your function accepts an int *anArray[] parameter, which is an array of pointers to int. Remove the unneccessary * and your function signature should look simply like this:
void getSmth(int anArray[]); // array of int
or
void getSmth(int *anArray); // pointer to first array element of type int
You should use either int anArray[] or int *anArray (which is effectively the same, because array decays to pointer). You should also make sure that the function knows how big your array is either by agreement or passing it as a parameter for it can not use sizeof for the purpose.