struct student
{
int roll;
char *name;
};
int main()
{
int i;
struct student arr[2];
arr[0].roll = 12;
arr[1].name = "John";
arr[1].roll = 13;
arr[1].name = "Craig";
struct student *ptr;
ptr=arr;
// This is perfect.
for(i = 0; i<2; i++)
{
printf("%d %s", ptr->roll, ptr->name);
}
// This is also ok.
printf("%d %s", ptr->roll, ptr->name);
ptr++ // getting to next structure.
printf("%d %s", ptr->roll, ptr->name);
// But this isn't ok
while(*ptr || ptr->name != NULL)
{
ptr++;
}
return 0;
}
How to check pointer in while loop?
ptr points to an array if you increment it, ptr start pointing to a memory out size array that is not null.
You can do something like:
ptr = arr;
while (ptr < (arr + sizeof(arr)/sizeof(arr[0])) ){
ptr++;
}
Note: this technique will nnot work for dynamic arrays.
To learn what is this formula about read: Weird behavior when printing array in C?
You can use ptr check for null if you traversing an array of pointers AND when you know that the end of such array is marked with NULL. You are not.
You actually are traversing an array of structures with the ptr pointing straight to the memory location of the first element.
You have to keep track of the size of the array (or amount of its filled elements) and just stop after you have gone through them all.
int count = 2;
struct student arr[count];
struct student* ptr = arr;
for (int i=0; i<count; i++) {
// do your stuff
ptr++; // place it in for if you like
}
You can use this:
struct student *ptr=arr;
int max_len = sizeof(arr)/sizeof(*arr);
while(max_len--)
{
//do something...
ptr++;
}
One more thing I want to point out is you need to allocate memory for the char* pointer before allocating it with a string.The last loop which you have written doesn't execute at all, since all are NULL pointers.
Other way around is to put some special value in the roll number(say a negative value) of the last struct in the array. You then traverse the array until the roll number is positive.
Note that this method can also be used for dynamic arrays.
struct student *arr = (struct student*)malloc(20*sizeof(struct student));
*(arr+19).roll = -1; //this acts as a sentinel to indicate the end of the array....
struct student *ptr=arr;
while(ptr->roll > 0)
{
//do something...
ptr++;
}
while(*ptr || ptr->name != NULL)
First things first: the value of *ptr is a struct, which can't be converted to a boolean value and so while(*ptr) won't compile.
In order to null-terminate an array of structs, you must choose some struct member which you know will never be NULL when the struct is initialized (usually an important pointer), and use it as the flag. You do have that: the name field.
while(ptr->name != NULL)
Then the only problem is that your array isn't actually NULL terminated. You need to reserve an extra, third element at the end, just like with strings. An easy way to do so is by zero-initializing the whole array at declaration. So:
struct student arr[3] = {0};
arr[0].roll = 12;
arr[0].name = "John";
...
Which would have the same effect as manually setting ar[2].name = NULL;
Related
This is just part of a bigger code, but it's full of errors so I try to fix them one by one. When I try to use malloc on my pointer vector the line returns this error
main.c|14|error: expected '{' before '*' token
Any resolutions?
struct students {
int group;
char name[20];
int grade;
};
int main()
{
struct students *ptr[100];
int num, i, max=0;
scanf("%d", &num);
ptr = (struct*) malloc(num * sizeof(struct));
if(ptr == NULL)
{
printf("error");
exit(0);
}
}
Struct is reserved keyword for declaring/defining structures in C, it isn't variable, nor something you cant get size of it. You have declared struct students (according to your code, i think it should be student instead of students), now you have to define a variable and allocate space for 100 structs via a double pointer, the code should be something like this
struct student {
int group;
char name[20];
int grade;
};
int main()
{
struct student ** ptr;
int num, i, max=0;
scanf("%d", &num);
ptr = malloc(num * sizeof(struct student));
if(ptr == NULL)
{
printf("error");
exit(0);
}
}
Now you can access individual students with array subscript
ptr[0]->grade = 20; // putting 20 in grade of first student
Also, there is no need for casting malloc result in C
While using malloc for a 1D array, you should allocate a pointer, not an array of pointers as you have done.
While allocating you are using sizeof(struct). The type here is struct students and you need sizeof(struct students)
Do not cast the result of malloc. See Do I cast the result of malloc?
The final code is
struct students *ptr;
ptr = malloc (num * sizeof(struct students));
You have an array of pointers to structure. You should allocate memory for them separately.
for(int i=0; i<100 && i<num; i++)
{
ptr[i] = malloc(sizeof(struct students));
if(0 == ptr[i])
{
/* Handle this case. */
}
}
/* Your code. */
/* At the end free the memory. */
for(int i=0; i<100; i++)
{
if(0 != ptr[i])
{
free(ptr[i]);
ptr[i] = 0;
}
}
But I think you just wanted to allocate an array of struct students. In that case you just need one pointer.
struct students *ptr = 0;
/* You allocate memory and store it in that pointer. */
ptr = malloc(num * sizeof(struct students));
if(0 == ptr)
{
/* Handle this case. */
}
You can access ith element of the array like ptr[i]. But add necessary checks and make sure i < num.
You need to free the allocated memory whenever you are done using the array.
if(0 != ptr)
{
free(ptr);
ptr = 0;
}
I am creating a program that modifies a dynamic array. It must initialize the array and be able to insert into it. I have been unable print the array after in order to test it, how would I go about this?
Piece of relevant code:
typedef struct {
char first;
char second;
} name;
typedef struct {
int number;
name name;
} data;
/*points to array, number allocated, number used*/
typedef struct {
data *info;
size_t numof;
size_t numused;
} list;
void init(list *l) {
l->data = malloc(sizeof(l) * l->numof);
l->numused = 0;
l->numof = 2;
}
int insert(list *l, const data *dat) {
if (l->numused == l->numof) {
l->numof *= 2;
l->data = (int *)realloc(l->data, l->numof * sizeof(int));
}
l->data[l->numused++] = *dat;
return 0;
}
int main(void) {
int i;
list l;
data list1;
/*example info for testing*/
list.number = 1234;
strcpy(list1.name.first, "abc");
strcpy(list1.name.second, "xyz");
init(&l);
insert(&l, list1);
/*runs through array elements to print*/
for (i=0; i < ((int)sizeof(&l)) /(int)sizeof(&l); i++) {
printf("%s\n", list1);
}
return 0;
}
Edit: I just need to know how to print the array to see if I'm doing it correctly, the code above will have errors as I had been messing around trying to figure it out.
strcpy(list1.name.first, "abc");
strcpy(list1.name.second, "xyz");
These both will invoke undefined behaviour as first and second are declared as char variables , and you copy string literals to them .
You need to declare both of them as character arrays .
And this -
for (i=0; i < ((int)sizeof(&l)) /(int)sizeof(&l); i++) {
printf("%s\n", list1);
}
You try to print struct variable list1 with %s specifier, maybe you tend to print the strings that you wanted to copy. So directly print list1.name.first and list1.name.second in printf with %s specifier.
And the condition -
i < ((int)sizeof(&l)) /(int)sizeof(&l)
The cast is not necessary , and it will yield 1 so, loop will run for 1 time . Change the condition .
In your code, the member of structure name is defined as char. But you are trying to copy a string into it. May be this was a typo. If not you should define them as character array or character pointer. Also in your print statement you are trying to print structure data as string. It should be like -
printf("%s %s\n", list1.name.first, list1.name.second);
Also you assigned value 1234 to list.number. You may have meant list1.number. The parameters in function call of insert is wrong as well. And lastly, you have put l->data in functions init and insert which should be l->info.
I have a structure in c and I want to allocate memory for an array of my structure,
for this I'd created a function.
The problem is that only first element of array is working.
If I do allocation in main, it is working.
Here is my code:
typedef struct {
int id;
char* name;
}Car;
void read(Car**cars){
int n,i;
char name[50];
printf("Cars:"); scanf("%i",&n);
*cars = (Car*) malloc(n * sizeof(Car));
for(i=0;i<n;i++) {
printf("\nCar Name[%i]: ",i); scanf("%s",name);
(*cars[i]).id = i; //when i>0 then It crash here...
(*cars[i]).name = (char*) malloc(strlen(name)+1);
strcpy((*cars[i]).name, name);
printf("Cars Name -> %s ", (*cars[i]).name);
}
}
int main() {
Car *cars = NULL;
read(&cars);
return 0;
}
what I am doing wrong?
(*cars)[i].id = i; //when i>0 then It crash here...
This should work for you.
explanation:
you allocate n elements to the value of the pointer to the cars pointer.
but you try to derefference the value of the ith pointer to a cars element.
With my correction you derefference the firsts pointer's ith cars id. what is bad coded but should do what you want.
But what you probabbly want to do is asigning multiple pointers which at all point to a single car pointer instead ;)
than your crashing line could stay at it is.
I am initializing a struct called Array which consists of an array of Items and an int to keep track of the number of the Items.
typedef struct anything{
char text[MAXI];
int any;
}Item;
typedef struct array{
Item arr[0];
int size;
}Array;
To initialize the Array, I'm using malloc and returning the pointer.
Array create(){
Array *p1 = malloc(sizeof(Array));
p1->size = 0;
return *p1;
}
The problem I have is that some functions are designed for 2 Arrays, such as intersection:
Array intersection(Array S,Array T){
int i, j;
Array I = create();
for(i=0; i<(S.size); i++){
for(j=0; j<(T.size); j++){
if((compStructs(S.arr[i], T.arr[j])) == true)
add(I, S.arr[i]);
}
}
return I;
}
According to this code, if I were to execute create() twice, I would lose the pointer to the first array. Is there something I can do in the main program to prevent this, or what modifications can I do to the current function?
Edit: Added the add item function:
void add(Array S,Item x){
bool rep = false;
int i = 0;
for(i = 0; i<(S.size); i++){
if(compStructs(x,S.arr[i]) == true)
rep = true;
}
if(rep == false){
Item *p2 = realloc(S.arr, sizeof(Item));
*p2 = x;
(S.size)++;
}
else
printf("The item is already in the set.");
}
My main problem is that I'm not sure how to call two seperate arrays which are to be created at the user's request. The program is in it's build up but currently it looks somehitng like this:
#include "array.h"
Item x;
void arraymenu(){
char inp;
while((inp = getchar())!= '\n'){
printf("a. To Create a new Array\n"
"b. To Add a new Item\n"
"c. To Remove an Item\n"
"d. To Clear all contents of the Array\n"
"e. To Get the size of the Array\n"
"f. To Get a list of the number of elements of your choice\n"
"g. To Check whether the array is empty\n"
"h. To Get the union of two sets\n"
"i. To Get the intersection of two sets\n"
"j. To Get the difference of two sets\n"
"k. To Check if a set is the subset of the other one\n"
"l. To map a function to all Items of an Array\n"
"m. To apply a function to all Items of an Array\n"
"n. To store the Array in a File\n"
"o. To load the Array from a File\n" );
switch(inp){
case 'a' : printf("Array A has been created.");
Array A = create();
break;
case 'b' : printf("Enter any integer, followed by any string.");
scanf("%d", &x.any);
scanf("%s", &x.text);
add(A, x);
break;
case 'c' : printf("Enter the integer and string you wish to remove ");
scanf("%d", &x.any);
scanf("%s", &x.text);
removee(A,x);
break;
}
}
}
Basically, instead of a derefferenced pointer to a variable local to a given function's scope you need to return a pointer (BTW, compiling return *ptr should give a warning when compiling, add -Wall, and don't ignore what the compiler is telling you):
Array *create()
{
Array *a_ptr = malloc(sizeof(*a_ptr));
if (a_ptr == NULL) exit (EXIT_FAILURE);//failed to allocate memory
a_ptr->size = 0;
return a_ptr;
}
To be called like this:
Array *S, *T;
S = create();
T = create();
Now you have 2 arrays ready to play with. Note that you'll need to either dereference these pointers, or use the indirection operator on them always:
(*S).size = 1;
//or
S->size += 123;
You'll also probably want to change intersection to something like:
Array *intersection(Array *S,Array *T)
{
int i, j;
Array *I = create();
for(i=0; i<(S->size); ++i)
{
for(j=0; j<(T->size); ++j)
if(compStructs(S.arr[i], T.arr[j])) add(I, S.arr[i]);
}
}
return I;
}
Of course, once you're done with all of these Array structs, you'll have to free() them, too.
As far as compStructs and add go, I expect you'll have to work on those functions, too. While you're at it, perhaps change the struct to better fit the way you're using it:
typedef struct array
{
Item *arr;
size_t size;//size_t makes more sense here
}Array;
Of course, this in turn requires a bit more work when free-ing the memory, so a generic free function is advisable:
void free_array(Array **a)
{//pointer to pointer
while((*a)->size--) free((*a)->arr+(*a)->size);
free(*a);
*a = NULL;//NULL pointers are safer
}
//call like so:
free_array(&Array_ptr);//yes, address of pointer
And realloc calls should look something like:
realloc(a->arr, (a->size + 1)*sizeof(*(a->arr)));
a->size += 1;
typedef struct array{
int size;
Item arr[];
}Array;
Array *create(int size){
Array *p1 = malloc(sizeof(Array) + size*sizeof(Item));
if(p1)p1->size = size;
//return *p1;//memory leak
return p1;
}
I am looking to do the following:
struct def:
struct mystruct {
char cArr[500];
}
global:
struct mystruct **ptr;
int count = 0;
in main:
ptr = malloc(20*sizeof(struct test *));
for (int i = 0; i != 20 ; i++) {
ptr[i] = malloc(sizeof(struct test));
}
in some function that is called 20 times:
char burp[500];
//put whatever I want in burp;
ptr[count]->cArr = burp //is this right? Or do I have to memcpy to it, and if so how?
count++;
So at the end I will sequentially fill in the array of mystruct with the chars that I want. I tried doing this with char** but had no luck; I am now wrapping it in a struct as it helps me visualize what is going on.
So I want a global array of char[500], where everytime a function is called it puts that char[500] into the index (that is either passed into the function or also global).
Any advice is appreciated; Ofc I will need to free at the end every index of the array as well.
Thanks!
edit:
so would something like:
memcpy(ptr[count]->cArr, burp, 500);
work then?
#include <stdio.h>
#include <stdlib.h>
struct mystruct
{
char *cArr;
// U were trying to assign array using = operator
// Remember its not like in STL where u can perform deep copy of a vector
};
struct mystruct **ptr;
int count = 0;
int main()
{ int i;
ptr = malloc(20*sizeof(struct mystruct *));
for (i = 0; i != 20 ; i++)
{
ptr[i] = malloc(sizeof(struct mystruct));
}
char burp[500]="No this is not correct boy.";
//put whatever I want in burp;
(*ptr+count)->cArr = burp ;
// Assigning pointer to a pointer , OK. Remember pointer != Array.
//is this right? Or do I have to memcpy to it, and if so how?
//count++; // Has no use in your code, enclose in a loop to then use it.
printf("%s\n",(*ptr + count)->cArr); // This works , I think.
}
For arrays i.e. char cArr[500],
If you want to use memcpy u can use it :
memcpy((*ptr+count)->cArr, burp, 500);
Strcpy also works :
strcpy((*ptr+count)->cArr, burp);
Two points are important :
Assignment of pointers to pointers is allowed, but deep copy of array is not.
**ptr is a double pointer.So, (*ptr + count ) or ptr[count] is a pointer to struct.
2nd point is not required for your answer.
You can use strcpy to copy the string.
strcpy(ptr[count]->cArr,burp);
But strcpy terminates on null character. So, make sure your character string(i.e burp) is properly initialized.
I guess all that you wanted to do is to store some text in your structure for later usage.
struct mystruct {
char carr[500];
}
struct mystruct *ptr = NULL;
int count = 0;
main{
...
ptr = malloc( 20 * sizeof(struct test) );
//Function call func()
...
//After performing work
free( ptr );
}
//Some function
func() {
char burp[500];
// burp has some data fed
memcpy( ptr[count]->carr, burp, 500 );
}