This question already has answers here:
Using .Contains() on a property in a list
(8 answers)
Closed 5 years ago.
So, for our c# class we have to create an array of 5 objects, that have 4 properties
an int for job number
a string for job name
a string for job description
a double for expected hours of the job.
I need in my loop a way to prevent the user from entering a duplicate job number: here is my code so far. This code works, but will allow duplicate job numbers;
namespace JobDemo2
{
class Program
{
static void Main(string[] args)
{
Job[] jobbies = new Job[5];
int x;
int jobNum;
string customerName;
string description;
double hours;
const double RATE = 45.00;
for (x = 0; x < jobbies.Length; ++x)// creates array
{
GetJobData(out jobNum, out customerName, out description, out hours, jobbies);
jobbies[x] = new Job(jobNum, customerName, description, hours);
}
//Array.Sort(jobbies);
Console.WriteLine("The jobs, sorted, are: ");
for (x = 0; x < jobbies.Length; ++x) // prints the array values
{
DisplayJobs(jobbies[x]);
}
double totalRevenue = (jobbies[0].Hours + jobbies[1].Hours +
jobbies[2].Hours + jobbies[3].Hours + jobbies[4].Hours) * RATE;
Console.WriteLine();
Console.WriteLine("The total revenue projected is {0}", totalRevenue);
Console.ReadKey();
}
static void GetJobData(out int jobNum,
out string customerName, out string description, out double hours,
Job[] jobbies)
{
string inString;
Console.Write("Please enter a job number >> ");
inString = Console.ReadLine();
int.TryParse(inString, out jobNum);
Console.Write("Please enter the customer's name for this job >> ");
customerName = Console.ReadLine();
Console.Write("Please enter the job's description >> ");
description = Console.ReadLine();
Console.Write("Please enter the projected hours for the job >> ");
inString = Console.ReadLine();
double.TryParse(inString, out hours);
Console.WriteLine();
}
static void DisplayJobs(Job jobbies)
{
Console.WriteLine("{0, 5} {1, -10} {2, 6} {3, 8}",
jobbies.JobNumber, jobbies.Customer, jobbies.Description, jobbies.Hours);
}
}
class Job //object
{
private double hours;
private double price;
public const double RATE = 45.00;
public Job(int num, string cust, string desc, double hrs)
{
JobNumber = num;
Customer = cust;
Description = desc;
Hours = hrs;
}
public int JobNumber { get; set; }
public string Customer { get; set; }
public string Description { get; set; }
public double Hours
{
get
{
return hours;
}
set
{
hours = value;
price = hours * RATE;
}
}
public double Price
{
get
{
return price;
}
}
public override string ToString()
{
return (GetType() + " " + JobNumber + " " + Customer + " " +
Description + " " + Hours + " hours #" + RATE.ToString("C") +
" per hour. Total price is " + Price.ToString("C"));
}
public override bool Equals(Object e)
{
bool equal;
Job temp = (Job)e;
if (JobNumber == temp.JobNumber)
equal = true;
else
equal = false;
return equal;
}
public override int GetHashCode()
{
return JobNumber;
}
}
}
the teacher is suggesting to the class that we ad another for loop here that compares the objects. What would that for loop look like?
Here is her email:
help for the looping create a boolean variable.
for loop through your array to ask the user to enter info and set your bool variable to true.
another for loop inside to call the equals method in the class that will compare the job just entered to each object in In the array. This is where most are messing up because you must compare objects to objects and not an interger for job number to an entire object. if the objects equal set the bool to false.
while the bool is false you want to tell them they entered a wrong number and to enter again. Set the bool to true in here and go the same for loop to compare again. as long as the number stays false the user will be stuck in this while loop. when they enter a correct number it will break out.
This is homework, so I'll only give you some pointers:
Don't hand in the array (jobbies) storing the jobs to GetJobData. This method should have only one concern: getting job data. Figuring out if the data has a duplicate Id is not it's concern.
Write a helper method that checks for duplicates. What does it need? It needs all previous jobs, how many there are, and the new job it needs to validate. The following signature looks about right:
private static bool CheckIfNewJobIsValid(Job newJob,
Job[] jobs,
int jobsValidatedCount)
What does this method have to do? Well, it only needs to loop through the first jobsValidatedCount jobs in jobs and check if newJob equals any of them. If it does, bail out returning false. If the loop finishes then you can return true, no match was found.
jobsValidatedCount doesn't need to be a new counter, maybe some other already existing variable in the code can give you that info already.
Good luck!
P.D. Because this was already handed down by your teacher, I'll fix up the Equals method just a little:
public override bool Equals(Object e)
{
bool equal = false;
Job temp = e as Job;
if (Job != null && JobNumber == temp.JobNumber)
{
equal = true;
}
return equal;
}
P.D. As Alexei Levenkov points out in comments, using Equals ony for JobNumber comparisson seems a bad idea. Are any two jobs with the same JobNumber really equal regardless of the value of all other properties? That could be confusing to say the least. A better approach would be to directly check JobNumber inside CheckIfNewJobIsValid and not use Equals but I guess its use is due to academic reasons.
Related
I am a student in my first year of CIS courses, so I am a begineer. We are supposed to get input from a text file with an employee, the employee's department, hourly salary, and hours worked in given week, that looks like:
EID001, 1, 10.00, 40
EID002, 2, 10.50, 35
EID003, 3, 11.00, 30
EID004, 4, 11.50, 25
EID005, 5, 12.00, 20
EID006, 6, 12.50, 40
EID007, 7, 11.00, 25
.
.
.
(Employee ID, Department, Hourly Salary, Hours Worked)
Then separate each field into elements of an array, validate each field, and calculate the total gross pay (Hourly Salary * Hours Worked) for each of the 7 departments.
My code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
namespace Project_3_rev
{
class Program
{
const int DEPARTMENTS = 7;
const int FIELDS = 4;
static void Main(string[] args)
{
FileStream fStream = new FileStream("project3data.txt", FileMode.Open, FileAccess.Read);
StreamReader inFile = new StreamReader(fStream);
string input = "";
string[] fields = new string[FIELDS];
string employee = "";
int department = 0;
double salary = 0.00;
int hours = 0;
double totalSalary = 0.00;
int totalHours = 0;
double[] grossPayArray = new double[DEPARTMENTS];
input = inFile.ReadLine();
while(input != null)
{
fields = input.Split(',');
checkEmployee(input, fields, employee);
checkDepartment(input, fields, department);
for(int x = 1; x <= DEPARTMENTS; x++)
{
totalSalary = 0.00;
totalHours = 0;
while (department == x)
{
checkSalary(input, fields, salary, department, totalSalary);
checkHours(input, fields, hours, department, totalHours);
grossPayArray[x - 1] = totalSalary * totalHours;
}
}
input = inFile.ReadLine();
}
displayOutput(grossPayArray);
}
static void checkEmployee(string inp, string[] fieldsArray, string emp)
{
if(fieldsArray[0] == null)
Console.WriteLine("An Employee ID is invalid.");
}
static void checkDepartment(string inp, string[] fieldsArray, int dept)
{
if((!int.TryParse(fieldsArray[1], out dept)) || dept < 0 || dept > DEPARTMENTS)
{
Console.WriteLine("Department field is invalid: " + fieldsArray[1]);
}
}
static void checkSalary(string inp, string[] fieldsArray, double sal, int dept, double totSal)
{
if ((double.TryParse(fieldsArray[2], out sal)) && sal >= 10.00)
totSal = totSal * sal;
else
Console.WriteLine("Salary field is invalid: " + fieldsArray[2]);
}
static void checkHours(string inp, string[] fieldsArray, int hrs, int dept, int totHrs)
{
if ((int.TryParse(fieldsArray[3], out hrs)) && hrs >= 0)
totHrs = totHrs * hrs;
else
Console.WriteLine("Hours field is invalid: " + fieldsArray[3]);
}
static void displayOutput(double[] grossArray)
{
for(int x = 1; x <= DEPARTMENTS; x++)
{
Console.WriteLine("Department " + x + ": Gross Pay = " + grossArray[x-1]);
}
}
}
}
My output:
Department 1: Gross Pay = 0
Department 2: Gross Pay = 0
Department 3: Gross Pay = 0
Department 4: Gross Pay = 0
Department 5: Gross Pay = 0
Department 6: Gross Pay = 0
Department 7: Gross Pay = 0
Why are the Gross Pays equaling zero?
Please keep in mind that I am in my first year of computer science. I am only allowed to use what we have learned and I only know the basics. Please cut me a little slack if this code is messy or my logic is way off. Thanks ahead of time.
In these two lines of code:
totalSalary = 0.00;
totalHours = 0;
you set the values to zero. Multiplying them by anything later, will still be zero. You need to make sure you either update these fields with the correct values before multiplying, or at the very least set them to 1.
The problem of your code is this kind of function:
static void checkSalary(string inp, string[] fieldsArray, double sal, int dept, double totSal)
{
if ((double.TryParse(fieldsArray[2], out sal)) && sal >= 10.00)
totSal = totSal * sal;
else
Console.WriteLine("Salary field is invalid: " + fieldsArray[2]);
}
Is similar to this kind of function:
function Increase(int number) {
number = number + 1;
}
var number = 5;
Increase(number);
Console.WriteLine(number);
What you get is 5, instead of your expectation, 6.
In C#, it's called "passed by value". The value is passed into the function, and no modification is affected to the outside variable. In your case, toSalary will remain 0.
YOu need to change to ref double toSalary to use "pass by reference".
Other thing you need to practice is debugging technique:
Put break point.
Print the value to check.
Write unit tests to verify your methods.
Looks like you are multiplying 'grossPayArray[x - 1] = totalSalary * totalHours;' correctly, but it appears you are not updating totalSalary or totalHours from the initial value of 0.
You will need to read the file.
Split the values.
Update the variables, from zero.
Perform your function, in this case, multipling.
Hope that helps
The problem is here:
for(int x = 1; x <= DEPARTMENTS; x++)
{
totalSalary = 0.00;
totalHours = 0;
while (department == x)
{
checkSalary(input, fields, salary, department, totalSalary);
checkHours(input, fields, hours, department, totalHours);
grossPayArray[x - 1] = totalSalary * totalHours;
}
}
Notice that you never change the variables totalSalary and totalHours.
What I suggest you do is redefine your functions to only validate the input salary:
static void validateSalary(string inp, string[] fieldsArray, double sal, int dept, double totSal)
{
// you might want to rewrite this
if !((double.TryParse(fieldsArray[2], out sal)) && sal >= 10.00)
Console.WriteLine("Salary field is invalid: " + fieldsArray[2]);
}
This way, the function actually only validates the salary, as it was named. See: Single Responsibility Principle
Then set your total salary within the loop itself:
while (department == x)
{
checkSalary(input, fields, salary, department, totalSalary);
checkHours(input, fields, hours, department, totalHours);
totalSalary *= salary;
totalHours += hours;
grossPayArray[x - 1] = totalSalary * totalHours;
}
EDIT: Of course, this still has the problem that salary doesn't change within the loop.
This type of question might be better in the Code Review section of StackExchange.
Nonetheless, for your reference later in the year, here's an example solution using classes and LINQ:
To run:
var app = new App_DepartmentPay();
app.Run();
Output:
using System;
using System.IO;
using System.Linq;
namespace StackOverflow
{
public class App_DepartmentPay
{
public void Run()
{
var lines = File.ReadAllLines(#"d:\temp\payments.txt");
var payStubs = lines.Select(l => new PayStub(l)).ToList();
var departmentTotals = payStubs.GroupBy(p => p.Department).Select(g => new DepartmentTotal(g.Key, g.Sum(w => w.Pay))).ToList();
departmentTotals.ForEach(t => Console.WriteLine(t.ToString()));
}
}
public class PayStub
{
public string EmployeeId { get; private set; }
public int Department { get; private set; }
public decimal HourlyWage { get; private set; }
public decimal HoursWorked { get; private set; }
public decimal Pay
{
get
{
return HourlyWage * HoursWorked;
}
}
public PayStub(string payLine)
{
var contents = payLine.Split(',');
EmployeeId = contents[0];
Department = int.Parse(contents[1]);
HourlyWage = decimal.Parse(contents[2]);
HoursWorked = decimal.Parse(contents[3]);
}
}
public class DepartmentTotal
{
public int Department { get; set; }
public decimal TotalPay { get; set; }
public DepartmentTotal(int department, decimal pay)
{
Department = department;
TotalPay = pay;
}
public override string ToString()
{
return $"Department: {Department} \tGross Pay: {TotalPay}";
}
}
}
I have a basic class that has four attributes (Patient). In Main() I have reserved the memory for the array and before I actually create the instance, I ask the user for the account number to ensure it doesn't already exist within the array. So BinarySearch requires it to be sorted but as soon as I sort it the ability to do the for loop is lost.
//Variables
int intMaxNum = 5; //set max number of patients to 5
int intInputValue;
int intResult;
string strTempName;
int intTempAge;
double dblTempTotal;
Patient[] objectPatient = new Patient[intMaxNum]; //create an array of references
for (int x = 0; x < objectPatient.Length; ++x)
{
//attempt to create a 'shadow' class to search through and keep integrity of main class (objectPatient)
Patient[] tempobjectPatient = new Patient[intMaxNum];
tempobjectPatient = objectPatient;
if (x > 0)
{
Console.Write("\n***Next Patient***");
Array.Sort(tempobjectPatient); //this will sort both objects even though I send the temporary class only - interface impact I'm sure
}
//ask for the Patient Account number
Console.Write("\nEnter Patient Account Number: ");
ReadTheAccountNumber:
intInputValue = Convert.ToInt32(Console.ReadLine());
//create temporary class for comparison
Patient SeekPatient = new Patient();
SeekPatient.PatientNumber=intInputValue; // reset the default info with the input Pateint Account Number
//verify the Patient Account number doesn't already exist
intResult = Array.BinarySearch(tempobjectPatient, SeekPatient);
//intResult = Array.BinarySearch(objectPatient, SeekPatient);
//if (objectPatient.Equals(SeekPatient)) //Can not get the .Equals to work at all...
if (intResult >= 0)
{
Console.Write("\nSorry, Patient Account Number {0} is a duplicate.", intInputValue);
Console.Write("\nPlease re-enter the Patient Account Number: ");
goto ReadTheAccountNumber;
}
else //no match found, get the rest of the data and create the object
{
if (x > 0) { Console.Write("***Patient Account Number unique and accepted***\n"); } //looks silly to display this if entering the first record
Console.Write("Enter the Patient Name: ");
strTempName = Console.ReadLine();
Console.Write("Enter the Patient Age: ");
intTempAge = Convert.ToInt32(Console.ReadLine());
Console.Write("Enter the total annual Patient amount due: ");
dblTempTotal = Convert.ToDouble(Console.ReadLine());
objectPatient[x] = new Patient(intInputValue, strTempName, intTempAge, dblTempTotal);
}
}
Here is the class:
class Patient : IComparable
{
//Data fields
private int patientNumber;
private string patientName;
private int patientAge;
private double patientAmountDue;
//Constructors
public Patient(): this(9,"ZZZ",0,0.00)
{
}
public Patient(int _patientNumber, string _patientName, int _patientAge, double _patientAmountDue)
{
PatientNumber = _patientNumber;
PatientName = _patientName;
PatientAge = _patientAge;
PatientAmountDue = _patientAmountDue;
}
//Properties
public int PatientNumber
{
get { return patientNumber; }
set { patientNumber = value; }
}
public string PatientName
{
get { return patientName; }
set { patientName = value; }
}
public int PatientAge
{
get { return patientAge; }
set { patientAge = value; }
}
public double PatientAmountDue
{
get { return patientAmountDue; }
set { patientAmountDue = value; }
}
//Interfaces
int IComparable.CompareTo(Object o)
{
int returnVal; //temporary value container
Patient temp = (Patient)o; //create temp instance of the class
if (this.PatientNumber > temp.PatientNumber)
returnVal = 1;
else
if (this.PatientNumber < temp.PatientNumber)
returnVal = -1;
else
returnVal = 0; //exact match
return returnVal;
}
}
You can put all the patient numbers into HashSet<int> and test via Contains() if a number is allocated one:
class Patient : IComparable {
...
// Simplest, not thread safe
private static HashSet<int> s_AllocatedPatientNumbers = new HashSet<int>();
public static Boolean IsNumberAllocated(int patientNumber) {
return s_AllocatedPatientNumbers.Contains(patientNumber);
}
public int PatientNumber {
get {
return patientNumber;
}
set {
s_AllocatedPatientNumbers.Remove(patientNumber);
patientNumber = value;
s_AllocatedPatientNumbers.Add(patientNumber);
}
}
}
So whenever you need to test if the number has been allocated you have no need to create a temporal patient, sort the array etc. just one simple call:
if (Patient.IsNumberAllocated(intInputValue)) {
...
}
This
Patient[] tempobjectPatient = new Patient[intMaxNum];
creates a new array and assigns it to tempobjectPatient. But this new array is never used, because here
tempobjectPatient = objectPatient;
you immediately assign the old one to tempobjectPatient. So after this, you don't have two array instances. Both tempobjectPatient and objectPatient refer to the same instance.
You probably want:
Patient[] tempobjectPatient = (Patient[])objectPatient.Clone();
Replace the Array with a Dictionary, it is desigend to be used with unique keys:
Dictionary<int,Patient> patients = new Dictionary<int,Patient>();
while (true)
{
Console.Write("\nEnter Patient Account Number: ");
int number = Convert.ToInt32(Console.ReadLine());
if (patients.ContainsKey(number))
{
Console.Write("\nSorry, Patient Account Number {0} is a duplicate.", number);
Console.Write("\nPlease re-enter the Patient Account Number: ");
continue;
}
Console.Write("***Patient Account Number unique and accepted***\n");
Console.Write("Enter the Patient Name: ");
string name = Console.ReadLine();
Console.Write("Enter the Patient Age: ");
int age = Convert.ToInt32(Console.ReadLine());
Console.Write("Enter the total annual Patient amount due: ");
double amountDue = Convert.ToDouble(Console.ReadLine());
patients.Add(number, new Patient(number, name, age, amountDue));
}
The loop is now missing an exit condition.
EDIT:
While this does not answer the question of the title i think it is what the OP was looking for.
I am making a program that calculates an employee's wages based on their hours and pay rate. However, when I try to use the method I created in another class:
public void GrossPay(int i)
{
double GrossPay = 0.0;
GrossPay = Hours[i] * PayRate[i];
Wages[i] = GrossPay;
}
trying to use it in my main program:
public static void Payroll()
{
int employeeID = 0;
int hours = 0;
double payRate = 0.0;
double wages = 0.0;
Payroll payroll = new Payroll(employeeID, hours, payRate, wages);
for (int i = 0; i < payroll.EmployeeID.Length; i++)
{
Console.WriteLine("Employee ID: {0}", payroll.EmployeeID[i]);
Console.WriteLine("How many hours does employee {0} work?", payroll.EmployeeID[i]);
string h = Console.ReadLine();
payroll.Hours[i] = Convert.ToInt32(h);
Console.WriteLine("What is the hourly wage for employee {0}?");
string w = Console.ReadLine();
payroll.PayRate[i] = Convert.ToInt32(w);
Console.WriteLine("Employee ID: {0} \nGross Pay: {1}", payroll.EmployeeID[i], payroll.Wages[i]);
Console.ReadLine();
}
}
Gross Pay returns 0, no matter what. Please help!
You never called the method that you've built; You should invoke it before you read from the Wages property.
// ...
payroll.PayRate[i] = Convert.ToInt32(w);
payroll.GrossPay(i);
Console.WriteLine("Employee ID: {0} \nGross Pay: {1}", payroll.EmployeeID[i], payroll.Wages[i]);
// ...
This will fix your problem, but I recommend that you give object oriented paradigm a shot. I recommend that you create an Employee class, which will have properties such as Id, PayRate, Hours and a property Wages which may look like this:
public double Wages
{
get
{
return PayRate * Hours;
}
}
Then, Payroll class may hold a sequence of employees: List<Employee> Employees;
I'm unsure how to display each course the user enters. As it stands only the last course entered gets displayed. What am I not thinking about?
while (quit != "0")
{
//get user data
Console.WriteLine("Enter course # {0}:", counter);
course = Console.ReadLine();
Console.WriteLine("Enter grade value of 1-4 # {0}:", counter);
grade = Convert.ToInt32 (Console.ReadLine());
Console.WriteLine("Enter credit hours from 1-3 # {0}:",counter);
creditHours = Convert.ToInt32 (Console.ReadLine());
//calculate grade * creditHours and store in gradePoints
gradePoints = grade * creditHours;
//running total of credit hours and grades
totalGradePoints += gradePoints;
totalCreditHours += creditHours;
Console.WriteLine("Press '0' to quit or any key to continue.");
quit = Console.ReadLine();
counter++;// adds one to counter
}//end while
// calculate gpa
double GPA = totalGradePoints / totalCreditHours;
//display course(s) credit hours and gpa
Console.WriteLine("Course(s): {0}", course);
Console.WriteLine("Credit hours: {0}",totalCreditHours);
Console.WriteLine("GPA: {0:n2}",GPA);
You need to move
Console.WriteLine("Course(s): {0}", course);
inside of your while loop. You are only displaying it after the loop ends. So that's why you see the last course.
If you don't want to display them immediately, then store the courses into a collection and iterate over the collection after while loop and display them:
var courses = new List<string>();
while(...)
{
...
course = Console.ReadLine();
courses.Add(course);
...
}
foreach(var c in courses)
Console.WriteLine(c);
You're setting variables inside a while loop, therefore that same variable gets overridden with each iteration of the loop.
Instead, try using a List<T> object or an array, both of which can hold multiple values, and consider making a class for your data, since it's all associated:
class CourseData
{
public string Course { get; set; }
public int Grade { get; set; }
public nt CreditHours { get; set; }
public int GradePoints { get { reutrn Grade * CreditHours; } }
}
I'm trying to figure out how to match a candidate name with candidate votes and display the highest vote along with the candidate name.
As in how to match the two arrays I have.
I know I'm missing something but what? I've only started learing C# at home.
namespace NumberOfVotes
{
class Program
{
static void Main(string[] args)
{
int size, minVotes;
int[] numOfCandidates;
int[] numOfVotes;
double avgMarks;
string[] candidateName;
Console.WriteLine("Enter number of candidates");
size = int.Parse(Console.ReadLine());
numOfCandidates = new int[size];
candidateName = new string[size];
numOfVotes = new int[size];
for (int i = 0; i < numOfCandidates.Length; i++)
{
Console.WriteLine("Enter a Candidate Name");
candidateName[i] = Console.ReadLine();
Console.WriteLine("Enter number of votes thus far");
numOfVotes[i] = int.Parse(Console.ReadLine());
}
int max = numOfVotes.Max();
avgMarks = numOfVotes.Average();
minVotes = numOfVotes.Min();
Console.WriteLine("Average votes: {0}", avgMarks);
Console.WriteLine("Min number of votes is: {0}", minVotes);
}
}
}
See these kind of things you can do with thinking about it with your head. StackOverflow isn't a website to post your problem if you're stuck, only if the problem you have needs a solution which can help other people.
This would work(most straightfoward approach to me):
int maxIndex = -1;
int max = -1;
for (int i = 0; i < numOfCandidates.Length; i++)
{
Console.WriteLine("Enter a Candidate Name");
candidateName[i] = Console.ReadLine();
Console.WriteLine("Enter number of votes thus far");
int num = int.Parse(Console.ReadLine()); // <-- unsafe
// just check it every time, if the number is greater than the previous maximum, update it.
if (num > max)
{
max = num;
maxIndex = i;
}
numOfVotes[i] = num;
}
Console.WriteLine("Candidate {0}, with {1} votes, has the most votes", candidateName[maxIndex], max);
However, if you want more things to calculate (like who has the least votes) without doing these kind of things, you should use a Dictionary<string, int>. That's a string associated with a number, a name associated with votes.
(More info about that here: http://www.dotnetperls.com/dictionary)
You should use a Dictionary for this:
static void Main(string[] args)
{
var candidates = new Dictionary<string, int>();
Console.WriteLine("Enter number of candidates");
var size = int.Parse(Console.ReadLine());
for (int i = 0; i < size; i++)
{
Console.WriteLine("Enter a Candidate Name");
var name = Console.ReadLine();
Console.WriteLine("Enter number of votes thus far");
var votes = int.Parse(Console.ReadLine());
candidates.Add(name, votes);
}
Console.WriteLine("Average votes: {0}", candidates.Average(entry => entry.Value));
Console.WriteLine("Min number of votes is: {0}", candidates.Min(entry => entry.Value));
}
You should probably use dictionary instead, but if you want to use array, here's how to do it :
avgMarks = numOfVotes.Average();
int avgIndex = numOfVotes.ToList().IndexOf(avgMarks);
Console.WriteLine("Average votes: {0} Candidate Names: {1}", avgMarks, candidateName[avgIndex]);
Your code just works fine. What you are looking for is the index of the array having highest number of votes. This index will be also useful to get the candidateName having highest number of vote. So, to get that index simply use the maximum value you got from this line :
int max = numOfVotes.Max();
and then use IndexOf static method to find the index of max in your array. For that try this line of code :
int index = Array.IndexOf<int>(numOfVotes, max);
Now simply print out the candidateName and highest number of votes as below :
Console.WriteLine(candidateName[index] + " has highest number of vote : " + numOfVotes[index] );
You can have a clean conception about Array.IndexOf() from DotNetPerls and MSDN
The solution to the problem, as it is, is to do something like this:
int indexOfWinner = Array.IndexOf(numOfVotes, numOfVotes.Max());
string winner = candidateName[indexOfWinner];
I don't know how far along in your C# and programming education you are (OOP and suchlike), so a couple of points you may find obvious or not:
you should use generic collections and not primitive arrays (List<> in this case).
you should encapsulate all this into a class.
This is how I would do it:
class Program
{
static void Main(string[] args) {
Candidates c = new Candidates("foo", "bar", "baz");
Random rand = new Random();
c.addVote(0, rand.Next(100));
c.addVote(1, rand.Next(100));
c.addVote(2, rand.Next(100));
Console.WriteLine(c.getWinner());
Console.WriteLine("number of votes:");
Console.WriteLine(c[0] + ": " + c[0].numberOfVotes);
Console.WriteLine(c[1] + ": " + c[1].numberOfVotes);
Console.WriteLine(c[2] + ": " + c[2].numberOfVotes);
}
}
class Candidates
{
private List<Candidate> candidates;
public Candidate this[string name] {
get {
return candidates.First(v => v.name == name);
}
}
public Candidate this[int index] {
get {
return candidates[index];
}
}
public Candidates(string firstCandidate, params string[] candidates) { //this is done to disable an empty constructor call
//and also allow multiple candidates
this.candidates = new List<Candidate>(candidates.Length);
this.candidates.Add(new Candidate(firstCandidate));
foreach(var c in candidates) {
this.candidates.Add(new Candidate(c));
}
}
public void addVote(int candidateNumber, int numberOfVotes = 1) {
candidates[candidateNumber].numberOfVotes += numberOfVotes;
}
public Candidate getWinner() {
candidates.Sort((candidate1, candidate2) => candidate2.numberOfVotes.CompareTo(candidate1.numberOfVotes));
return candidates[0];
}
}
class Candidate
{
public string name { get; private set; }
public int numberOfVotes { get; set; }
public Candidate(string name) {
this.name = name;
this.numberOfVotes = 0;
}
public override string ToString() {
return name;
}
}