Pages: 1 2 [3] 4   Go Down
Author Topic: Removing elements from array  (Read 2963 times)
0 Members and 1 Guest are viewing this topic.
Sydney, Australia
Offline Offline
Edison Member
*
Karma: 33
Posts: 1287
Big things come in large packages
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

An alternative approach for the elevator problem would be to have an array representing the number of floors, which does not change much, and if the elevator needs to go there put a 1 in the array element for the floor. For example, if I need to go to floor 3 then array element 3 has a 1 in it. No rearranging necessary and if the elevator is going past the floor it can just stop there by checking whether the floor has been requested.
Logged

Arduino libraries http://arduinocode.codeplex.com
Parola hardware & library http://parola.codeplex.com

Offline Offline
Newbie
*
Karma: 0
Posts: 21
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Jumping up a level for a moment: shuffling data within an array is a well-known anti-pattern, which is to say it should be avoided if possible in favor of other, better approaches.

What is it that you are trying to do that apparently requires you to shuffle data within an array?  Perhaps there is a different approach...

-br


I'm trying to make an elevator, so the array contains the different floors that the elevator are told to go to, so when it have visited a floor I want it to remove the floor (element) from the array, and be able to add it (as the last element) in the array when the button are pressed again.

I hope you understand what I mean smiley

If I might suggest an alternate method that might work better for your application. Still using arrays, but in a different way. First construct an array of boolean values one for each floor of the building, lets call it floorArray[]. For this example, lets pretend your building has a basement (or you are using a more European floor counting method) such that the first floor is actually floorArray[1] so the basement (or ground floor) is floorArray[0]. When anyone presses any button for a specific floor (whether that button is located in the elevator lobby, in the actual elevator, or in the elevator master control room) it sets floorArray[that floor] to TRUE. This could either be done as part of the main loop, or in an ISR. When the elevator stops at a floor and opens (or closes) it's door, it sets floorArray[that floor] to FALSE. For the elevator movement, it knows the previous/current direction (up or down). It knows where it is, and scans floorArray[] for the next TRUE value in the direction it was/is previously/currently moving. If there aren't any more TRUEs in the direction it is scanning, reverse the direction and scan for the next TRUE in that direction. (Hopefully if it scans before moving when leaving a floor, it should continuously keep scanning in alternating directions until a button somewhere else is pressed. You may need to put in some additional check when parked at a floor to see if the button on the current floor is presses so the doors will open again.) Keep looping through the scanning of floorArray[] while the elevator is moving to catch any new elevator calls while it is moving.

I suppose one could conserve your SRAM (where all variables are stored) by using bitmasking instead of an array because an array of booleans is the same size as an array of bytes (8 times more space wasteful than bitmasking), but the array method is simpler and easier to expand. Expand it just by increasing the array size.

I hope this gives you another way to view the problem.

Edit: I see both billroy and PeterH suggested the exact same thing while I was drafting this. Taking all our comments together should hopefully be enough to write your code. Good luck with your project.


Thank you for your suggestion smiley

But I have a problem, when I use this code:

Code:
int countu = 0;
int countd = 0;
boolean up[7] = {};
boolean down[7] = {};
boolean moving = false;
boolean bup = false;
boolean bdown = true;

void setup() {
  Serial.begin(9600);
  for(int x = 0; x <= 7; x++){
    up[x] = true;
    down[x] = true;
  }
  for(int i = 22; i <= 30; i++){
    pinMode(i, OUTPUT);
  }
  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);
  for(int i = 1; i <= 6; i++){
    pinMode(i, INPUT);
  }
  for(int i = 12; i <= 17; i++){
    pinMode(i, INPUT);
  }
  pinMode(19, INPUT);
  for(int i = 22; i <= 30; i++){
  digitalWrite(i, LOW);}
}


void loop(){
      Serial.print("Up:\n");
  while(up[countu] == true){
   Serial.print(up[countu]);
   Serial.print("\n");
 countu++;
  }
   Serial.print("---------------------------\n"); 
      Serial.print("Down:\n");
  while(down[countd] == true){
   Serial.print(down[countd]);
   Serial.print("\n");
 countd++;
  }
   Serial.print("---------------------------\n");
   delay(1500);
 }

It should fill both arrays with all the 7 elements with the value "True" right?
But when I write it out I get 14 elements from the first array (boolean up[7]) and 7 from the second one (boolean down[7]), but only the first time it writes out all the elements, all the other times it doesn't write anything :/

Do you know what the problem could be? smiley
Logged

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 310
Posts: 26630
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
for(int x = 0; x <= 7; x++){
Wrong.
Your array only has 7 elements.
Logged

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Offline Offline
Newbie
*
Karma: 0
Posts: 21
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
for(int x = 0; x <= 7; x++){
Wrong.
Your array only has 7 elements.

Woops didn't see that :S

But does not fix the problem :/
Logged

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 310
Posts: 26630
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
But does not fix the problem
It fixed a very serious problem.
The other problem(s) is (are) related - reading past the end of an array.
Logged

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Offline Offline
Newbie
*
Karma: 0
Posts: 21
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
But does not fix the problem
It fixed a very serious problem.
The other problem(s) is (are) related - reading past the end of an array.

How come I can read past the end of my array, if there is only 7 elements, and I fill them with a value (true) and I write out all the values that are equal to true?

An alternative approach for the elevator problem would be to have an array representing the number of floors, which does not change much, and if the elevator needs to go there put a 1 in the array element for the floor. For example, if I need to go to floor 3 then array element 3 has a 1 in it. No rearranging necessary and if the elevator is going past the floor it can just stop there by checking whether the floor has been requested.

Also I have tried using integers instead of booleans, but I get the same problem, the only difference is that I get 8 elements in the second array (int down[7] = {};) where the 8th element is eaquals to 18 :S
Logged

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 310
Posts: 26630
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
How come I can read past the end of my array
Welcome to C, microcontrollers and a complete freedom of interfering memory managers!

Code:
void loop(){
      Serial.print("Up:\n");
  while(up[countu] == true){
   Serial.print(up[countu]);
   Serial.print("\n");
 countu++;
  }
Where do you reset "countu" to zero?
Logged

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Offline Offline
Newbie
*
Karma: 0
Posts: 21
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
How come I can read past the end of my array
Welcome to C, microcontrollers and a complete freedom of interfering memory managers!

Code:
void loop(){
      Serial.print("Up:\n");
  while(up[countu] == true){
   Serial.print(up[countu]);
   Serial.print("\n");
 countu++;
  }
Where do you reset "countu" to zero?

ohh.. sorry, I think I'm overseeing alot of thinks :S


So, now I have this:

Code:
int countu = 0;
int countd = 0;
boolean up[7] = {};
boolean down[7] = {};
boolean moving = false;
boolean bup = false;
boolean bdown = true;

void setup() {
  Serial.begin(9600);
  for(int x = 0; x < 7; x++){
    up[x] = true;
    down[x] = true;
  }
  for(int i = 22; i <= 30; i++){
    pinMode(i, OUTPUT);
  }
  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);
  for(int i = 1; i <= 6; i++){
    pinMode(i, INPUT);
  }
  for(int i = 12; i <= 17; i++){
    pinMode(i, INPUT);
  }
  pinMode(19, INPUT);
  for(int i = 22; i <= 30; i++){
  digitalWrite(i, LOW);}
}


void loop(){
      Serial.print("Up:\n");
  while(up[countu] != false){
   Serial.print(up[countu]);
   Serial.print("\n");
 countu++;
  }
   Serial.print("---------------------------\n"); 
      Serial.print("Down:\n");
  while(down[countd] != false){
   Serial.print(down[countd]);
   Serial.print("\n");
 countd++;
  }
   Serial.print("---------------------------\n");
   delay(1500);
   countd = 0;
   countu = 0;
 }

And my output is this:

Code:
Up:
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
---------------------------
Down:
1
1
1
1
1
1
1
17
---------------------------
Up:
1
1
1
1
1
1
1
1
1
1
1
1
1
1
235
5
---------------------------
Down:
1
1
1
1
1
1
1
255
6
---------------------------
Up:
1
1
1
1
1
1
1
1
1
1
1
1
1
1
219
11
---------------------------
Down:
1
1
1
1
1
1
1
240
11
---------------------------
Up:
1
1
1
1
1
1
1
1
1
1
1
1
1
1
206
17
---------------------------
Down:
1
1
1
1
1
1
1
227
17
---------------------------
Up:
1
1
1
1
1
1
1
1
1
1
1
1
1
1
193
23
---------------------------
Down:
1
1
1
1
1
1
1
214
23
---------------------------
Up:
1
1
1
1
1
1
1
1
1
1
1
1
1
1
180
29
---------------------------
Down:
1
1
1
1
1
1
1
201
29
---------------------------
Up:
1
1
1
1
1
1
1
1
1
1
1
1
1
1
166
35
---------------------------
Down:
1
1
1
1
1
1
1
188
35
---------------------------
Up:
1
1
1
1
1
1
1
1
1
1
1
1
1
1
153
41
---------------------------
Down:
1
1
1
1
1
1
1
174
41
---------------------------
Up:
1
1
1
1
1
1
1
1
1
1
1
1
1
1
140
47
---------------------------
Down:
1
1
1
1
1
1
1
161
47
---------------------------
Up:
1
1
1
1
1
1
1
1
1
1
1
1
1
1
127
53
---------------------------
Down:
1
1
1
1
1
1
1
148
53
---------------------------
Up:
1
1
1
1
1
1
1
1
1
1
1
1
1
1
114
59
---------------------------
Down:
1
1
1
1
1
1
1
135
59
---------------------------
Up:
1
1
1
1
1
1
1
1
1
1
1
1
1
1
100
65
---------------------------
Down:
1
1
1
1
1
1
1
121
65
---------------------------
Up:
1
1
1
1
1
1
1
1
1
1
1
1
1
1
87
71
---------------------------
Down:
1
1
1
1
1
1
1
107
71
---------------------------
Up:
1
1
1
1
1
1
1
1
1
1
1
1
1
1
73
77
---------------------------
Down:
1
1
1
1
1
1
1
93
77
---------------------------
Up:
1
1
1
1
1
1
1
1
1
1
1
1
1
1
58
83
---------------------------
Down:
1
1
1
1
1
1
1
78
83

Can you please tell me what I do wrong or how to prevent this from happening?
Because I can't figure it out.. :/


And thanks for taking your time to help me out, I really appreciate that smiley-grin
Logged

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 310
Posts: 26630
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
while(up[countu] != false){
   Serial.print(up[countu]);
   Serial.print("\n");
 countu++;
  }
Your problem is probably that "up" and "down" are contiguous in memory, that is, down[0] is in the very next location to up [6].
C is very unforgiving in this respect, and you have to be very careful about how you handle arrays and pointers.
You need to keep track of your array bounds; the language will not do this for you.

Code:
if (up[countu] != false)
is much clearer if you write it
Code:
if (up[countu] == true)
or, more simply
Code:
if (up[countu])
Logged

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Offline Offline
Newbie
*
Karma: 0
Posts: 21
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
while(up[countu] != false){
   Serial.print(up[countu]);
   Serial.print("\n");
 countu++;
  }
Your problem is probably that "up" and "down" are contiguous in memory, that is, down[0] is in the very next location to up [6].
C is very unforgiving in this respect, and you have to be very careful about how you handle arrays and pointers.
You need to keep track of your array bounds; the language will not do this for you.

Code:
if (up[countu] != false)
is much clearer if you write it
Code:
if (up[countu] == true)
or, more simply
Code:
if (up[countu])

okay I have this code now:

Code:
int countu = 0;
int countd = 0;
int test = 0;
int test2 = 0;
boolean up[7] = {};
boolean down[7] = {};
boolean moving = false;
boolean bup = false;
boolean bdown = true;

void setup() {
  Serial.begin(9600);
  for(int x = 0; x < 7; x++){
    up[x] = true;
    down[x] = true;
  }
  for(int i = 22; i <= 30; i++){
    pinMode(i, OUTPUT);
  }
  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);
  for(int i = 1; i <= 6; i++){
    pinMode(i, INPUT);
  }
  for(int i = 12; i <= 17; i++){
    pinMode(i, INPUT);
  }
  pinMode(19, INPUT);
  for(int i = 22; i <= 30; i++){
  digitalWrite(i, LOW);}
}


void loop(){
      Serial.print("Up:\n");
  check();
   Serial.print("---------------------------\n");
   delay(1500);
   countd = 0;
   countu = 0;
 }
 
 
 void check(){
   while(test == 0){
     if(up[countu]){
   Serial.print(up[countu]);
   Serial.print("\n");
 countu++;
  }else{
    test = 1;
  }}
  Serial.print("---------------------------\n"); 
      Serial.print("Down:\n");
  while(test2 == 0){
  if(down[countd]){
   Serial.print(down[countd]);
   Serial.print("\n");
 countd++;
  }else{
    test2 = 1;
  }
  }
  test2 = 0;
  test = 0;
   }

But I still gets some weird outputs like this:

Code:
Up:
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
---------------------------
Down:
1
1
1
1
1
1
1
17
---------------------------
Up:
1
1
1
1
1
1
1
1
1
1
1
1
1
1
235
5
---------------------------
Down:
1
1
1
1
1
1
1
255
6
---------------------------
Up:
1
1
1
1
1
1
1
1
1
1
1
1
1
1
219
11
---------------------------
Down:
1
1
1
1
1
1
1
240
11

... :/
Logged

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 310
Posts: 26630
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
void check()
{
   while(test == 0)
   {
     if(up[countu])
     {
       Serial.print(up[countu]);
       Serial.print("\n");
       countu++;
     }else{
       test = 1;
     }
}
I moved some of the braces around to make the code clearer.
There's nothing at all weird about the output; you're still running off the end of your first array.

There is nothing magical that C can do to prevent you doing this; you have to manage it yourself, by testing the index (countu) against the maximum size of the array.
Logged

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Offline Offline
Newbie
*
Karma: 0
Posts: 21
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
void check()
{
   while(test == 0)
   {
     if(up[countu])
     {
       Serial.print(up[countu]);
       Serial.print("\n");
       countu++;
     }else{
       test = 1;
     }
}
I moved some of the braces around to make the code clearer.
There's nothing at all weird about the output; you're still running off the end of your first array.

There is nothing magical that C can do to prevent you doing this; you have to manage it yourself, by testing the index (countu) against the maximum size of the array.


hmm... so to test for the size of my array i would use
Code:
sizeof(up) / sizeof(up[0])
right?

so to see if I have true in the element and it's not going over the size of my array I would use:
Code:
if(up[countu] && countu <= sizeof(up) / sizeof(up[0]))

am I right? smiley
Logged

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 310
Posts: 26630
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
am I right?
Close.
Code:
sizeof(up) / sizeof(up[0])
Gives the number of elements in your array "up", in this case 7.
Code:
if(up[countu] && countu <= sizeof(up) / sizeof(up[0]))
Can you see the problem there? (Hint: you've already seen something similar)
Logged

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 653
Posts: 50883
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Instead of calling sizeof() twice and performing a divide operation every time, create a variable, global and const, initialized ONCE that contains the size of the array(s).
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 21
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
am I right?
Close.
Code:
sizeof(up) / sizeof(up[0])
Gives the number of elements in your array "up", in this case 7.
Code:
if(up[countu] && countu <= sizeof(up) / sizeof(up[0]))
Can you see the problem there? (Hint: you've already seen something similar)

I can't see it.. :/

Instead of calling sizeof() twice and performing a divide operation every time, create a variable, global and const, initialized ONCE that contains the size of the array(s).

I know I can do that smiley
This was more to make a shorter view of what I wanted to do smiley
Logged

Pages: 1 2 [3] 4   Go Up
Jump to: