0
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?

user1502952
  • 1,390
  • 4
  • 13
  • 27

4 Answers4

4

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?

Community
  • 1
  • 1
Grijesh Chauhan
  • 57,103
  • 20
  • 141
  • 208
  • Yes, but why this is running an extra loop, even this was the same case when i did while(ptr->name != NULL) i.e an extra garbage value – user1502952 Sep 20 '13 at 07:09
  • @user1502952 Why extra? my answer is about how to save `ptr` not pointing to outside array that is actually undefined behavior. Suppose if if for some `arr` index value `name` points to a NULL then add an extra check. – Grijesh Chauhan Sep 20 '13 at 07:15
  • @user1502952 do like: `while (ptr < (arr + sizeof(arr)/sizeof(arr[0]) -1) && ptr->name != NULL ){ do your code here}` – Grijesh Chauhan Sep 20 '13 at 07:21
  • 1
    Why `-1`? I fail to see why this is necassary - it even seems invalid! It'll skip last element. For 1 element in an array it will not iterate at all. – Dariusz Sep 20 '13 at 10:41
  • @Dariusz Math mathematically I may be uncorrected here, Should I remove ? – Grijesh Chauhan Sep 20 '13 at 10:44
  • @Dariusz your last line is helpful *`For 1 element in an array it will not iterate at all.`* Thanks! – Grijesh Chauhan Sep 20 '13 at 10:46
  • The problem is that the user has accepted your answer and most likely has already used your code. A pity. – Dariusz Sep 20 '13 at 10:48
  • @Dariusz yes :) ... I didn't post answer sincerely – Grijesh Chauhan Sep 20 '13 at 10:52
2

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
}
Dariusz
  • 21,561
  • 9
  • 74
  • 114
1

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++;
}
nitish712
  • 19,504
  • 5
  • 26
  • 34
0
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;

tab
  • 903
  • 1
  • 6
  • 8