Something is wrong with my code, could anyone help, thanks in advance.
using System;
using System.Collections.Generic;
using System.Text;
namespace ConsoleApplication1
{
class Bus
{
int busNo;
string startDepot, endDepot;
float departTime;
public void Update()
{
Console.Write("Entert Bus No.:");
busNo = int.Parse(Console.ReadLine());
Console.Write("Enter Start depot: ");
startDepot = Console.ReadLine();
Console.Write("Enter End depot: ");
endDepot = Console.ReadLine();
Console.Write("Enter depart time: ");
departTime = float.Parse(Console.ReadLine());
}
public void Display()
{
Console.WriteLine("Bus No. is " + busNo);
Console.WriteLine("Start depot is " + startDepot);
Console.WriteLine("End depot is " + endDepot);
Console.WriteLine("Depart time is " + departTime);
}
}
class Program
{
static void Main(string[] args)
{
char choice;
do
{
int num=0;
Console.WriteLine("a) Update b) Display e) Exit");
Console.Write("Enter choice: ");
choice = char.Parse(Console.ReadLine());
switch (choice)
{
case 'a':
Console.WriteLine("Enter Number of Bus");
num = int.Parse(Console.ReadLine());
Bus[] group1 = new Bus[num]; //dynamic sizing
for (int row = 0; row < num; row++)
{
group1[row] = new Bus();
group1[row].Update();
}
break;
case 'b':
Console.WriteLine("Display all Bus(es)");
Bus[] group1 = new Bus[num]; //Something is wrong here !
for (int row = 0; row < num; row++)
{
//group1[row] = new Bus();
group1[row].Display(); //stuck
}
break;
default: Console.WriteLine("No such choice"); break;
}
} while (choice != 'e');
}
}
}
Guest UserPosted Jan 7, 2008, 6:46 PM
Guest UserPosted Jan 7, 2008, 6:43 PM
using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
namespace ConsoleApplication3
{
class Bus:IComparable
{
public int busNo;
string startDepot, endDepot;
float departTime;
public Bus(int n)
{
busNo = n;
}
public void Update()
{
Console.Write("Enter Start depot: ");
startDepot = Console.ReadLine();
Console.Write("Enter End depot: ");
endDepot = Console.ReadLine();
Console.Write("Enter depart time: ");
departTime = float.Parse(Console.ReadLine());
}
public void Display()
{
Console.WriteLine("Bus No. is " + busNo);
Console.WriteLine("Start depot is " + startDepot);
Console.WriteLine("End depot is " + endDepot);
Console.WriteLine("Depart time is " + departTime);
}
public int CompareTo(Object otherBus)
{
return busNo.CompareTo(((Bus)otherBus).busNo);
}
}
class Program
{
static void Main(string[] args)
{
char choice;
SortedList group1 = new SortedList();
int num = 0;
do
{
Console.WriteLine("a) Update b) Display d) Delete e) Exit");
Console.Write("Enter choice: ");
choice = char.Parse(Console.ReadLine());
switch (choice)
{
case 'a':
Console.WriteLine("Enter Number of Bus");
num = int.Parse(Console.ReadLine());
if (!(group1.ContainsKey(num)))
{
Bus b = new Bus(num);
group1.Add(num, b);
b.Update();
}
else
Console.WriteLine("Bus " + num + " is already in the list!");
break;
case 'b':
Console.WriteLine("Display all Bus(es)");
for (int i = 0; i < group1.Count; i++)
{
Bus b = (Bus)(group1.GetByIndex(i));
b.Display();
}
break;
case 'd':
Console.WriteLine("Enter Number of Bus");
num = int.Parse(Console.ReadLine());
if (group1.ContainsKey(num))
{
group1.Remove(num);
Console.WriteLine("Bus " + num + " has been removed from the list.");
}
else
Console.WriteLine("Bus " + num + " is not in the list!");
break;
case 'e':
break;
default:
Console.WriteLine("No such choice"); break;
}
} while (choice != 'e');
}
}
}
First of all, I removed the standard array and switched it over to a collection, in this case a SortedList. Using a standard collection object opens up a lot of functionality, including methods like ContainsKey to find a particular entry. Also, your method of re-creating the array when a new Bus is added may be functional but it's very inefficient in terms of performance and program flow. SortedList will take care of the sorting and storage for you.
When I ran your code and tried to add a new Bus, the program prompted me twice for the bus number. This was because there was no code in place to assign the number to the Bus object. I fixed this by adding a public constructor to the Bus object which takes the bus number as a parameter. Now the busNo is assigned when the Bus object is created, so there's no need to prompt the user for it again.
Switching to a standard collection object allowed me to add a new bit of functionality to your app - deleting bus entries! Again, this is handled by the SortedList, as it has a method called Remove() which lets you delete entries from the list.
You asked about preventing duplicate entries from appearing in the list... SortedList doesn't allow you to add entries with duplicate keys (and in this case I'm using the bus number as the key), it will throw an Exception if you try. The code here is proactive in that it will check to see if a bus number is already in the list (using ContainsKey()) before using Add() to put the new entry in the list.
KeithPosted Jan 3, 2008, 1:11 PM
Based on the above code, how do I modify such that the bus no. is a unique one ?
Example, my Bus no. is 101 and it can only accept once.
Anyone out there could help ?
KeithPosted Jan 1, 2008, 10:54 PM
Thanks Dave, will follow your sequence to read up the followings.
Unfortunately my lecturer did not cover quite enough for us to understand in details.
DavePosted Jan 1, 2008, 8:17 PM
A quick note on CompareTo(). It returns either 1, 0 or -1. 0 if the objects are equal, 1 if the instance calling it is is bigger and -1 if smaller.
Regarding the actual parameter ((Bus)otherBus).busNo, to implement IComparable, CompareTo always takes Object as its formal parameter type. If you look at where I defined it in the code, the heading was CompareTo(Object otherBus).
Now inside that method, I am calling CompareTo() again. But this time I am calling the CompareTo() method of the int type.(aside: the int type has two versions of the CompareTo() method. One takes Object as a parameter and the other takes an int as a parameter. That way, it implements IComparable and also has an overloaded version that takes int as a parameter to make it easier to use for one-off comparisons). I am doing this because the array will be ordering on BusNo.s, so we need to be able to compare each BusNo with each other BusNo. So, to sum up so far, when we call CompareTo() of the class Bus, the incoming object of that method will be another Bus and the method will compare the BusNo.s of the two buses i.e. the BusNo of the Bus calling CompareTo() and the BusNo of the Bus which is passed to CompareTo().
Finally, when the Bus is passed to CompareTo(Object otherBus), we need to cast it to the Bus type. Take as an example:
busOne.CompareTo(busTwo)
busTwo is of the type Bus, but it is also of the type Object (everything in C# derives from the Object class). That is why it can be successfully passed to a method which takes Object as a parameter. When it comes into that method, it is coerced to the Object type. In order to expose its BusNo attribute, we have to explicitly cast it back to the Bus type.
We can do that simply by this code - (Bus)otherBus
You need to learn about casting if you have not seen anything like that before. Now, I just take it a step further to expose the BusNo attribute. By placing it all in brakets - ((Bus)otherBus) we know that there is a Bus inside the brackets. So we can access its BusNo in the normal way i.e. ((Bus)otherBus).busNo
There's quite a lot of concepts in all there for you to digest, and I'm not sure how much you know. So, as background reading, I'd start with casting, then interfaces and then IComparable.
Hope this helps.
KeithPosted Jan 1, 2008, 1:59 PM
Thank you Dave, your code is great, short and simple to understand.
I will heed your advise to learn and research on IComparable interface to user Array.Sort().
But could you explain on this line, return busNo.CompareTo(((Bus)otherBus).busNo); ?
Especially ((Bus)otherBus).busNo
Thanks.
DavePosted Dec 31, 2007, 7:45 AM
I have altered Bus so that it implements IComparable. You will notice a new public method CompareTo(Object otherBus)
I made the busNo variable public (although I really should have created a public Property to expose that variable - better programming pactice).
I was then able to call Array.Sort(group1); in case 'b'
Here's the code:
KeithPosted Dec 30, 2007, 11:41 PM
I am able to run this program , however if I need to sort the display according to the bus number, how do I apply the Array.Sort Command ?
Anyone out there could advise ?
KeithPosted Dec 30, 2007, 9:50 PM
Hi Dave,
Thank you for your clear and precise explanation.
The program works fantastically great after you have corrected them !
DavePosted Dec 30, 2007, 9:35 PM
1st, move Bus[] group1 = null; out of the do loop. I suggest putting it up with the declaration of Choice at the top of the Main() method. The reason - every time the do loop iterates, group1 is essentially wiped clean and allocated a fresh memory location. You want to be working with an existing array when you select 'b'.
2nd, remove the line group1 = new Bus[num]; from inside case 'b'. Same reason as above.
3rd, also move int num = 0; out of the do loop. By declaring it and initialising it inside the loop, it is assigned 0 with every iteration. As such, when you select case 'b', it thinks the array group1 does not have any items in it.
The code with fixes:
KeithPosted Dec 30, 2007, 9:13 PM
Hi Alan,
Thanks for your help. Although there is no error now since the declaration is done outside, but how do I go about displaying the records in case 'b'. It doesn't seem to work, can you help, thanks.
AlanPosted Dec 30, 2007, 7:29 PM
The compiler is complainng because you've already declared another variable called group1 within the switch statement, namely the one in the case 'a' section.
To deal with this, I'd declare group1 outside the switch statement altogther:
static void Main(string[] args)
{
char choice;
do
{
int num=0;
Console.WriteLine("a) Update b) Display e) Exit");
Console.Write("Enter choice: ");
choice = char.Parse(Console.ReadLine());
// declare it here say
Bus[] group1 = null;
switch (choice)
{
case 'a':
Console.WriteLine("Enter Number of Bus");
num = int.Parse(Console.ReadLine());
group1 = new Bus[num]; //dynamic sizing
for (int row = 0; row < num; row++)
{
group1[row] = new Bus();
group1[row].Update();
}
break;
case 'b':
Console.WriteLine("Display all Bus(es)");
group1 = new Bus[num];
for (int row = 0; row < num; row++)
{
//group1[row] = new Bus();
group1[row].Display(); //stuck
}
break;
default: Console.WriteLine("No such choice"); break;
}
} while (choice != 'e');
}