C#, Extensive wage calculation with Arrays - c#

Here's a description of what I need to do:
Write a program that first initializes arrays via user input with the names and wages of all employees, then prompts the user for the hours worked for each employee and computes their regular pay, overtime pay, gross income, federal tax deduction (10% of gross), state tax deduction (5% of gross), and net income. After the last employee is processed, the program displays totals for regular pay and overtime pay and the names and gross incomes for the employees that earned the most and least amount.
I'm stuck at the if-else statement, I'm fairly new to c# and still don't know a lot, basically I'm stuck, and I'm in a rush to get this done, I would appreciate any help on this.
using System;
using static System.Console;
namespace Exercise3
{
class ArrayCalculations
{
static void Main(string[] args)
{
double hours,
regularPay,
overtimePay,
grossPay,
netPay,
stateTax,
fedTax;
const double FED_TAX = .10;
const double STATE_TAX = .05;
const double REG_HOURS = 40.0;
const double OVERTIME = 1.5;
string[] name = new string[5];
double[] wage = new double[5];
for (int i = 0; i < name.Length; i++)
{
Write("Please enter name: ", (i + 1));
name[i] = ReadLine();
Write("Please enter your hourly wage: ", (i + 1));
wage[i] = Convert.ToDouble(ReadLine());
Write("Please enter hours worked this week", (i + 1));
hours = Convert.ToDouble(ReadLine());
}
WriteLine();
for (int i = 0; i < name.Length; i++)
{
WriteLine("Name: " + name[i] + " Wage: " + wage[i]);
}
if (hours <= 40)
{
regularPay = hours * wage;
overtimePay = 0;
}
else
{
// ??
}
}
}
}

1.) Try to split your code into logic pieces:
private double CalculateWage(double hours, double wage)
{
return (hours * wage);
}
Or like this:
private string GetUserInput_String(string message, int index)
{
Write(message, index);
return ReadLine();
}
Now you can call it like this:
name[i] = GetUserInput_String("Please enter name: ", (i + 1))
Same for doubles.
private string GetUserInput_Double(string message, int index)
{
try
{
Write("Please enter wage: ", (i + 1));
return Convert.ToDouble(ReadLine());
//OR
double result;
double.TryParse(ReadLine(),out result);
if(result != 0)
{
return result;
}
return null;
}
catch(Exception ex) //Catch all thrown Exception
{
Write(ex.Message);//Handle Exceptions (log, retry,..)
return null; //When retunring null check for null when working with the returned value !!!
}
}
2.) Use Try {} catch {}
Catch and handle exception ALWAYS when casting, converting, etc.
Check out Linq:
private void PrintWages(string[] names, double[] wages)
{
names.ToList().ForEach(x => Console.WriteLine($"Name: {x} Wage: {wages[names.ToList().IndexOf(x)]}"));
}
This does the following:
string[] names = {"Anna", "Peter", "Marc"};
string[] wages = { "1500", "2000", "3500" };
names.ToList().ForEach(x => Console.WriteLine($"Name: {x} Wage: {wages[names.ToList().IndexOf(x)]}"));
Output:
Name: Anna Wage: 1500
Name: Peter Wage: 2000
Name: Marc Wage: 3500
So what have I done here:
using System.Linq; - Adds the "Foreach" and other extension methods to Collections
array.ToList() => array converted to list
Foreach element in names I called WriteLine();
names.ToList().IndexOf(x) gives me the index of the current element to use in wages[index]
I condesed the output via Interplated Strings
So the more or less complete result would be sth. like this
//Care of naming !
// string[] names - its a sort of collection of names so dont call it name.
// name would be ONE item of that array
//I recommend using List<sting> / List<double> here !
List<string> employees = new List<string>();
List<double> wages = new List<double>();
//Or way better => Dictionairy<string, double>(),
//A Dictionairy has a Key (unique) and a correlating value
Dictionary<string, double> EmployeeWages = new Dictionary<string, double>();
int employeesToAdd = 0;
try
{
Console.Write("How many employees would you like to add ?");
employeesToAdd = int.Parse(Console.ReadLine());
}
catch (Exception ex)
{
Console.Write($"Error: {ex.Message}");
return;
}
//We reach this line only if employeesToAdd has a value !
for (int i = 0; i < employeesToAdd; i++)
{
EmployeeWages.Add(GetUserInput_String("Please enter name: "), GetUserInput_Double("Please enter your wage: "));
}
PrintResult(EmployeeWages);

Related

How to type different words as variable entry data

I’m new to programming and I’m trying to write a code that does this:
Entry data
Name 1
Time 1
Name 2
Time 2
Output
Show the name that has the best time.
Now, I’ve managed to create a code that shows the correct result if I write the entry data like this:
A
200
B
300
(numbers are random)
Here is what I have tried so far -
string inputdata = Console.ReadLine();
char name = Convert.ToChar(inputdata);
inputdata = Console.ReadLine();
double time1 = Convert.ToDouble(inputdata);
inputdata = Console.ReadLine();
char name2 = Convert.ToChar(inputdata);
inputdata = Console.ReadLine();
double time2 = Convert.ToDouble(inputdata);
inputdata = Console.ReadLine();
if (time1 < time2) { Console.WriteLine(name); }
else { Console.WriteLine(name2);
I don’t know how to type into the console the full name (any full word) so I don’t get “String must be exactly one character long”.
I’ve been strugling a bit with this and can’t seem to find the right answer.
Thank you!
I think that this should do the trick.
Here is the link so you can try it out.
Console.WriteLine ("Name 1: ");
string name1 = Console.ReadLine(); //put name into a string, so we can use it after
Console.WriteLine ("Time 1: ");
int time1 = Convert.ToInt32(Console.ReadLine()); //put time into an int, so we can see who has better time
Console.WriteLine ("Name 2: ");
string name2 = Console.ReadLine();
Console.WriteLine ("Time 2: ");
int time2 = Convert.ToInt32(Console.ReadLine());
if(time1 > time2) //checking who has better time
Console.WriteLine(name1 + " has the better time."); //writing the name with the message
else if(time1 < time2)
Console.WriteLine(name2 + " has the better time.");
else
Console.WriteLine(name1 + " and " + name2 + " have the same time");
To read full word you must use Console.ReadLine (Reads the next line of characters from the standard input stream). To better data representation you need to introduce some class or struct that contains Name and Time. I add example according to your input data but if you want to add arbitrary number of elements than it's better to use List instead of array and do-while loop instead of for loop
public class Sprinter
{
public string Name { get; set; }
public int Time { get; set; }
}
...
//Define array
var results = new Sprinter[2];
// Load data
for (var index = 0; index < results.Length; index++)
{
results[index] = new Sprinter();
results[index].Name = Console.ReadLine();
results[index].Time = int.Parse(Console.ReadLine() ?? "0");
}
//Find minimum
var minTime = int.MaxValue;
Sprinter minElement = null;
for (var index = 0; index < results.Length; index++)
{
var sprinter = results[index];
if (sprinter.Time < minTime)
{
minElement = sprinter;
minTime = sprinter.Time;
}
}
//Show minimum
Console.WriteLine($"Min is {minElement.Name} with time {minElement.Time}");
Output:
Foo
200
Bar
300
Min is Foo with time 200

How Can I sum all digits in a number using loop?

when I enter 1 for n
and 1111 for lines
the sum must be 1+1+1+1=4 but the output is 1.
THIS IS THE QUESTION...
you will get a (n) then (n) lines as an input, In each line there are some numbers (we don’t know how many they are) and you must print (n) lines, In the i-th line print the sum of numbers in the i-th line.
using System;
namespace prom2
{
class Program
{
static void Main(string[] args)
{
int lines=0, sum = 0;
Console.Write("Enter a number of lines ");
int n = int.Parse(Console.ReadLine());
for (int i = 1; i <= n&n>0&1000>n; i++)
{
Console.WriteLine("Enter line " + i + " numbers");
lines = int.Parse(Console.ReadLine());
lines = lines / 10;
sum += lines % 10;
Console.WriteLine("sum is " + sum);
}
}
}
}
Try this:
static void Main(string[] args)
{
int input;
bool times = true;
List<int> numbers = new List<int>();
while (times)
{
Console.Clear();
Console.WriteLine("Enter number: ");
var num = int.TryParse(Console.ReadLine(), out input);//tryparse will output a bool into num and set input to a int
if (num)
{
numbers.Add(input);//only integers will be added to list
}
Console.Clear();
Console.WriteLine("Another? Y or N");//ask if they want to sum more numbers
var yesno = Console.ReadLine();//get answer from user
if (yesno.ToUpper().Trim() != "Y")//if N or anything else
{
//assume no
times = false;
}
Console.Clear();
}
var sum = numbers.Sum();
Console.WriteLine("Sum : " + sum.ToString());
Console.ReadLine();//just to pause screen
}
Because Console.ReadLine returns a string, and it's possible to treat a string as if it's an array of chars (where char represents a single character), you can have a method like this to calculate the sum of all the digits in a single line:
private int SumTheDigits(string line)
{
var sum = 0;
foreach (var character in line)
{
sum += int.Parse(character.ToString());
}
return sum;
}
Please note this method contains no validation - ideally you should validate that line is purely numeric, otherwise int.Parse will throw an exception, although the same is true of the code you provided too.
If you want to work with multiple lines of console input, just call this method from within another loop which solicits / works through those lines of console input.
Edit
My answer doesn't answer all of your question, it only answers the part which asks how to calculate the sum of the digits in a numeric string, and it does work, to the extent that it correctly does what it says on the tin.
Here's all the code I wrote to validate the answer before posting the original answer (I wrote it as a xUnit unit test rather than a console application, but that doesn't change the fact that the code I shared works):
using System;
using Xunit;
namespace StackOverflow71442136SumDigits
{
public class UnitTest1
{
[Theory]
[InlineData("1", 1)]
[InlineData("12", 3)]
[InlineData("23", 5)]
[InlineData("1234", 10)]
[InlineData("123456789", 45)]
public void Test1(string line, int expectedSum)
{
var actualSum = this.SumTheDigits(line);
Assert.Equal(expectedSum, actualSum);
}
private int SumTheDigits(string line)
{
var sum = 0;
foreach (var character in line)
{
sum += int.Parse(character.ToString());
}
return sum;
}
}
}
You might want to read How do I ask and answer homework questions?

how to output the contents of the list

essentially I'm making a guessing game for an assignment but as I try to output the list it comes out as
System.Collections.Generic.List`1[System.Int32]
System.Collections.Generic.List`1[System.Int32]
essentially I just need to store a users guess number and their attempt number so that once they guess the correct number it will display it as
"YOU WON, the number was ___ and here are your attempts
you chose 45
you chose 54
you chose 32
you chose ___
using System;
using System.Collections.Generic;
namespace main__4_8_2021_
{
class Program
{
public static void Main(string[] args)
{
while (true)
try
{
int NumberOfTries = 0;
Console.WriteLine("Guess a number between 1 and 100");
int number = Convert.ToInt32(Console.ReadLine());
List<int> mylist2 = new List<int>(number);
List<int> mylist = new List<int>(NumberOfTries);
int rng = new Random().Next(1, 101);
if (number == rng)
{
Console.WriteLine("Your guess was correct! The number was " + number + "!");
Console.WriteLine(mylist);
Console.WriteLine(mylist2);
break;
}
else if (number > rng)
{
NumberOfTries++;
Console.WriteLine("Your guess was too high ");
Console.WriteLine(mylist);
Console.WriteLine(mylist2);
Console.WriteLine("you now have done " + NumberOfTries + " Tries");
}
else if (number < rng)
{
NumberOfTries++;
Console.WriteLine("too low, ");
Console.WriteLine(mylist);
Console.WriteLine(mylist2);
Console.WriteLine("you now have done " + NumberOfTries + " Tries");
}
Console.Write($"Try again. ");
}
catch(Exception e)
{
Console.WriteLine(e.Message);
}
}
}
}
(the other console.writelines of the lists are just there for debug)
You have a number of issues with your code.
First, you don't need a counter for number of attempts, a Count property on the List is enough.
Second, you need to keep that list outside of the loop so it is not recreated each time.
Try the below
using System;
using System.Collections.Generic;
namespace main__4_8_2021_
{
class Program
{
public static void Main(string[] args)
{
List<int> mylist = new List<int>();
void PrintListContents() {
Console.WriteLine("here are your attempts");
var index = 0;
foreach(var value in mylist) {
Console.WriteLine($"{index}. You chose {value}");
index++;
}
}
while (true)
try
{
Console.WriteLine("Guess a number between 1 and 100");
int number = Convert.ToInt32(Console.ReadLine());
mylist.Add(number);
int rng = new Random().Next(1, 101);
if (number == rng)
{
Console.WriteLine("Your guess was correct! The number was " + number + "!");
PrintListContents()
break;
}
else if (number > rng)
{
NumberOfTries++;
Console.WriteLine("Your guess was too high ");
PrintListContents()
Console.WriteLine("you now have done " + myList.Count + " Tries");
}
else if (number < rng)
{
NumberOfTries++;
Console.WriteLine("too low, ");
PrintListContents()
Console.WriteLine("you now have done " + myList.Count + " Tries");
}
Console.Write($"Try again. ");
}
catch(Exception e)
{
Console.WriteLine(e.Message);
}
}
}
}
Console.WriteLine(mylist);
If value is null, only the line terminator is written. Otherwise, the
ToString method of value is called to produce its string
representation, and the resulting string is written to the standard
output stream.
SOURCE https://learn.microsoft.com/en-us/dotnet/api/system.console.writeline?view=net-5.0#System_Console_WriteLine_System_Object_
this means that you actually calling the ToString method of the list. Most of the "complex" types do not overwrite the ToString method which results in just returning the string representation of Type. In your case: List<int> which is represented as System.Collections.Generic.List`1[System.Int32]
you may also want to have a look at https://learn.microsoft.com/en-us/dotnet/api/system.object.tostring?view=net-5.0

C# Show variables

I'm starting with the C# language making console "apps". This one is to make grade averages. It doesn't show each name on each line with its own average that I still have to code. It works 100% until the //notation I've put
on the code. Under that I think it's the main problem, something that I might have forgotten to add or something.
namespace Repeat
{
class Program
{
static void Main(string[] args)
{
Console.BackgroundColor = ConsoleColor.Black;
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine("grade averages\n");
Console.ResetColor();
Console.WriteLine("");
float studentNumber;
float testNumber;
string name = "0";
string test;
float average = 0;
Console.WriteLine("Type the student number");
float.TryParse(Console.ReadLine(), out studentNumber);
Console.WriteLine("Type the number of tests");
float.TryParse(Console.ReadLine(), out testNumber);
Console.WriteLine("");
for (int a = 1; a <= studentNumber; a++)
{
Console.WriteLine("Type the student name " + a + ":");
nome = Console.ReadLine();
for (int p = 1; p <= testNumber; p++)
{
Console.WriteLine("Type the grade of test " + p + ":");
prova = Console.ReadLine();
}
Console.WriteLine("");
}
//All above is working 100%
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine("Students average:");
Console.ResetColor();
Console.WriteLine("");
for (int a = 1; a <= studentNumber; a++)
{
Console.WriteLine(name + ":" + average);
}
Console.ReadKey();
}
}
}
Every time you read the names and test-results of the students, you overwrite the previous value. You should store the names and grades (and possibly do some averaging-calculations). One example would be to use a Dictionary<string,List<int>> or Dictionary<string,List<string>>, where the name is stored in the Key, and the grades are stored as a list in the Value.
The Dictionary class is from the namespace System.Collections.Generic.
Here is the documentation for the Dictionary.
You're entering the names of the students and the test scores, but you need to save those values somewhere so that you can display them again.
This is just a basic example. You could add another class to your project like this:
public class StudentScoreCollection
{
private List<float>() _testScores = new List<float>();
public string StudentName {get;set;}
public List<float> TestScores {get{return _scores}}
}
Then, in your main program, declare a variable like
var scores = new List<StudentScoreCollection>();
Each time you start with a new student name (inside the first for loop)
declare
var score = new StudentScore();
score.Name = Console.ReadLine();
Then as each score is entered,
score.TestScores.Add(float.Parse(Console.ReadLine());
(There's no validation here - it will blow up if they enter something that isn't a number.)
Then at the end,
scores.ForEach(score => Console.WriteLine(score.name + score.TestScores.Average());
I wrote that as a LINQ expression. That can be confusing at first. It's more readable as a for-each loop. This is the exact same thing:
foreach(var score in scores)
{
Console.WriteLine(score.name + score.TestScores.Average();
}
Once you create a class that represents data that logically belongs together - like a name and a list of related scores - the rest becomes a little easier to work with.

Getting System.Byte [] instead of ASCII value

I'm a newer programmer with C#. I am having an issue where my character frequency reading program is not displaying the ASCII values correctly. What it is supposed to do is read from a text file, convert all uppercase to lowercase, display the ASCII values, frequency appeared, and percentage of the total number of characters each character appears in the file and then sort the list by frequency. Below is my code so far:
using System;
using System.Collections.Generic;
using System.Collections;
using System.Text;
using System.IO;
using LibUtil;
using LibDate;
namespace Ch8Prb3
{
class Program
{
const string INPUT_FILE_NAME = "\\CIS210\\Ch8Prb3\\TextDat.Txt";
const string OUTPUT_FILE_NAME = "\\CIS210\\Ch8Prb3\\Ch8Prb3Rpt.Txt";
int count;
static StreamReader fileIn;
static StreamWriter fileOut;
static void Main()
{
ConsoleApp.ClrScr(); IdentifyApplication();
OpenFiles(); LetterFreq();
CloseFiles();
}
static void IdentifyApplication()
{
Console.WriteLine();
Console.WriteLine("Application: Ch8Prb3 -- Find and display a character-frequency ");
Console.WriteLine(" report of only letter chracters and their");
Console.WriteLine(" ASCII values from a text file.");
Console.WriteLine();
}
static void OpenFiles()
{
try
{
fileIn = File.OpenText(INPUT_FILE_NAME);
Console.WriteLine("{0} was opened", INPUT_FILE_NAME);
}
catch
{
Console.WriteLine("Error: {0} does not exist\n", INPUT_FILE_NAME);
ConsoleApp.Exit();
}
try
{
fileOut = File.CreateText(OUTPUT_FILE_NAME);
Console.WriteLine("{0} was created\n", OUTPUT_FILE_NAME);
}
catch
{
Console.WriteLine("Error: {0} could not be created\n", OUTPUT_FILE_NAME);
ConsoleApp.Exit();
}
}
static void LetterFreq()
{
int[] c = new int[(int)char.MaxValue];
int total = 0;
int j = 0;
string s = File.ReadAllText("\\CIS210\\Ch8Prb3\\TextDat.Txt");
string l = Convert.ToString(Encoding.ASCII.GetBytes(s));
s = System.Threading.Thread.CurrentThread.CurrentCulture.TextInfo.ToLower(s.ToLower());
double percent;
foreach (char t in s)
{
c[(int)t]++;
}
PrintHeader();
for (int i = 0; i < (int)char.MaxValue; i++)
{
if (c[i] > 0 && char.IsLetter((char)i))
{
total += c[i];
percent = c[i] / total * 100;
fileOut.WriteLine(" {0} {1,3} {2,3} {3,2:f2}", (char)i, l, c[i], percent);
}
}
fileOut.WriteLine();
fileOut.WriteLine("Number of Characters: {0}", total);
}
static void PrintHeader()
{
fileOut.WriteLine(" Chapter 8 Problem 3");
fileOut.WriteLine("Character Frequency Report");
fileOut.WriteLine(" {0:MM/dd/yyyy}", Date.Today);
fileOut.WriteLine();
fileOut.WriteLine(" ASCII ");
fileOut.WriteLine("Char Value Freq Percent");
fileOut.WriteLine("---- ----- ---- -------");
}
static void CloseFiles()
{
fileIn.Close(); fileOut.Close();
}
}
}
Instead of getting the ASCII value of each character, I'm getting System.Byte [] all the way down the ASCII column.
Help!
This is the problem:
Convert.ToString(Encoding.ASCII.GetBytes(s));
Encoding.GetBytes(string) returns a byte[], and calling Convert.ToString() on that will just return System.Byte[].
It's not clear why you're using Encoding.ASCII at all here - you've got the contents of the file as a string, on the previous line:
string s = File.ReadAllText("\\CIS210\\Ch8Prb3\\TextDat.Txt");
Just use that instead of l. It's not clear what you're expecting to do with l anyway, to be honest. By "ASCII value" if you mean the Unicode code point for the character, just cast i to int:
fileOut.WriteLine(" {0} {1,3} {2,3} {3,2:f2}", (char)i, (int) i, c[i], percent);
Oh, and you probably want to change the way you're computing percent, too - you're using integer arithmetic, so the result will always be 0.
It's not clear why you're lower-casing the string twice either, by the way. Don't you think once is enough? Why are you lower-casing at all?
Oh, and you open an input file, but never do anything with it. Why?
There are various other things I'd change about your code - not least the layout (one statement per line, almost always!) - but this'll do for a start.
You program con be condensed considerably using list and groupby:
class Program
{
const string INPUT_FILE_NAME = "\\CIS210\\Ch8Prb3\\TextDat.Txt";
static void Main(string[] args)
{
var s = System.IO.File.ReadAllText(INPUT_FILE_NAME).ToLower();
var list = s.ToList();
var group = list.GroupBy(i => i);
foreach (var g in group)
{
Console.WriteLine("{0} {1}", g.Key, g.Count());
}
Console.ReadLine();
}
}

Categories

Resources