I have a console app that waits for the User to enter a number between 1 and 4. Depending on the selection, a case statement will then print out the appropriate console statement, or go to a different method. When I start the program and enter the number, nothing is returned and the program ends.
if the user selects number 1 I want to print out a line of text and then execute program called NewEntry. It doesn't seem to even start that program.
class Program
{
static void Main(string[] args)
{
//initial Prompt
Console.WriteLine("***Welcome to the Asset Directory***");
Console.WriteLine("Please Select an Option");
Console.WriteLine("1. New Entry");
Console.WriteLine("2. Edit Entry");
Console.WriteLine("3. Look Up");
Console.WriteLine("4. Print Master List");
int userInput;
userInput = Convert.ToInt32(Console.ReadLine());
Console.WriteLine(userInput);
switch (userInput)
{
case '1':
Console.WriteLine("1. New Entry");
NewEntry();
break;
case '2':
Console.WriteLine("2. Edit Entry");
break;
case '3':
Console.WriteLine("Look Up");
break;
case '4':
Console.WriteLine("4. Print Master List");
break;
default:
Console.WriteLine("Invalid Selection");
break;
}
}
static void NewEntry ()
{
Console.WriteLine("Enter the DSCADA Asset Information");
Test_RTU = new DSCADA_RTU();
Test_RTU.StationName = Console.ReadLine();
Test_RTU.RTUmake = Console.ReadLine();
Test_RTU.RTUtype = Console.ReadLine();
Test_RTU.CommunicationType = Console.ReadLine();
Test_RTU.DateInService = Console.ReadLine();
}
}
class Test_RTU
{
public string EDiv { get; set; } //division that owns the asset
public string StationName { get; set; } // name of station RTU is located
public string RTUmake {get; set;}
public string RTUtype { get; set; }
public string CommunicationType { get; set; }
public string DateInService { get; set; }
}
Your switch cases should look like this:
case 1:
...
case 2:
...
case 3:
...
case 4:
...
not this:
case '1':
...
case '2':
...
case '3':
...
case '4':
...
userInput is an int, so the cases should be int literals as well. The literals that you are using (such as '1') are char literals. There just so happens to be an implicit conversion from char to int, converting '1' to the integer 49, '2' to the integer 50, etc. Because of this implicit conversion, your code passes compilation, but doesn't work as expected.
Hi there I am making a C# windows forms app, I made a switch with all my teammates birthdays in order to calculate their birthday age, however I want to add the functionality that if today is their birthday a message appears.
Therefore I need something that goes into EACH CASE of the switch and there I will add a validation like if today's date is equal to bday, then messageshow "its name 1 birthday, today!"
switch (name)
{
case "name 1":
bday = DateTime.Parse("11.11.1988");
break;
case "name 2":
bday = DateTime.Parse("11.12.1988");
break;
case "name 3":
bday = DateTime.Parse("03.12.1987");
break;
}
Why dont you use a Dictionary.
Dictionaries use other objects as Keys to retrieve their values.
In your case you could map all the birthdays to their names like:
Dictionary<string, DateTime> birthdays = new Dictionary<string, DateTime>;
//Add values like this
birthdays.Add("name 1", DateTime.Parse("11.11.1988"));
birthdays.Add("name 2", DateTime.Parse("11.12.1988"));
...
//Then you could loop through all the entries
foreach(KeyValuePair<string, DateTime> entry in birthdays)
{
if(entry.Value.Day == DateTime.Now.Day && entry.Value.Month == DateTime.Now.Month)
{
Console.WriteLine(entry.Key + " has birthday!");
}
}
Based on what you provided in your snippet, you could do this sort of check outside of the case statement. Example:
public void WhateverYourMethodIs()
{
switch (name)
{
case "name 1":
bday = DateTime.Parse("11.11.1988");
break;
case "name 2":
bday = DateTime.Parse("11.12.1988");
break;
case "name 3":
bday = DateTime.Parse("03.12.1987");
break;
}
if (this.IsBirthday(bday))
{
// do whatever you want for when it's the name's birthday.
}
}
public bool IsBirthday(DateTime bday)
{
if (bday.Day == DateTime.Now.Day && bday.Month == DateTime.Now.Month)
return true;
return false;
}
note the above would not take into account leap day birthdays.
Based on your comments, it sounds like you're hoping to evaluate the birthdays of all names regardless of the switch. This won't work in your current approach. bday is a single value that can only be attributed to the current "name".
One way to accomplish what you're hoping for would be to use a class to represent a name as so:
public class User
{
public string Name { get; set; }
public DateTime Birthday { get; set; }
public bool IsBirthday
{
get
{
if (Birthday.Day == DateTime.Now.Day && Birthday.Month == DateTime.Now.Month)
return true;
return false;
}
}
}
public class SomeClass
{
private List<User> Users = new List<User>();
public void PopulateNames()
{
Users.Add(new User()
{
Name = "name 1",
Birthday = DateTime.Parse("11.11.1988")
};
Users.Add(new User()
{
Name = "name 2",
Birthday = DateTime.Parse("11.12.1988")
};
// etc
}
public void DoSomethingOnUsersWithABirthday()
{
foreach (User user in Users)
{
if (user.IsBirthday)
{
// do something for their birthday.
Console.WriteLine(string.format("It's {0}'s birthday!", user.Name));
}
}
}
}
I have a method that I would like to pass an option to, but as a switch. It is hard for me to explain so I will include the class:
class Special
{
int Var1;
int Var2;
public void Add1(int option, int variable)
{
int ToReturn;
ToReturn = variable + 1;
switch(option)
{
case 1:
Var1 = ToReturn;
break;
case 2:
Var2 = ToReturn;
break;
}
}
}
Is there a way I can limit the value of option to 1 or 2? Can I add any information to the Add1 so that when it is called it informs the programmer as to which values it may be, and what each option does?
I have given an example class, but my class contains many more variables this may apply to.
Yes:
public enum Option
{
Option1,
Option2
}
public void Add1(Option option, int variable)
{
int ToReturn;
ToReturn = variable + 1;
switch(option)
{
case Option1:
Var1 = ToReturn;
break;
case Option2:
Var2 = ToReturn;
break;
}
}
Looks like you want to use enumerations, basically placeholders for statically defined values.
I could think of a number of ways to do what you are asking however if I was in your scenario (providing I have understood your question correctly) I would be using an enum...
enum Options {
Option1 = 1,
Option2 = 2
}
class Special
{
int Var1;
int Var2;
public void Add1(Options option, int variable)
{
int ToReturn;
ToReturn = variable + 1;
switch(option)
{
case Options.Option1:
Var1 = ToReturn;
break;
case Options.Option2:
Var2 = ToReturn;
break;
}
}
}
To give some background I'm trying to solve the Project Euler Problem 54 involving poker hands. Though there's infinite approaches to this. What I would like to do is enumerate through a list of strings, for example:
{ "8C", "TS", "KC", "9H", "4S" };
I would like to "get" an instance of class card with properties value, and suit, for each respective string. I've not yet utilized get/set so maybe there is an obvious approach to this I'm missing.
Ultimately I would like to have a list of objects type Card, I don't mind building all the card's ahead of time, such that "2H" returns an instance of type Card where suit = Hearts, and value = 2, for example.
I know this code is wrong, but it should give an idea of what I'm trying to do. Any suggestions would be appreciated.
class Card
{
public string suit;
public int value;
public string cardname
{
get
{
if (cardname == "2H") Card TwoH = new Card();
TwoH.suit = "Hearts"
TwoH.value = 2;
return TwoH;
}
}
}
Why not make a constructor that fills suit and value based on a string parameter
public Card(string name)
{
switch(name)
{
case "2H":
this.suit = "Hearts";
this.value = 2;
break;
//...
}
}
This might not be the exact solution you seem to be asking for but if the values you'll be getting (eg 2H, 3C etc) are all 2 characters long, then you can try this:
public class Card
{
public string suit { get; set; }
public int value { get; set; }
public static Card GetCard(string cardName)
{
string tmpSuit;
int tmpValue;
char[] cardNameParts = cardName.ToCharArray();
switch(charNameParts[0])
{
case "A":
tmpValue = 1;
break;
case "2":
tmpValue = 2;
break;
...
}
switch(charNameParts[1])
{
case "H":
tmpSuit= "Hearts";
break;
case "C":
tmpSuit= "Clubs";
break;
...
}
return new Card() { suit = tmpSuit, value = tmpValue };
}
}
I would do it like that:
public class Card
{
public string Suit { get; set; }
public int Value { get; set; }
public static Card FromString(string s)
{
if (s == "2H") return new Card() { Suit = "Hearts", Value = 2 };
else if (s == "....")
...
else return null;
}
}
I have converted your suit and value field into properties and instead of some getter method which in your case wouldn't work I have added a static method.
You can use it like this Card card2H = Card.FromString("2H");
Maybe use two switch statements, first
switch (cardname[0])
{
...
}
then
switch (cardname[1])
{
...
}
Before that, check that cardname.Length == 2. In each switch, have a default section where you throw an exception in case the char value doesn't make sense.
I use class Card which contains 2 enumerated properties (suite - hearts diamonds spades and clubs) and card value from 2 to A. And overrides ToString() method to returns something like Ah Ad etc. All ok, but enum value can't starts with number, therefore my card value enumerated looks like x2, x3, x4 ... it is not beautiful.
Also need simple approach to parse few cards from single string.
Who know the best approach to design this class?
Couldn't you assign Jack, Queen, King, and Ace to be 11, 12, 13, and 14, respectively? It'd end up looking something like:
public class Card
{
public int Value { get; private set; }
public enum SuitType
{
Clubs, Spades, Hearts, Diamonds
}
public SuitType Suit { get; private set; }
public Card(int value, SuitType suit)
{
Suit = suit;
Value = value;
}
public Card(string input)
{
if (input == null || input.Length < 2 || input.Length > 2)
throw new ArgumentException();
switch (input[0])
{
case 'C': case 'c':
Suit = SuitType.Clubs;
break;
case 'S': case 's':
Suit = SuitType.Spades;
break;
case 'H': case 'h':
Suit = SuitType.Hearts;
break;
case 'D': case 'd':
Suit = SuitType.Diamonds;
break;
default:
throw new ArgumentException();
}
int uncheckedValue = (int)input[1];
if (uncheckedValue > 14 || uncheckedValue < 1)
throw new ArgumentException();
Value = uncheckedValue;
}
public string encode()
{
string encodedCard = "";
switch (Suit)
{
case SuitType.Clubs:
encodedCard += 'c';
break;
case SuitType.Spades:
encodedCard += 's';
break;
case SuitType.Hearts:
encodedCard += 'h';
break;
case SuitType.Diamonds:
encodedCard += 'd';
break;
}
encodedCard += (char) Value;
return encodedCard;
}
public override string ToString()
{
string output = "";
if (Value > 10)
{
switch (Value)
{
case 11:
output += "Jack";
break;
case 12:
output += "Queen";
break;
case 13:
output += "King";
break;
case 14:
output += "Ace";
break;
}
}
else
{
output += Value;
}
output += " of " + System.Enum.GetName(typeof(SuitType), Suit);
return output;
}
}
Edit:
I added some string functionality.
I took structure of Card(string input) from Jon Hanna's answer.
There's an obvious numeric value for the pip-cards, and we can add J=11, Q=12, K=13.
It may be more convenient to have A=14 than A=1 depending on the game being modelled (so one can more simply compute different relative values of hands).
Enums gives no real advantage, especially since enums allow out-of-range values unless you explicitly check for them (e.g. there is nothing to stop someone assigning (CardValue)54 to the card-value enumeration value).
ToString can be aided with an array of the values {null,"1","2","3","4","5","6","7","8","9","10","J","Q","K"}. Likewise {'♥','♦','♠','♣'} could give a nicer output.
Parsing always trickier than outputting a string, even if you are very strict in what you accept, as you have to deal with the potential for invalid input. A simple approach would be:
private Card(string input)
{
if(input == null)
throw new ArgumentNullException();
if(input.length < 2 || input.length > 3)
throw new ArgumentException();
switch(input[input.Length - 1])
{
case 'H': case 'h': case '♥':
_suit = Suit.Hearts;
break;
case 'D': case 'd': case '♦':
_suit = Suit.Diamonds;
break;
case 'S': case 's': case '♠':
_suit = Suit.Spades;
break;
case 'C': case 'c': case '♣':
_suit = Suit.Clubs;
break;
default:
throw new ArgumentException();
}
switch(input[0])
{
case "J": case "j":
_cardValue = 11;
break;
case "Q": case "q":
_cardValue = 12;
break;
case "K": case "k":
_cardValue = 13;
break;
case "A": case "a":
_cardValue = 1;
break;
default:
if(!int.TryParse(input.substring(0, input.Length - 1), out _cardValue) || _cardValue < 2 || _cardVaue > 10)
throw new ArgumentException;
break;
}
}
public static Card Parse(string cardString)
{
return new Card(cardString);
}
You might want to add a static method that read a larger string, yield returning cards as it parsed, to allow for easier encoding of several cards.
When I first started on the card.dll, I was using enumerations for suits and card rankings but then I didn't want to have to deal with that same issue and writing extra code to compensate for the strings, there for I wrote a abstract class Info with only two variables
(Flag (byte)) and (Name(string)) to be implemented by the Rank class and Suit class which would be members of the Card class. I have found this to work a lot better for naming conventions and filtering purposes. I love using enums but having to work around variable naming can be a hassle so sometimes it is best not to if you have to get the variable name as string.
So when the Card constructor get called the card ID is entered and then it passes into the Rank and Suit which will then separate what the ID means in code (101 = 100 (suit flag) +
1 (rank flag)). The protected abstract SetName(int cardID) and SetFlag(int cardID) while handle the rest from there in the info's constructor via Rank and Suit. No more issues with the enumeration and it can still be filtered by number via the Flag.
This card naming system uses a 1 through 4 * 100 (telling the suit flag) + 1 through 13 (for card rank). 500 + 14 through 16 are Little Joker, Big Joker, and Wild.
public class Card
{
short id;
public Card(string zFile)
{
this.id = Convert.ToInt16(zFile.Split('.')[0].Trim());
this.Rank = new Rank(id);
this.Suit = new Suit(id);
}
public override string ToString()
{
if (Suit.Flag == 5)
return Suit.Name;
return string.Concat(Rank.Name, " of ", Suit.Name);
}
public override int GetHashCode()
{
return id;
}
public Rank Rank { get; private set; }
public Suit Suit { get; private set; }
public static Card GetGreaterRank(Card value1, Card value2)
{
return (value1.Rank >= value2.Rank) ? value1 : value2;
}
public static bool CompareRank(Card value1, Card value2)
{
return (value1.Rank.Flag == value2.Rank.Flag);
}
public static bool CompareSuit(Card value1, Card value2)
{
return (value1.Suit.Flag == value2.Suit.Flag);
}
};
public abstract class Info
{
protected Info(short cardID)
{
Flag = SetFlag(cardID);
}
protected string SetName(short cardID, params string[] names)
{
for (int i = 0; i < names.Length; i++)
{
if (Flag == (i + 1))
return names[i];
}
return "Unknown";
}
protected abstract byte SetFlag(short cardID);
public static implicit operator byte(Info info)
{
return info.Flag;
}
public byte Flag { get; protected set; }
public string Name { get; protected set; }
};
public class Rank : Info
{
internal Rank(short cardID) : base(cardID)
{
string name = SetName(cardID, "A","2","3","4","5","6","7",
"8","9","10","J","Q","K","Little Joker","Big Joker","Wild");
Name = (name == "Unknown") ? string.Concat(name, " Rank") : name;
}
protected override byte SetFlag(short cardID)
{
return Convert.ToByte(cardID.ToString().Remove(0, 1));
}
};
public class Suit : Info
{
internal Suit(short cardID) : base(cardID)
{
string name = SetName(cardID,"Clubs","Diamonds","Hearts","Spades");
Name = (name == "Unknown") ? string.Concat(name, " Suit") ? name;
}
protected override byte SetFlag(short cardID)
{
return Convert.ToByte(cardID.ToString().Remove(1));
}
};
So now if you have your card image file named 101.png and pass it into the Card ctor it will pass to the Rank and Suit getting the info for you. Really all you are doing in giving the image file a code(numeric) for a name.
I would probably start out with 2 enums, 1 representing the Suits and 1 representing the Faces. Then declare a public property "Suit" and a public property "Face" based off of these enums. You will also probably need an array with the different unique values that a card can have (i.e. 1 throught 13).
You can start enums with number (although it is preferred to start at zero)
public enum Card
{
Two = 2,
Three,
Four,
...
}
Scratch what I wrote before, this is better.
using System;
enum Suit
{
Clubs,
Hearts,
Diamonds,
Spades
}
class Card
{
Suit Suit
{
get;
private set;
}
int Value
{
get;
private set;
}
Card(Suit suit, int value)
{
Suit = suit;
Value = value;
}
private const string[] valsToString = new string[] { "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A" };
bool IsValid()
{
return Value >= 2 && Value <= 14;
}
override string ToString()
{
return string.Format("{0} of {1}", valsToString[Value - 2], Suit);
}
}