In this program, I have 2 classes Application and Customer. I want to initialize Standard Fare with some value which should be entered by the user. Standard Fare field is in Customer class.
I did this, but it is not showing the desired result. When Calculate function is called The Value of Standard fare is becoming zero.
When I initialize the value of STANDARD_FARE in Customer class itself, then the program is working as desired.
How can I input the value given by the user to STANDARD_FARE?
Also methods like GetAge(), GetPassNo() in Application class is not returning the value of the same.
class Application
{
private static int Nop ;
private static double TotalFare=0;
Customer cust= new Customer();
static void Main(string[] args)
{
Application obj = new Application();
Console.Write("Enter the STANDARD RATE of the tour ");
obj.cust.StandardFare = int.Parse(Console.ReadLine());
a:
Console.Clear();
Console.WriteLine("Enter the number of passengers");
Nop = int.Parse(Console.ReadLine());
Application[] app = new Application[Nop];
if (Nop <= 0)
{
Console.WriteLine("Please enter a valid number of passengers");
Console.ReadKey();
goto a;
}
for (int i = 0; i < Nop; i++)
{
app[i] = new Application();
app[i].GetInformationFromCust();
}
for (int j = 0; j < Nop; j++)
{
app[j].cust.Display();
}
}
public int GetInformationFromCust()
{
b:
Console.Clear();
int slen = 0;
Console.WriteLine("Enter the title of the passenger");
cust.Customer_Title = Console.ReadLine();
Console.WriteLine("\r\nEnter passenger's First name :");
cust.Customer_FName = Console.ReadLine();
Console.WriteLine("\r\nEnter passenger's Last name :");
cust.Customer_LName = Console.ReadLine();
slen = cust.Customer_FName.Length + cust.Customer_LName.Length;
if (slen < 5 || slen > 15)
{
Console.WriteLine("\r\nName should be between 5 to 15 characters, Please try again ");
Console.ReadLine();
goto b;
}
c:
long x = 0, len = 0;
Console.WriteLine("\r\nEnter the passport number of the passenger ");
cust.CustomerPassNo = int.Parse(Console.ReadLine());
x = cust.CustomerPassNo;
while (x > 0)
{
x = x / 10;
++len;
}
if (len != 8)
{
Console.WriteLine("\r\nInvalid passport number, passport should be of 8 digits ");
goto c;
}
d:
Console.WriteLine("\r\nEnter the age of the passenger :");
cust.Customer_Age = int.Parse(Console.ReadLine());
if (cust.Customer_Age < 0)
{
Console.WriteLine("\r\nInvalid age, please enter a valid age ");
goto d;
}
cust.CalculatePrice();
return 0;
}
public int GetAge()
{
return cust.Customer_Age;
}
public double GetAirFare()
{
return cust.CustomerTicket ;
}
public long GetPassportNo()
{
return cust.CustomerPassNo;
}
public string GetTitle()
{
return cust.Customer_Title;
}
}
class Customer
{
const double K_DISCOUNT = 0.10;
const double S_DISCOUNT = 0.20;
private double STANDARD_FARE;
private string CustomerName { get; set; }
private int CustomerAge;
private string CustomerFName;
private string CustomerLName;
private long CustomerPassport;
private double CustomerPrice;
private string CustomerTitle;
private double KidDiscount;
private double SeniorDiscount;
public Customer()
{
this.KidDiscount = K_DISCOUNT;
this.SeniorDiscount = S_DISCOUNT;
}
public double StandardFare
{
get { return STANDARD_FARE; }
set { STANDARD_FARE = value; }
}
public int Customer_Age
{
get { return CustomerAge; }
set { CustomerAge = value; }
}
public string Customer_Title
{
get { return CustomerTitle; }
set { CustomerTitle = value; }
}
public string Customer_FName
{
get { return CustomerFName; }
set { CustomerFName = value; }
}
public string Customer_LName
{
get { return CustomerLName; }
set { CustomerLName = value; }
}
public long CustomerPassNo
{
get { return CustomerPassport; }
set { CustomerPassport = value; }
}
public double CustomerTicket
{
get { return CustomerPrice; }
set { CustomerPrice = value; }
}
public int CalculatePrice()
{
if (CustomerAge < 3)
{
CustomerPrice = 0;
}
else if (CustomerAge >= 3 && CustomerAge < 18)
{
CustomerPrice = STANDARD_FARE - (STANDARD_FARE * KidDiscount);
}
else if (CustomerAge > 65)
{
CustomerPrice = STANDARD_FARE - (STANDARD_FARE * SeniorDiscount);
}
else
{
CustomerPrice = STANDARD_FARE;
}
return 0;
}
public void Display()
{
//some code here
}
}
You are populating your array app with instances of Application that still have the default STANDARD_FARE value (which is 0.0), because you have never set it on those instances. You only set it on the obj.cust instance, which you never again use. Because STANDARD_FARE is an instance variable, changes to it have no affect on other (or future) instances.
You have the same problem in reverse with all the Application.Get* functions; they are getting properties of an object (obj.cust) that has never had any properties set, other than StandardFare/STANDARD_FARE.
The most obvious fix is to do away with obj and obj.cust entirely - they have no use other than to be confusing - and make STANDARD_FARE a static variable (and its setter StandardFare a static property).
BTW, your naming conventions are terrible and inconsistent; if I were your grader I'd dock you points for using unclear variable names(app, nop), and for using ALL_CAPS for non-constants (STANDARD_FARE). I'd also object to using a private auto-backed property (CustomerName, which is also never used) instead of simply a private variable, for not using auto-backed properties elsewhere (StandardFare as an explicitly-coded public getter and setter for STANDARD_FARE, etc.), and for copying constant values into non-settable instance variables (K_DISCOUNT to KidDiscount; just use the constant directly, or at least make KidDiscount static and add some non-private access to it). As others have mentioned, you of course should not be using goto in place of loops. I'll also mention the error-prone and inefficient checking the length of the passport number by repeated division instead of simply checking whether it's less than 99999999 (in theory, passport numbers might start with a zero, which would look like less than 8 digits after parsing, but you could also make sure it's greater than 10000000 if you want).
Related
I have an Invoice class and a main class. I have an array of objects within my main class and I want to multiply the quantity(7) by the price(57.88). How do you select different elements within an object array. I have shown my main and my invoice classes. I'm looking for an example on how I would go about this pertaining to what I have done with my code.
static void Main(string[] args)
{
var tools = new[]
{
new Invoice(83,"Electric Sander", 7, 57.88M),
new Invoice(24, "Power Saw", 18, 99.99M),
new Invoice(7, "Sledge Hammer", 11, 21.50M),
new Invoice(77, "Hammer", 76, 11.99M),
new Invoice(39, "Lawn Mower", 3, 79.50M),
new Invoice(68, "Screwdriver", 106, 6.99M),
new Invoice(56, "Jig Saw", 21, 11.00M),
new Invoice(3, "Wrench", 34, 7.50M)
};
Console.WriteLine("Original Array: ");
foreach (var tool in tools)
{
Console.WriteLine(tool);
}
var descriptionSort = from t in tools
orderby t.PartDescription
select t;
}
public class Invoice
{
// declare variables for Invoice object
private int quantityValue;
private decimal priceValue;
// auto-implemented property PartNumber
public int PartNumber { get; set; }
// auto-implemented property PartDescription
public string PartDescription { get; set; }
// four-argument constructor
public Invoice(int part, string description,
int count, decimal pricePerItem)
{
PartNumber = part;
PartDescription = description;
Quantity = count;
Price = pricePerItem;
}
// property for quantityValue; ensures value is positive
public int Quantity
{
get
{
return quantityValue;
}
set
{
if (value > 0) // determine whether quantity is positive
{
quantityValue = value; // valid quantity assigned
}
}
}
// property for pricePerItemValue; ensures value is positive
public decimal Price
{
get
{
return priceValue;
}
set
{
if (value >= 0M) // determine whether price is non-negative
{
priceValue = value; // valid price assigned
}
}
}
// return string containing the fields in the Invoice in a nice format;
// left justify each field, and give large enough spaces so
// all the columns line up
public override string ToString() =>
$"{PartNumber,-5} {PartDescription,-20} {Quantity,-5} {Price,6:C}";
}
You could always just add a getter to your Invoice class
public decimal TotalPrice
{
get
{
return Price * Quantity;
}
}
tools[0].TotalPrice to get the first element in your array
You already "select different objects" here:
foreach (var tool in tools)
{
Console.WriteLine(tool);
}
You could add to this, and even keep a total:
double total = 0;
foreach (var tool in tools)
{
Console.WriteLine($"{tool.Quantity} of {tool.Name} (costing {tool.Price} each) totals {tool.Quantity * tool.Price}");
total += (tool.Quatity * tool.Price);
}
Console.WriteLine("Invoice total " + total);
You can also access arrays etc by index, typical examples being:
for(int x = 0; x < tools.Length; x++)
Console.WriteLine(tools[x].Price);
for(int x = tools.Length-1; x >= 0; x--)
Console.WriteLine(tools[x].Price);
This is a common requirement to do that they have a shortcut - you type forTABTABorforr`TABTAB VS will insert skeletons of these for you
EDITED: (editd the binary search method)
I am using c sharp. I have a sorted list that has some values in it such as name and their quantity.
My code:
using System;
using System.Collections.Generic;
using static System.Console;
namespace InventoryManagementSystem
{
public class Tool
{
public Tool(string name, int quantity)
{
this.Name = name;
this.Quantity = quantity;
}
public string Name { get; }
public int Quantity { get; }
public int CompareTo(SortedList<string, Tool> other, String name)
{
return; //not sure how to write this properly
}
}
}
//toolitems class
public class ToolItems
{
SortedList<string, Tool> gardeningTools = new SortedList<string, Tool>();
public void gardeningToolData()
{
Tool gardeningTool1 = new Tool("Garden gloves", 50);
gardeningTools.Add(gardeningTool1.Name, gardeningTool1);
WriteLine("Please enter a name of the tool");
String user = ReadLine();
int number = binarySearch(user);
}
public int binarySearch(String user)
{
while (low <= high)
{
mid = (high + low) / 2;
if (gardeningTools.Values[high].Name.CompareTo(user) == 0)
{
WriteLine("mid is: " + mid);
return mid;
}
else if (gardeningTools.Values[high].Name.CompareTo(user) > 0)
high = mid - 1;
else
low = mid + 1;
}
return -1;
}
Edited: My code works now except it returns the index 0 if the value is between first and last index of list. How can I get the exact index from the sortedlist depending on what name user search for?
In short all I am trying to do is when user enter some string value and if it matches in the sortedlist (which we search using binary search algorithm) we get the index of that value from sorted list and update the quantity of that specific value (If user chose 'A' and it is at index 0 ("A", 5) then we ask user for how many A you want to borrow and user say 2, so the quantity gets update to 3 now.
SortedList is implementing IDictionary. Basically, your sorted list will have methods that IDictionary has. You can check this link Microsoft Docs SortedList out.
In your question, my understanding is you want to find your Tool object from SortedList and update its quantity. I am not directly answering your question about how to write CompareTo method but instead proposing alternative solution to how you can achieve your actual goal. Please find below sample code:
Slight change on your Tool class, added setter to Quantity property and removed your CompareTo method:
public class Tool
{
public Tool(string name, int quantity)
{
this.Name = name;
this.Quantity = quantity;
}
public string Name { get; }
public int Quantity { get; set; }
}
And here your console app part how to find and update quantity with user inputs:
SortedList<string, Tool> gardeningTools = new SortedList<string, Tool>();
public void gardeningToolData()
{
var gardeningTool = new Tool("Garden gloves", 50);
gardeningTools.Add(gardeningTool.Name, gardeningTool);
Console.WriteLine("Please enter a name of the tool");
var toolName = Console.ReadLine();
Console.WriteLine("Please enter quantity of tools");
var quantity = int.Parse(Console.ReadLine()); // Ideally you should check whether user enters valid integer
if(gardeningTools.TryGetValue(toolName, out var tool))
{
// You should check here whether you have sufficient quantity before decreasing quantity
tool.Quantity -= quantity;
}
}
UPDATE
I've modified this so that I'm also answering how to implement compareto.
public class Tool : IComparable<Tool>, IComparable<string>
{
public Tool(string name, int quantity)
{
this.Name = name;
this.Quantity = quantity;
}
public string Name { get; }
public int Quantity { get; }
public int CompareTo(Tool other)
{
// You could manually compare rather than this
// return this.Name == other?.Name ? 0 : this.Name < other?.Name ? -1 : 1;
return string.Compare(this.Name, other?.Name);
}
public int CompareTo(string other) {
return string.Compare(this.Name, other);
}
}
public int binarySearch(String user)
{
while (low <= high)
{
mid = (high + low) / 2;
switch(gardeningTools.Values[mid].CompareTo(user)) {
case 0: // Found
WriteLine("mid is: " + mid);
return mid;
case -1: // Mid is too small.
low = mid + 1;
break;
default: // Mid is too high
high = mid - 1;
break;
}
// probably should also check that high and low != at this point
return -1;
}
First I would like to say sorry that I didn't use english but you will have the general idea of what I am trying to do.
Create class subjects variables and characteristics / properties:
- kodiILendes
- emriILendes
- nota
The method Main should make it possible for users to introduce these data, code
file, the file name and grade.
You need to create objects for 5 subjects
Make use of accessories (get and set), to mark So while you should assign grades should not be
less than 5 and also must not be greater than 10.
And to submit your average for this semester format, p.sh .: "Your Average
It is 9.3 ".
class Lendet
{
public int kodiIlendes;
public string emriIlendes;
private int nota;
public int Nota {
get {
return nota;
}
set {
if (value > 5 && value <= 10)
{
nota = value;
}
else {
Console.WriteLine("Nota duhet te jet me e > se 5 dhe nuk duhet te jet me e > se 10 ");
}
}
}
}
static void Main(string[] args)
{
Lendet Anglisht = new Lendet();
Anglisht.kodiIlendes = 100;
Anglisht.emriIlendes = "Anglisht";
Anglisht.Nota = 10;
}
Now lets imagine I created the 5 objects and I want to find the average.How can I do that ?
One way is like this Console.WriteLine(x.Nota+y.Nota+z.Nota+b.Nota+c.Nota/5)
class Lendet
{
public int kodiIlendes;
public string emriIlendes;
public static float sum;
public static int count;
public Lendet()
{
count++;
}
private int nota;
public int Nota {
get {
return nota;
}
set {
if (value > 5 && value <= 10)
{
sum =sum+value;
nota = value;
}
else {
Console.WriteLine("Nota duhet te jet me e > se 5 dhe nuk duhet te jet me e > se 10 ");
}
}
}
}
static void Main(string[] args)
{
//create object1
// create object2
//......create object n
Console.WriteLine(Lendet.sum/Lendet.count);
}
create two static variables, one for count of objects created and other for sum. Divide second by first to get the average.
My approach, with history:
class Lendet
{
public int Nota { get; private set; }
public Lendet(int nota)
{
this.Nota = nota;
LendetHistory.Add(this);
}
}
static class LendetHistory
{
private static List<Lendet> lendets = new List<Lendet>();
public static float Average()
{
if(lendets.Count < 1)
return 0;
return lendets.Select(s => s.Nota).Average();
}
public static void Add(Lendet lendet)
{
lendets.Add(lendet);
}
}
use in code:
var k = new Lendet(10);
var c = new Lendet(20);
Console.WriteLine(LendetHistory.Average());
and with that approach you can expand your logic
I know this is probably similar to some other posts, but I'm not quite sure what I'm doing wrong here. As an FYI, I'm new to programming and still trying to learn proper flow.
Here is the code, the exception occurs at "MyFriends[i].Name = friendName".
using System;
using System.Collections;
namespace FriendList
{
class FriendList
{
static public Friend[] MyFriends = new Friend[2];
public static void Main()
{
string friendName;
string friendPhone, friendMonth, friendDay, friendYear;
int intMonth, intDay, intYear;
for (int i = 0; i < 2; ++i)
{
Console.Write("enter name");
friendName = Console.ReadLine();
MyFriends[i].Name = friendName;
Console.Write("phone");
friendPhone = Console.ReadLine();
MyFriends[i].Phone = friendPhone;
Console.WriteLine("Enter Month: ");
friendMonth = Console.ReadLine();
intMonth = Convert.ToInt32(friendMonth);
MyFriends[i].Month = intMonth;
Console.WriteLine("Enter Day: ");
friendDay = Console.ReadLine();
intDay = Convert.ToInt32(friendDay);
MyFriends[i].Day = intDay;
Console.WriteLine("Entery Year: ");
friendYear = Console.ReadLine();
intYear = Convert.ToInt32(friendYear);
MyFriends[i].Year = intYear;
}
for (int i = 0; i < 2; ++i)
{
string information = string.Format("first name: {0}, phone {1}", MyFriends[i].Name, MyFriends[i].Phone);
Console.WriteLine(information);
}
Console.Read();
}
}
class Friend
{
string _Name = string.Empty, _Phone = string.Empty;
int _Day = 0, _Month = 0, _Year = 0;
public string Name
{
get { return _Name; }
set { _Name = value; }
}
public string Phone
{
get { return _Phone; }
set { _Phone = value; }
}
public int Month
{
get { return _Month; }
set { _Month = value; }
}
public int Day
{
get{ return _Day; }
set{ _Day = value ; }
}
public int Year
{
get { return _Year;}
set { _Year = value; }
}
public Friend()
{ }
}
}
Thank you for your guidance!
Your friend array is initialized empty. So MyFriends[i] will hit a null reference, which is another way to say you are trying to access something that doesn't exist.
In other words, you have an Array with slots for two friends, but both slots are empty. You still need to have a friend in each slot before you can use their properties, such as Name, Phone etc.
Simply start the for loop like this:
for (int i = 0; i < 2; ++i)
{
MyFriend[i] = new Friend(); //or pass parameters as required by the constructor
// rest of your code goes here
}
And things will be fine. This way, you are adding a friend to the slot you will be using.
You've created an array with two elements, but you have set the elements to any value. They are both null:
static public Friend[] MyFriends = new Friend[2];
So, when you try to use MyFriends[i] from the array, you're actually getting null.
MyFriends[i].Name = friendName;
That where your NullReferenceException came from.
You'll have to initialize the members of the array. For example:
for (int i = 0; i < MyFriends.Length; i++)
{
// Put a new Friend object in the array.
MyFriends[i] = new Friend();
// ...
When creating collections, they're populated with default values of the target type, and the default value for any reference type if null. So to solve your problem you'd have to initialize items in the array before accessing them:
....
for (int i = 0; i < 2; ++i)
{
MyFriends[i] = new Friend();
...
MyFriends is an array of Friend class.
each element in the array needs to be initialized with a friend constructor so it will be allocated with a memory.
I have the following class:
public class test
{
private int i;
public test(int in)
{
i = in;
}
public int testint;
{
get { return i; }
set { i = testint; }
}
}
And the following code:
test[] data = new test[3];
for(int j = 0; j < 3; j++)
{
data[i] = new test(0);
data[i].testint = int.Parse(Console.ReadLine());
}
Console.WriteLine(test[0].testint);
Console.WriteLine(test[1].testint);
Console.WriteLine(test[2].testint);
When I run this program and type in 1, 2, 3 as the input, the output is 0, 0, 0. I don't understand why the get or set seem to be not working. If I initialize the array elements with a value other than 0, the output will be that. The data[i].testint = int.Parse(Console.ReadLine()); seems to not be working. How would I go about doing something like that?
Change the set method to this:
public int testint
{
get { return i; }
set { i = value; }
}
You setter is incorrect. It should be:
set { i = value; }
You had:
set { i = testint; }
Which only triggers the getter, which gets from i, so in the end your setter was doing i = i .
In a setter, the value keyword contains the new candidate value for the property. value's type equals the property's. I say candidate value because you can validate it and choose to not apply it.
In your case, you were not applying the value.
Update
Also, when defining getters and setters, no semicolon should be used. Code, then, would look like this:
public int testint
{
get { return i; }
set { i = value; }
}
I see two errors in this code:
public int testint;
{
get { return i; }
set { i = testint; }
}
There should be no semicolon after testint at the top. Also, set needs to assign using value, like this:
public int testint
{
get { return i; }
set { i = value; }
}
Change your setter to say:
set { i = value; }
value corresponds to the value you send to set the variable.
Here's simple way.
public int TestInt {get; set;}