I need to create mini social network in C. I made a struct for each person. And I'm storing each friend in a char pointer with id's. I thought I can manage it like this:
ptr_friends = id1,id2,id3,id4...
and when I need them I could just read those by using strtok.
But I couldn't manage to save it that way. It should be like this:
ptr_friends = ptr_friends + id + ","
but of course it doesn't work this why and I don't know how to do it.
How can I save and use this way? Or if you have another idea for a save method please tell.
I'd suggest that you make ptr_friends a pointer to multiple chars by using malloc(size_t) and then resizing the space with realloc(void *, size_t) everytime you want to add an ID to the friendlist. That way you can just get the numbers using ptr_friends[i].
For example :
int friends_size = 1;
char *ptr_friends = malloc((size_t)1);
ptr_friends[0] = john_id; // john_id is a fictional ID here
And when you want to add a friend :
ptr_friends = realloc(ptr_friends, ++friends_size);
ptr_friends[friends_size-1] = mary_id;
EDIT :
If you want to make a function to add a friend, for example addfriend(char *,int), doing the following is an error :
void addfriend(char *ptr_friends, int *friends_size, int id)
{
ptr_friends = realloc(ptr_friends, (size_t) ++(*friends_size));
ptr_friends[friends_size-1] = id;
}
ptr_friends here is getting reallocated, and since the pointer can move while being reallocated, we're storing it in ptr_friends. But, it's the ptr_friends from inside the function, that means that the pointer we give to the function will not get modified, since arguments to a function are copied elsewhere beforehand. That means that you have to give a pointer to the pointer, so you can modify the pointer in the main code.
I guess this will help you : https://stackoverflow.com/a/5901241/2549281
You should use something like :
strcat(ptr_friends, id);
strcat(ptr_friends, ",");
instead of ptr_friends + id + ","
Would not it be easier to you to do an array of ints with ids?
int max_friends = 50;
int friends_size = 0;
int friends* = malloc(sizeof(int) * MAX_FRIENDS);
friends[friens_size] = id;
friends_size++;
Another suggestion is instead of using a string or a simple array you can use a "generic" dynamic array (using void*). It's a simple code and you can find many examples.
take a look at that question: C dynamically growing array
Related
struct orange_t {
short size;
Month expirationMonth;
char** foodCompanies;
int maxNumberOfFoodCompanies;
int sellingPrice;
};
memcpy(orange->foodCompanies,foodCompany,sizeof(strlen(foodCompany)));
printf("%s %s",orange->foodCompanies[0],foodCompany);
My problem. that I really don't know to access rightfully to the first word in orange in foodComapnies, the second and so on ...
What is the right syntax and the right way to do it?
I want to write a few foodComapny into orange->foodCompanies, each foodComapny in another place in the array of strings.
memcpy(orange->foodCompanies,foodCompany,sizeof(strlen(foodCompany)));
is wrong. sizeof(strlen...) tells you how big a number is - not useful.
I assume that foodCompanies is an array of names and you want to add foodCompany to that array. You dont show how that array was set up (v important). I will assume that its not set up
orange->foodCompanies = malloc(sizeof(char*))// array holds one entry
orange->foodCompanies[0] = strdup(foodCompany);
to add another entry you will need to realloc or make the original malloc bigger
Okay so that wasn't very clear. What I am trying to do is this:
while (//something) {
char * tempuser;
char * users[100];
tempuser = "bobsmith" //I'm not actually doing this. But using a method that does the same thing
users[i] = tempuser;
}
Where "bobsmith" is is different everytime through the loop. If I run this, as is, 5 times and the last entry is "janetsmith" all 5 places in the array before that, regardless of being different when assigned, all end up as "janetsmith". How should I assign users[i] so that it has a different value in all indexes?
Do not create the array users in loop body, and use strdup to create new string with the same content inside the array. Remember that You are using pointers not some kind of string objects. Each entry in array holds the address of the text inside memory.
char *users[100]={0}; //one hundred pointers that are null so You don't use a wild one.
int i=0;
while(/*whatever*/) {
char *tmp=getsometext(); //returns char pointer
users[i++]=strdup(tmp); //copies contents pointed by tmp into new memory location and returns its address
}
//don't forget to free every pointer when You are done.
It is because you are assigning address of the variable tempuser. By the end of it all, it will always hold the address of "janetsmith". Try creating the variable dynamically using malloc() function.
char * users[100]; //with this you can use it outside while
while (//something) {
static unsigned int i = 0;
//char * tempuser;
//tempuser = "bobsmith" //I'm not actually doing this. But using a method that does the same thing
users[i] = method_which_return_char_pointer();
i++;
if( 100 <= i)
i=0;
}
this what from your brief Question explanation .
Im creating a web app and already working on the backend. I need to process a lot of post request data using C and API's provided in appweb.
Here's the code:
static void addStudentInformation()
{
char * average = malloc(30000);
MprJson * userInput = httpGetParams(getConn());
char * name;
strcpy(name,mprLookupJson(userInput, "name"));
average = computeGrade(mprLookupJson(userInput, "gradeSubject1_1"), mprLookupJson(userInput, "gradeSubject1_2"), mprLookupJson(userInput, "gradeSubject1_3"));
//more function calls
}
char * computeGrade(char * grade1, char * grade2, char * grade3)
{
/*process grade*/
return average;
}
//more function
As you can see, the value returned by mprLookupJson was directly used a a parameter in function computeGrade. I thought of not storing those values in a variable since it wont needed/ used in addStudentInformation. I thought that there's no point of alloting/using a memory. Now, my question is it safe/good practice to do that? is there any possibility that a security issue may arise because of that? What would be the best approach for this?
Thank you.
What happens if mpfLookupJson(userInput, "name") does not find a valid entry? Say, it delivers -1 as it has not found an entry. In that case, your strcpy() could crash.
If mpfLookupJson finds something valid, it will allocate some memory on the heap and give you the pointer to it. In that case, the memory has already been allocated. If you create a further pointer variable to it, in my opinion it won't matter. If you program some special micro controller, maybe you have to care about some bytes more or less, but probably not here.
Now you create a pointer variable name and try to copy the value found to where name points to. As long as you don't allocate memory for name to point to, this will crash. Further: do you really need a copy of the value found by mpfLookupJson? Can't you use it as it has been returned?
To my eyes, this would be enough, more reliable and more readable:
static void addStudentInformation()
{
char * average = malloc(30000);
MprJson * userInput = httpGetParams(getConn());
char * name;
char * grade1;
char * grade2;
char * grade3;
name = mprLookupJson(userInput, "name");
grade1 = mprLookupJson(userInput, "gradeSubject1_1");
grade2 = mprLookupJson(userInput, "gradeSubject1_2");
grade3 = mprLookupJson(userInput, "gradeSubject1_3");
if (name <= 0 || grade1 <= 0 || grade2 <= 0 || grade3 <= 0 ) {
// handle error and / or abort
}
average = computeGrade(grade1, grade2, grade3);
//more function calls
...
}
Then, what happens after the end of the function? If memory is important to you, make sure you deallocate everything the right way.
These are rather safety concerns than security concerns. Security starts where somebody can misuse your code to get admin privileges or make the process crash or the memory being flooded. The first points to examine would be what mprLookupJson precisely does, how good userInput has been filtered against tampering and how strict you react if name, grade1, grade2 etc. are invalid the slightest way. Alone for this reasons, you need well readable code.
Hope these suggestions are a good start :-)
I am having a problem with creating a function that will add (copy) structure from parameter to resized array.
Here is my simplified code:
typedef struct User
{
char FirstName[32];
char LastName[32];
}
User;
User * Users
unsigned short UsersNum = 0;
void AddUser(User * NewUser)
{
Users = (User *) realloc(Users, (UsersNum + 1) * sizeof(User));
memcpy(Users[UsersNum], NewUser, sizeof(User));
UsersNum++;
}
With this I'm getting:
error: incompatible type for argument 1 of `memcpy'
I've also tried
memcpy(Users + UsersNum, NewUser, sizeof(User));
But got SEGFAULT.
How can i copy NewUser to the end of Users?
First, please don't cast the return value of malloc() in C.
Second, why do you feel you must use memcpy() here? The memcpy() function is great, but it's a rather blunt tool meant to "blindly" copy large areas of memory that have no further structure that the program is aware of. In your case, you know that the bytes you're copying make up an instance of the User type, i.e. it's simply a value of type User.
Values are typically moved around by assignment, so use that instead:
void AddUser(const User *NewUser)
{
User *UsersGrown = realloc(Users, (UsersNum + 1) * sizeof *Users);
if(UsersGrown != NULL)
{
Users = UsersGrown;
Users[UsersNum] = *NewUser;
++UsersNum;
}
}
You can see that I also made the argument const, and added some basic error-checking since realloc() can fail.
It would be a good idea to separate the allocated size of the Users array from the length of the array, so that you can grow them at different speeds and cut down on the number of calls to realloc(). In other words, allocate room for e.g. 8 elements at first, and when that is hit, double the size and realloc(), and so on. This gives much better performance if you expect many insertions.
You should ask yourself what type is User[UsersNum] ... that is User, and memcpy operates on pointers. To get address of it there is & operand. So it should be
memcpy(&Users[UsersNum], NewUser, sizeof(User));
Also please note the you are using very very inefficient way to implement the functionality. Copying/moving stuff around so much should be avoided.
Firstly, I am really sorry if this has already been asked and resolved - I have spent ages searching and trying to adapt code samples to give me what I need... but sadly to no avail. Essentially I am just trying to copy the contents of one struct to another (which is documented here elsewhere but I cannot get it to work).
A scanner populates the following struct when it reads a barcode:
struct barcode
{
char *text;
int length;
int id;
int min;
int max;
};
This is instantiated as:
static struct barcode code = {0};
I instantiate another one of the same type:
struct barcode *barcodeHolder;
This is intended to store a copy of the scanned barcode. This is because other codes will then be scanned that indicated other steps such as barcodes to indicate numbers or stages (eg. end, start, etc). Once I want to write the struct contents to disk I use the "copy" of the struct as that is what I want.
However, the char *text property always equals 'c' and not the value of the barcode.
I copy them as follows:
barcodeHolder = malloc(sizeof(code));
barcodeHolder->text = malloc(strlen(code->text) + 1);
strcpy(barcodeHolder->text, code->text);
barcodeHolder->id = code->id;
barcodeHolder->length = code->length;
barcodeHolder->max = code->max;
barcodeHolder->min = code->min;
This is what I have got from other posts on a similar topic.
However, I am clearly doing something stupidly wrong and would welcome any help anyone might be able to offer so that my copy of the struct text element does actually get the right value copied.
Thank you!
Your code is not a pointer
You need this:
barcodeHolder = malloc(sizeof(code));
barcodeHolder->text = malloc(strlen(code.text) + 1);
strcpy(barcodeHolder->text, code.text);
barcodeHolder->id = code.id;
barcodeHolder->length = code.length;
barcodeHolder->max = code.max;
barcodeHolder->min = code.min;
I don't believe that your code is really:
static struct barcode code = {0};
[..]
strcpy(barcodeHolder->text, code->text);
Because the last statement would yield a compile error - because code is not a pointer you have to use code.text there (instead of code->text).
Assuming that you are actually using something like
struct barcode *code = ...;
You are allocating with your above code sizeof pointer of struct code bytes which is not enough for your structure.
Thus, copy it like this:
barcodeHolder = malloc(sizeof(struct barcode));
// alternative: ... = malloc(sizeof(*code));
*barcodeHolder = *code;
barcodeHolder->text = malloc(strlen(code->text) + 1);
strcpy(barcodeHolder->text, code->text);
Or, more simply:
barcodeHolder = malloc(sizeof(code));
*barcodeHolder = code;
barcodeHolder->text = strdup(code.text);
Probably unrelated, but if code in your example is a pointer to a struct, then your sizeof is wrong. It should be sizeof(*code) or sizeof(struct barcode). – Sean Bright 21 hours ago
#SeanBright In no way would I ever call myself a C programmer - ever! - so you saved completely here! Thank you. No, "code" is not a pointer in programme which confused me too... and was probably why I couldn't get anywhere. I just needed to get it work to prove we can do it for a demo. Should it progress I will come back (hopefully!) and revisit the code to better understand why it is working when it maybe shouldn't be. Thank you again!!!