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.
Related
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
i did write , but it gets just the nam:
var namenListe = new List<string>();
while(true)
{
Console.WriteLine("Geben Sie die Namen ein ; ");
string name = Console.ReadLine();
Console.WriteLine("Die namen : ");
namenListe.Add(name);
for (int i = 0; i < namenListe.Count; i++)
{
Console.WriteLine(namenListe);
}
private static readonly Random random = new();
static void Main(string[] args)
{
while (true)
{
Console.WriteLine("Enter a set of comma separated name here:");
var names = Console.ReadLine();
if (string.IsNullOrWhiteSpace(names))
{
Console.WriteLine("Bad name input, try again \n");
continue;
}
Console.WriteLine("Enter number of randomly selcted named:");
var count = Console.ReadLine();
if (!int.TryParse(count, out var nameCount))
{
Console.WriteLine("Bad name count input, try again \n");
continue;
}
// Split the names.
var nameCollection = names.Split(',', StringSplitOptions.TrimEntries).ToList();
// Shuffle names.
nameCollection = nameCollection.OrderBy(_ => random.Next()).ToList();
Console.WriteLine($"Your randomly selected {nameCount} names are : {string.Join(", ", nameCollection.Take(nameCount))}\n\n");
}
}
I think you will need to create a random number in a range from your minimum desired number of names to your maximum, then Use that to determine whether or not a name gets printed.. Like if your random number is five.. int x=0; if (x<ran) {print name(); x++;} If (x==ran) return; run this kind of code in your for loop instead of just printing all names.. But you'll have to generate your own random number.. the code is something like. int ran; ran =Random %max *100 +minimum; You'll have to check to be sure. And include Math.h or some other header to make sure random works.
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);
Hello ive been sitting with this problem now for a training excersise while trying to learn C#. I'm making a list with 4 variabels and then trying to sort them after one of them, Sold.
Im using a struct to make the list with the variabels and then use a while loop to fill it.
I can get it to write out the list and its all there i just cant get it to sort.
Ive tried using list.sort but i cant get it to accept the command. The struct is as follows.
Public struct Sale
{
public string Name;
public decimal Personalnumber;
public string District;
public int Sold;
}
And the list and while loop.
Console.WriteLine("Press Enter to start");
Console.ReadLine();
Sale[] saleslist = new Sale[8]; //skapar en lista
int i = 0;
while (i < 8)
{
Console.WriteLine("Enter Name");
saleslist[i].Name = Console.ReadLine(); //indata namn
Console.WriteLine("Enter Personalnumber");
saleslist[i].Personalnumber = decimal.Parse(Console.ReadLine());//indata personnummer
Console.WriteLine("Enter District");
saleslist[i].District = Console.ReadLine();//indata distrikt
Console.WriteLine("Enter amount sold");
saleslist[i].Sold = int.Parse(Console.ReadLine()); //indata antal sålda
Console.WriteLine("Press Enter to continue to next person"); /* tryck enter för att gå vidare*/
i++;
}
Try using Enumerable.OrderBy:
salesList = salesList.OrderBy(n => n.Sold).ToArray();
You also need to add a using System.Linq; at the top of your file.
Alternatively, you could also use Array.Sort:
Array.Sort(salesList, (a, b) => a.Sold.CompareTo(b.Sold));
I am having trouble copying data from inside a do--while loop and repeating it outside the loop. It is during a split function, where each student's test score is entered on the same line as his/her name. I'm sorry if this is a very simple question but I cannot find anywhere how to fix it. Thanks very much for any help.
do {
Console.Write("Enter the student's name followed by his/her score on the same line:");
studentAndScore = Console.ReadLine();
if (studentAndScore == "")
{
break;
}
string[] parsedInput;
parsedInput = studentAndScore.Split();
string student = parsedInput[0] = students[0];
score = int.Parse(parsedInput[1]);
score = studentScores[0];
i++;
} while (i<=MAX);
Console.WriteLine("The test scores of the students are:");
Console.WriteLine("students \t scores \t");
//And I need to repeat the list of student names and scores here
This line of code:
string student = parsedInput[0] = students[0];
is going to copy students[0] into parsedInput[0] first. So you're losing your parsed input.
Instead, try:
string student = parsedInput[0];
students[0] = student;
If that is, in fact, your intent. It's seldom a good idea to do two assignments in the same line of code.
It is likely that you really want to use i instead of 0 in your indexers, as in parsedInput[i] and students[i].
Just create two lists...
var names = new List<String>();
var scores = new List<Int32>();
...read the input into the lists...
while (true)
{
Console.Write("student/score: ");
var input = Console.ReadLine();
if (String.IsNullOrWhiteSpace(input))
{
var parts = input.Split();
names.Add(parts[0]);
scores.Add(Int32.Parse(parts[1]);
}
else
{
break;
}
}
... and output the lists.
for (var i = 0; i < names.Count; i++)
{
Console.WriteLine("{0}\t{1}", names[i], scores[i]);
}
And of course add a lot of error handling. Or you could use a dictionary but I am not really sure about the guarantees you get regarding the ordering of the items.
var data = new Dictionary<String, Int32>();
while (true)
{
Console.Write("student/score: ");
var input = Console.ReadLine();
if (String.IsNullOrWhiteSpace(input))
{
var parts = input.Split();
data.Add(parts[0], Int32.Parse(parts[1]));
}
else
{
break;
}
}
foreach (var entry in data)
{
Console.WriteLine("{0}\t{1}", entry.Key, entry.Value);
}
What Robert wrote is true. Additionally, you don't use the loop variable i to store each student in a different "slot" of the array, so you're overwriting everything currently in the same place. And the declaration of the array must be outside of the loop, otherwise it will erase it in each iteration.
Summing up the changes required to your C# code sample, the corrected version looks like this:
void Main()
{
int MAX = 20;
var students = new string[MAX];
var scores = new int[MAX];
int i=0;
do {
Console.Write("Enter the student's name followed by his/her score on the same line:");
var studentAndScore = Console.ReadLine();
if (studentAndScore == "")
{
break;
}
string[] parsedInput = studentAndScore.Split();
students[i] = parsedInput[0];
scores[i] = int.Parse(parsedInput[1]);
i++;
} while (i<MAX);
Console.WriteLine("The test scores of the students are:");
Console.WriteLine("students \t scores \t");
for(int k=0; k<i; k++) {
Console.WriteLine("Student: {0}, Score: {1}", students[k], scores[k]);
}
}
Note that I am using the value of i in the for statement rather than MAX, because the user can break out of the do loop by entering a blank line. And i always contains the # of items, which have been entered previously.
Of course, this code does not yet contain any error handling, which would be required in the real world.