I have enum called Department that has abbreviations. (e.g. CSIS, ECON etc.)
I have struct Course with fields name, number of the course(e.g. 101 Fundamentals Of Computing just the number)
I created the constructor with four parameters.
In Program cs I created the List of these courses. with the order of (name(which is string), Department(I got this through calling Department type in enum), CourseCode(enum members like CSIS)and credit hours).
I was required to print all the courses through toString().
public string Name
{
get { return name; }
set { name = value; }
}
public int Number
{
get { return number; }
set { number = value; }
}
public int CreditHours
{
get { return numOfCreditHours; }
set { numOfCreditHours = value; }
}
public override string ToString()
{
return String.Format("{ -30, 0}--{4, 1}/{2}--{3:0.0#}", name, Department, number, numOfCreditHours);
}
This is where I created my List: in Program cs.
static void Main(string[] args)
{
Course course = new Course(courses);
foreach (Course crs in courses)
{
Console.WriteLine(string.Join(" , ", crs));
}
Console.WriteLine();
//Array.Sort(courses);
Console.ReadLine();
}
private static List<Course> courses = new List<Course>()
{
new Course("Fundamentals of Programming", Department.CSIS, 1400, 4),
new Course("Intermediate Programming in C#", Department.CSIS,2530, 3),
new Course("Introduction to Marketing", Department.MKTG,1010, 3),
new Course("Algorithms and Data Structures", Department.CSIS,2420, 4),
new Course("Object Oriented Programming", Department.CSIS, 1410, 4)
};
I get format exception. I know why I get it. Because of string type. but some how I need to do it. Please help me with some explaining. and what I should do to get it right. Thanks.
it looks like you swapped places in string format:
return String.Format("{0,-30}--{1,4}/{2}---{3:0.0#}"
You're confusing indexes in the format string in "{ -30, 0}--{4, 1}/{2}--{3:0.0#}".
"{ -30, 0}" must be "{0, -30}".
"{4, 1}" must be "{1, 4}".
Then, returns must be:
return String.Format("{0,-30}--{1,4}/{2}--{3:0.0#}", name, Department, number, numOfCreditHours);
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
I am currently working on a project which uses two methods, one method returns the most accurate player list on a server with the duration the player was on the server, and the second method utilizes a different method which returns a player list with less accuracy and no time, but with an additional value which I need that other method doesn't have. To put it in simple terms:
Method 1:
List<PlayerObjectMethod1> playerListMethod1 = GetPlayersFromServerMethod1(serverIp, serverPort);
The class method 1:
public string Name { get; set; }
public float Duration { get; set; }
Method 2:
List<PlayerObjectMethod2> playersFromMethod2 = new List<PlayerObjectMethod2>();
The class method 1:
public string Name { get; set; }
public string SpecialValue { get; set; }
public string CustomDuration { get; set; }
Now as you can see the method 2 doesn't officially return duration, however this method is running every 15 seconds, so in theory, I could attach 15 seconds to each player every time it runs.
More background:
The parent method runs on a timer every 15seconds. There are 5 servers in total for one server (time in between specific server gets scanned) is around 18 seconds, as such each player on each call can be 18 seconds. I need to get an accurate player for that specific value. Two comparisons I want to do:
If a players name is not 123, only compare the name to get a specific value.
if(playerListMethod1[i].Name != "123") {
var index = playersFromMethod2.FindIndex(x => x==playerListMethod1[i].Name)
playersFromMethod2[index].IsOnline = True;
playersFromMethod2[index].Duration = playerListMethod1[i].Duration;
}
And now if it is 123 I need to find it by name and duration. However, the issue I have is how to upkeep that second list and add 15 seconds to all the players with name 123. As before I would use a list to store old player list value and just clear it and AddRange of the new one.
Example:
serverNotfPlayerListOld[server.Name].Clear();
serverNotfPlayerListOld[server.Name].AddRange(playersFromMethod2);
So I basically need an idea on how to do this, would I first fill the method2 with players, then check non 123 players, then check 123 players, and then add 15 seconds to the 123 players and at some point the list would get accurate?
Edit:
As mentioned before there are two different methods (two different sources) one gives name and duration, the other name and player id. As such, I need to somehow merge that data together. To do that I thought I could add my own duration for the second method because it's being run every 45 seconds. The current new code I have:
Example of the addition solution
class Program
{
static void Main()
{
HashSet<A> a = new HashSet<A>()
{
// add random values
new A { Id = "josh", Value = 60, },
new A { Id = "tom", Value = 60, },
new A { Id = "koven", Value = 120, },
new A { Id = "123", Value = 240, },
};
HashSet<A> b = new HashSet<A>()
{
// add random values (some with Id's from a)
new A { Id = "tom", Value = 10, },
new A { Id = "4123", Value = 10, },
new A { Id = "koven", Value = 65, },
new A { Id = "5552", Value = 60, },
new A { Id = "123", Value = 45, },
};
IEnumerable<A> c = IdJoin(a, b);
int i = 0;
foreach (A element in c)
{
Console.WriteLine($"{element.Id}: {element.Value}");
i++;
}
Console.WriteLine($"Count: {i}");
Console.WriteLine("Press [enter] to continue...");
Console.ReadLine();
}
public static IEnumerable<A> IdJoin(IEnumerable<A> a, IEnumerable<A> b)
{
Dictionary<string, A> dictionary = a.ToDictionary(i => i.Id);
foreach (A element in b)
{
if (dictionary.TryGetValue(element.Id, out A sameId))
{
if (element.Id == "123")
{
sameId.Value += element.Value;
}
else
{
sameId.Value += 45;
}
}
else {
dictionary.Add(element.Id, element);
}
}
return dictionary.Values;
}
}
public class A
{
public string Id;
public float Value;
}
Issue with this is that if it reads by only name it will bug out as multiple players can have 123. Which is why I need comparison method which gets by name and duration (of few minutes differences) in those two lists and I need help with that. Another example:
Two 123 players join the game. One list has values [name:123, duration:240],[name:123, duration:60] the other has [name:123, player:7548, customDuration: 225], [name:123, player:7555, customDuration: 90]
I need to get which player is which.
Presuming Id and Value combination makes unique value:
class Program
{
static List<A> firstList;
static List<A> secondList;
static List<A> resultList;
static void Main(string[] args)
{
// Fill firstList, secondList with data <your server methodes>
resultList = new List<A>();
foreach (var item in firstList)
{
var match = secondList.Find(a => a.Equals(item));
if (match != null)
{
if (item.Id == "123")
{
item.Value += match.Value;
}
else
{
item.Value += 45;
}
}
resultList.Add(item);
}
resultList.AddRange(secondList.Except(firstList));
}
}
public class A
{
public string Id;
public float Value;
public override bool Equals(Object obj)
{
if ((obj == null) || !GetType().Equals(obj.GetType()))
{
return false;
}
else
{
var a = (A)obj;
return (Id == a.Id) && (Value == a.Value);
}
}
}
i have written below code without applying any design pattern,Is anything wrong in this code.
class Employee {
public int EmployeeID
{ get; set; }
public int YearOExperience
{ get; set; }
public int Salary
{ get; set; }
public string EmploeyeeType
{ get; set; }
}
interface IEmployee {
List<Employee> getInformation(int id, int exp, int sal);
}
class EmployeeData1 {
public List<Employee> GetData(int id,int exp , int sal)
{
List<Employee> empInfo = new List<Employee> {
new Employee { EmploeyeeType = "P", EmployeeID = 1, Salary = 20000, YearOExperience= 2 },
new Employee { EmploeyeeType = "P", EmployeeID = 2, Salary = 20000, YearOExperience= 2 },
new Employee { EmploeyeeType = "C", EmployeeID = 3, Salary = 20000, YearOExperience= 2 }
};
return empInfo;
}
}
static void Main(string[] args) {EmployeeData1 emp = new EmployeeData1();
emp.getInformation(1, 2, 2000);
};
}
Here is the assignment:
Since you pasted the image instead of text, we have to pay for it by re-typing.
Do not handover like this. Instead of trying to employ design patterns (which is not expected from you), handover work which is correct.
Your assignment says that you should take as input the employee name, employee type and years of experience.
Your console app should get these three values by Console.ReadLine() commands.
Please make sure that this is so. Bu it probably is, since all the code competitions use stdin (Console.ReadLine() reads from stdin) to feed input to an application.
Then, what your teacher wants from you are:
Generate a sequential employee Id,
Calculate the salary according to the years of experience
Print out the results (using Console.WriteLine(), which writes to the stdout (standard output))
Proceed to the next employee
Here is a limited example to help you. Please do research and fill in the required parts yourself, otherwise, what does it mean to get a good mark if it isn't yours?
I am not saying that you can handover this directly, mind you.
But at least you can take this as a starting point.
Good luck.
static void Main()
{
// this will be used to create sequential employee Ids
int employeeId = 0;
while(true) // Just press enter without entering anything to exit.
{
string employeeName = Console.ReadLine();
if(employeeName == "")
{
return;
}
// Get the other two input parameters like the one above.
// Please be careful with the last one (years of experience)
// It should be parsed to an integer (a little research effort)
// string employeeType = ..
// int yearsOfExperience = ..
// Now, assign this employee the next Id.
employeeId++;
// And now, calculate the employee's salary
// You should use the years of experience and employee type
// to match an amount in the salary table.
int salary;
if(employeeType == "Permanent")
{
salary = ..;
}
else
{
salary = ..;
}
// And finally, print-out using stdout
Console.WriteLine("Employee ID: {0}", employeeId);
// Print the other two outputs like the one above
}
}
The dataset I have is :
Name Order ID
Summary 1 147
Software Functionality -9 211
I have this LINQ query:
string value = projectA.OrderByDescending(a => a.Order)
.ThenBy(a => a.Name)
.ToList()
.First()
.ID
.ToString();
The answer I get is 211, but I think the answer should be 147. Why does this happen?
Note: the Order field is of type string.
You get the output you have because your Order is a string. As proof, this sample will show that you get the correct output when it's an integer:
void Main()
{
var list = new List<Project>() { new Project() { Order = 1, Id = 147, Name = "Summary" }, new Project() { Order = -9, Id = 211, Name = "Software Functionality" } };
int value= list.OrderByDescending(a => a.Order).ThenBy(a => a.Name).ToList().First().Id;
Console.WriteLine (value);
}
public class Project
{
public int Order {get;set;}
public int Id {get;set;}
public string Name {get;set;}
}
However, in case you do need it as a string: why doesn't it work like this?
Take a look at the CompareOptions enum. More specificically: CompareOptions.IgnoreSymbols.
Indicates that the string comparison must ignore symbols, such as white-space characters, punctuation, currency symbols, the percent sign, mathematical symbols, the ampersand, and so on. This is also explained here.
This essentially makes your -9 a 9.
You can bypass this easily by creating your own comparer and passing it what you need:
public class CustomComparer : IComparer<string>
{
public int Compare(string x,string y)
{
return CultureInfo.CurrentCulture.CompareInfo.Compare(x, y, CompareOptions.Ordinal);
}
}
which can be used as
new[] {"1", "-9"}.OrderByDescending(x => x, new CustomComparer())
I tried to reconstruct your issue. Here is my code (LinqPad), which works properly:
void Main()
{
List<ProgramA> progs = new List<ProgramA>{
new ProgramA("Summary", 1, 147),
new ProgramA("Software Functionality", -9, 211)
};
int value= progs.OrderByDescending(a => a.Order).ThenBy(a => a.Name).ToList().First().ID;
value.Dump();
}
// Define other methods and classes here
class ProgramA
{
private string sName = string.Empty;
private int iOrder = 0;
private int iID = 0;
public ProgramA(string _Name, int _Order, int _ID)
{
sName = _Name;
iOrder = _Order;
iID = _ID;
}
public string Name
{
get {return sName;}
set {sName = value;}
}
public int Order
{
get {return iOrder;}
set {iOrder = value;}
}
public int ID
{
get {return iID;}
set {iID = value;}
}
}
returns: 147
[EDIT]
#DStanley It is stored as "1" and "-9" in the list – user1989 6 mins ago
If Order is stored as string value, you can try to convert it into integer:
int value= progs.OrderByDescending(a => Convert.ToInt32(a.Order)).ThenBy(a => a.Name).ToList().First().ID;
string value= projectA.OrderByDescending(a => a.Order).ThenBy(a => a.Name).ToList().First().ID.ToString();
OrderByDescending => Orders
Output - -9, 1
Select First element
- 9 = 211. Logic is correct.
I have a string with the following structure:
Student Name________AgeAddress_______________________Bithday___Lvl
Example:
Jonh Smith 016Some place in NY, USA 01/01/2014L01
As you can see, there is no delimited character like | or ,
Also, there is no space between fields (if you check, there is no space between Age/Address and Birthday/Level.
The size of each field is static so if data's length is less then it will contains white spaces.
I have a class that need to be filled with that information:
public class StudentData
{
public char[] _name = new char[20];
public string name;
public char[] _age = new char[3];
public string age;
public char[] _address = new char[30];
public string address;
public char[] _bday = new char[10];
public string bday;
public char[] _level = new char[3];
public string level;
}
Is there any way to do this automatically and dynamically?
I mean I really don't want to code like this:
myClass.name = stringLine.substring(0,19);
myClass.age = stringLine.substring(20,22);
That's because I have way more fields that the ones added in this example & way more string lines with other different data.
Update: There were supposed to be a lot of spaces between "Smith" and "016", but I don't know how to edit it.
Update2: If I use StringReader.Read() I can evade to use substring and indexes, but it isn't still so dynamically because I would need to repeat those 3 lines for each field.
StringReader reader = new StringReader(stringLine);
reader.Read(myClass._name, 0 myClass._name.Length);
myClass.name = new string(myClass._name);
Given your requirement I came up with an interesting solution. All be-it it may be more complex and longer than using the String.SubString() method as stated.
However this solution is transferable to other types and other string. I used a concept of Attributes, Properties, and Reflection to parse a string by a Fixed Length and setting the class Properties.
Note I did change your StudentData class to follow a more conventional coding style. Following this handy guide on MSDN: http://msdn.microsoft.com/en-us/library/xzf533w0(v=vs.71).aspx
Here is the new StudentData class. Note it uses the properties as opposed to fields. (Not discussed here).
public class StudentData
{
string name;
string age;
string address;
string bday;
string level;
[FixedLengthDelimeter(0, 20)]
public string Name { get { return this.name; } set { this.name = value; } }
[FixedLengthDelimeter(1, 3)]
public string Age { get { return this.age; } set { this.age = value; } }
[FixedLengthDelimeter(2, 30)]
public string Address { get { return this.address; } set { this.address = value; } }
[FixedLengthDelimeter(3, 10)]
public string BDay { get { return this.bday; } set { this.bday = value; } }
[FixedLengthDelimeter(4, 3)]
public string Level { get { return this.level; } set { this.level = value; } }
}
Note on each of the properties there is an Attribute called FixedLengthDelimeter that takes two parameters.
OrderNumber
FixedLength
The OrderNumber parameter denotes the order in the string (not the position) but the order in which we process from the string. The second parameter denotes the Length of the string when parsing the string. Here is the full attribute class.
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
public sealed class FixedLengthDelimeterAttribute : Attribute
{
public FixedLengthDelimeterAttribute(int orderNumber, int fixedLength)
{
this.fixedLength = fixedLength;
this.orderNumber = orderNumber;
}
readonly int fixedLength;
readonly int orderNumber;
public int FixedLength { get { return this.fixedLength; } }
public int OrderNumber { get { return this.orderNumber; } }
}
Now the attribute is simple enough. Accepts the two paramters we discussed eariler in the constructor.
Finally there is another method to parse the string into the object type such as.
public static class FixedLengthFormatter
{
public static T ParseString<T>(string inputString)
{
Type tType = typeof(T);
var properties = tType.GetProperties(BindingFlags.Instance | BindingFlags.Public); //;.Where(x => x.GetCustomAttributes(typeof(FixedLengthDelimeterAttribute), false).Count() > 0);
T newT = (T)Activator.CreateInstance(tType);
Dictionary<PropertyInfo, FixedLengthDelimeterAttribute> dictionary = new Dictionary<PropertyInfo, FixedLengthDelimeterAttribute>();
foreach (var property in properties)
{
var atts = property.GetCustomAttributes(typeof(FixedLengthDelimeterAttribute), false);
if (atts.Length == 0)
continue;
dictionary[property] = atts[0] as FixedLengthDelimeterAttribute;
}
foreach (var kvp in dictionary.OrderBy(x => x.Value.OrderNumber))
{
int length = kvp.Value.FixedLength;
if (inputString.Length < length)
throw new Exception("error on attribute order number:" + kvp.Value.OrderNumber + " the string is too short.");
string piece = inputString.Substring(0, length);
inputString = inputString.Substring(length);
kvp.Key.SetValue(newT, piece.Trim(), null);
}
return newT;
}
}
The method above is what does the string parsing. It is a pretty basic utility that reads all the properties that have the FixedLengthDelimeter attribute applied a Dictionary. That dictionary is then enumerated (ordered by OrderNumber) and then calling the SubString() method twice on the input string.
The first substring is to parse the next Token while the second substring resets the inputString to start processing the next token.
Finally as it is parsing the string it is then applying the parsed string to the property of the class Type provided to the method.
Now this can be used simply like this:
string data1 = "Jonh Smith 016Some place in NY, USA 01/01/2014L01";
StudentData student = FixedLengthFormatter.ParseString<StudentData>(data1);
What this does:
Parses a string against property attributes in a fixed length format.
What this does not do:
It does convert the parsed strings to another type. Therefore all the properties must be a string. (this can be easily adapted by adding some type casting logic in).
It is not well tested. This is only tested against a few samples.
It is not by all means the only or best solution out there.
You could use FileHelpers library (NuGet).
Just define the structure of your input file with attributes:
[FixedLengthRecord]
public class StudentData
{
[FieldFixedLength(20)]
[FieldTrim(TrimMode.Right)]
public string name;
[FieldFixedLength(3)]
public string age;
[FieldFixedLength(30)]
[FieldTrim(TrimMode.Right)]
public string address;
[FieldFixedLength(10)]
public string bday;
[FieldFixedLength(3)]
public string level;
}
Then simply read the file using FileHelperEngine<T>:
var engine = new FileHelperEngine<StudentData>();
var students = engine.ReadFile(filename);