- The indentation of your code is a mess. Reindenting your code, you get into it:
package estacionamento;
import java.util.Scanner;
public class Estacionamento {
public static void main(String[] args) {
Pilha p = new Pilha(4);
Pilha p2 = new Pilha(4);
char mov = 0;
int placa = 0;
Scanner s = new Scanner(System.in);
for (int i = 0; i < p.ele.length; i++) {
do {
System.out.println("Informe a movimentação do carro : ");
mov = s.next().charAt(0);
switch(mov) {
case 'E':
if (p.estaCheia()) {
System.out.println("Estacionamento cheio!");
}
else {
System.out.println("Por favor,informe a placa");
placa = s.nextInt();
p.inserir(placa);
System.out.println(placa + " foi inserido");
}
break;
case 'S':
System.out.println("Informe a posição do carro a ser retirado");
int e = s.nextInt();
while (i != e) {
Object rem = p.remover();
p2.inserir(rem);
}
while(p.inserir(p2.remover())) {
}
;
}
break;
} while (!p.estaCheia());
}
System.out.println(p);
}
}
package estacionamento;
public class Pilha<T> {
int topo;
T[] ele;
public Pilha(int max) {
ele = (T[]) new Object[max];
topo = -1;
}
public boolean estaCheia(){
return topo == ele.length-1;
}
public boolean estaVazia() {
return topo == -1;
}
public boolean inserir(T elem) {
if (!this.estaCheia()) {
topo++;
ele[topo]= elem;
return true;
}
return false;
}
public T remover() {
if (!this.estaVazia()) {
return ele[topo--];
}
return null;
}
public String toString() {
Pilha p2 = new Pilha(this.ele.length);
String s = "[";
while (!this.estaVazia()) {
T a = this.remover();
p2.inserir(a);
s += a + ",";
}
s += "]";
return s;
}
}
The implementation of the method toString()
class Pilha
is one of the worst I’ve ever seen, because he destroys the pile in question. This is very VERY VERY wrong! You are removing all the elements from the stack and saving them in p2
. It turns out that p2
goes to the garbage collector when the toString()
ends. Calling the method toString()
NEVER should produce side effects either on the object in which it was called or on any other.
Arrays do not do well with generic types and there are (or at least should be) few reasons to want to use arrays instead of lists. Use lists.
When using a list within the class Pilha
, you will no longer need the variable topo
.
Very hard you will be interested in using the package visibility, so don’t forget the modifier private
or public
.
Use descriptive variable names. That’s not what’s happening with ele
and with mov
, for example.
With that, your class code Pilha
gets like this:
package estacionamento;
import java.util.ArrayList;
import java.util.List;
public class Pilha<T> {
private final int max;
private final List<T> elementos;
public Pilha(int max) {
this.max = max;
this.elementos = new ArrayList<>(max);
}
public boolean estaCheia() {
return max == elementos.size();
}
public boolean estaVazia() {
return elementos.isEmpty();
}
public boolean inserir(T elem) {
if (this.estaCheia()) return false;
elementos.add(elem);
return true;
}
public T remover() {
return this.estaVazia()) ? null : elementos.remove(elementos.size() - 1);
}
@Override
public String toString() {
return elementos.toString();
}
}
Avoid declaring variables in a larger scope than necessary. This is happening with variables mov
which could be declared only within the do-while
and placa
which could be declared only within the else
.
When your program starts to get complicated (switch
inside do-while
inside for
) it is a good idea to divide it into smaller classes and functions. In particular, if you see that you may have an object of the type Estacionamento
and separate what’s in the case 'E'
and in the case 'S'
in smaller methods, things will get a lot easier.
Don’t violate the encapsulation of objects with things like p.ele.length
. Here, p
is an internal fact of main
and so far, so good the main
access it. However, ele
is an internal data of p
, and therefore, at this point, main
is accessing an internal data of an internal data. Accessing the internal data of an internal data is a violation of the encapsulation.
The reason you can’t use the Scanner
to read text is east of here.
If your class Pilha
is generic, so you should use it as such within the method main
. Using generic classes without generic types is bad programming practice.
You just need your p2
while removing cars. So it is convenient that the p2
is created and used only on that occasion.
There’s a break
within the do-while
that makes it always stop right at the first interaction. I think this is wrong and was for the break
be inside the case 'S'
. Again, this kind of confusion is common when you don’t enter your code.
There’s no point in turning the for
four times, considering what happens in the do-while
could add and remove cars at will (if not the problem of item 13). It makes much less sense to still use the content of for
in the removal of cars.
The while(p.inserir(p2.remover()))
will give problem when the remover
return null
.
Knowing when the program should stop, considering the for
and the do-while
is a bit tricky. Better to make the program stop only when the user asks for it (for example by typing X instead of S or And).
Trying to remove a car when the battery is already empty will not work. The same if you want to take out the third car if there is only one, or something like that. With a if
plus, we can protect ourselves from that.
To count how many times the top has been removed, you just need to increment a counter inside the while
that removes the cars.
Your code Estacionamento
gets like this:
package estacionamento;
import java.util.Scanner;
public class Estacionamento {
private final Scanner scan;
private final Pilha<String> p1;
private final Pilha<String> p2;
private int remocoesSofridas;
public Estacionamento(int max) {
this.scan = new Scanner(System.in);
this.p1 = new Pilha<>(max);
this.p2 = new Pilha<>(max);
this.remocoesSofridas = 0;
}
public static void main(String[] args) {
Estacionamento e = new Estacionamento(4);
while (e.mover()) {}
System.out.println(e);
System.out.println("Total de vezes que o topo foi removido: " + e.remocoesSofridas);
}
private boolean mover() {
System.out.println("Informe a movimentação do carro: ");
char mov = scan.nextLine().charAt(0);
switch(mov) {
case 'E':
e.adicionar();
return true;
case 'S':
e.retirar();
return true;
case 'X':
return false;
default:
System.out.println("Desculpe, não entendi isso.");
return true;
}
}
private void adicionar() {
if (p1.estaCheia()) {
System.out.println("Estacionamento cheio!");
} else {
System.out.println("Por favor, informe a placa: ");
String placa = scan.nextLine();
p1.inserir(placa);
System.out.println(placa + " foi inserido.");
}
}
private void retirar() {
Pilha<String> p2 = new Pilha<>(p1.tamanho());
System.out.println("Informe a posição do carro a ser retirado: ");
int posicao = Integer.parseInt(scan.nextLine());
if (posicao + 1 >= p1.tamanho()) {
System.out.println("Não podemos retirar o carro " + i + " pois o último é o " + (p1.tamanho() - 1) + ".");
return;
}
while (p1.tamanho() > posicao) {
String rem = p1.remover();
p2.inserir(rem);
remocoesSofridas++;
}
String placaRemovida = p2.remover();
while (!p2.estaVazia()) {
p1.inserir(p2.remover());
}
System.out.println("O carro removido foi o " + placaRemovida);
}
@Override
public String toString() {
return p1.toString();
}
public boolean estaCheia() {
return p1.estaCheia();
}
}
What is the class code
Pilha
? Why the license plate of the car is a whole instead of aString
? I see you have two batteries and only thep
is that you use to account for whether the parking lot is full, thep2
should not also be considered?– Victor Stafusa
Good evening,I used an int, because the String was not accepting inside the swtich... And the second stack serves to rearrange the cars. The first stack, emplilha normally and the second is an auxiliary
– user160874