how do validate the data [closed] - c#

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
I have a class called UserInfo in which there are two properties Name and ID.
class UserInfo
{
public int Id { get; set; }
public string Name { get; set; }
}
and also i have one custom exception class called UserAlreadyLoggedInException which called in my main method when someone try to use the Name which is already taken by someone.
class UserAlreadyLoggedInException : Exception //
{
public UserAlreadyLoggedInException() : base()
{
}
public UserAlreadyLoggedInException(string message) : base(message)
{
}
public UserAlreadyLoggedInException(string message,Exception innerException) : base(message,innerException)
{
}
Here It Is my main method.
try
{
UserInfo[] Ui = new UserInfo[3];
Ui[0] = new UserInfo();
Ui[1] = new UserInfo();
Ui[2] = new UserInfo();
for (int i = 0; i < 3; i++)
{
Ui[i].Id = i;
Console.WriteLine("Please inter the name of " + (i+1) + " user");
if (i == 0)
{
Ui[i].Name = Console.ReadLine();
}
else
{
Ui[i].Name = Console.ReadLine();
if (Ui[i].Name.Equals(Ui[i - 1].Name))
{
throw new UserAlreadyLoggedInException("UserName Has already taken");
}
}
}
}
catch(Exception ex)
{
Console.WriteLine(ex.GetType().Name + ex.Message);
Console.ReadLine();
}
There are 3 objects of UserInfo Class when [0] index object called it directly take input without any logic because it is the first object.
when [1] index called it will go in to else statement because i here is = 1 , so it will take input and compare it with (i-1) which is zero index , if the name is present it will throw an exception.if the name does not match the loop will continue and the i will become 2 this time , and now again it will go towards else statement and take input , but the prob is here .... now it will compare it with (i - 1 ) which is now become [1] index .. so it will compare the name of 2nd index with 1st index , but not with 0 index ....
how can i compare it with all of the indexes ???

You could put your
if (Ui[i].Name.Equals(Ui[i - 1].Name)){
throw ...
}
code into a loop that goes from 0 -> (i - 1).
So you'd have
for (int j = 0; j < i; j++) {
// (if logic from above, but j instead of (i - 1))
}

You can just check the entire array for the name before you assign it to any item. If you add using System.Linq; to your file, you can use the Any() extension method, which returns true if any item in the array matches the condition:
else
{
string name = Console.ReadLine();
// Before assigning the name to any item, see if it already exists
if (Ui.Any(user => user.Name == name))
{
throw new UserAlreadyLoggedInException("UserName Has already taken");
}
// NOW assign the name
Ui[i].Name = name;
}

Related

Kattis - Recount C# [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 10 months ago.
Improve this question
I'm trying to solve https://open.kattis.com/problems/recount in C#. I have my code written but I know I'm missing something but I'm stuck and I've been working on this for a few days. Whenever I try to run my code I receive a runtime error and I know it's because I need to be able to add a user inputted list to convert to a dictionary but I'm not sure how.
Running on .NET 3.1 for school
Here is the code I have currently
namespace Kattis_Solution___Recount
{
class Program
{
static void Main(string[] args)
{
SortedDictionary<string, int> votes = new SortedDictionary<string, int>();
List<string> names = new List<string>();
string name = "";
name = Console.ReadLine();
Console.Write(name);
Console.Write("\n");
int max = 0;
string winner = "";
while (name[0] != '*')
{
if (votes[name] == 0)
{
names.Add(name);
}
votes[name]++;
if (votes[name] > max)
{
max = votes[name];
winner = name;
}
name = Console.ReadLine();
Console.Write(name);
Console.Write("\n");
}
Console.Write(winner);
Console.Write("\n");
for (int i = 1; i < names.Count; i++)
{
if (votes[names[i]] == max && winner != names[i])
{
Console.Write("Runoff!");
Console.Write("\n");
break;
}
}
}
}
}
You cannot do this if the entry isnt there
if (votes[name] == 0) {
names.Add(name);
}
(unlike some other languages - c++ for example)
You need to do
if (!votes.ContainsKey(name)) {
names.Add(name);
votes[name] = 0;
}
See docs here https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.dictionary-2.item?view=net-6.0
The value associated with the specified key. If the specified key is not found, a get operation throws a KeyNotFoundException, and a set operation creates a new element with the specified key.

how to use if condition with string inside the condition using c# [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
The values are comes from xml, user only declare what condition to do.
string condition ="25<10";
Now, I want to use this in if condition like:
if(condition)
{
//my condition
}
and I am getting this error
Cannot implicitly convert type string to bool
Can anyone tell me how to do this?
If provided conditions are not that complex, you can try an old trick with DataTable:
https://msdn.microsoft.com/en-us/library/system.data.datatable.compute(v=vs.110).aspx
private static bool ComputeCondition(string value) {
using (DataTable dt = new DataTable()) {
return (bool)(dt.Compute(value, null));
}
}
...
string condition ="25<10";
if (ComputeCondition(condition)) {
//my condition
}
First of all:
If you do this string condition ="25<10"condition will have the value 25<10 and not true or flase! If 25, 10 and the < come from your xml paste them into 3 different string like x, y and z and compare them like:
string input = "25<10"; //input form your xml
int operatorPosition;
//get the position of the operator
if(input.contains("<")){
operatorPosition = input.IndexOf("<");
}else{
operatorPosition = input.IndexOf(">");
}
//maybe i messed up some -1 or +1 here but this should work this
string x = input.Substring(0,operatorPosition-1);
string y = input.Substring(operatorPosition+1, input.length-1);
string z = input.charAt(operatorPosition);
//check if it is < or >
if(z.equals("<"){
//compare x and y with <
if(Int32.parse(x) < Int32.parse(y)){
//do something
}else{
//do something
}
}
//z does not equal < so it have to be > (if you dont have something like = otherwise you need to check this too)
else{
if(Int32.parse(x) < Int32.parse(y)){
//do something
}else{
//do something
}
Maybe there is a better way to transform a pure string input into a if clause but this is the way i would go.
You can use this code for do it:
string statment = "10<25"; // Sample statement
string leftOperand = statment.Split('<').First();
string rightOperand = statment.Split('<').Last();
int relationValue = Math.Sign(leftOperand.CompareTo(rightOperand));
if(relationValue == -1)
{
// leftOperand < rightOperand
}
else if (relationValue == 0)
{
// leftOperand == rightOperand
}
else if (relationValue == 1)
{
// leftOperand > rightOperand
}
If you just want check leftOperand < rightOperand you can use ternary operator like this:
bool condition = Math.Sign(leftOperand.CompareTo(rightOperand)) == -1 ? true : false;

Return multiple values from one method C# [duplicate]

This question already has answers here:
Return multiple values to a method caller
(28 answers)
Closed 7 years ago.
Apologies on the duplicate question, I viewed similar Qs and just got confused. I have a method that is prompting a user to enter 5 different attribute values and would like to return the values chosen to be used for later decisions in the program.
while (true)
{
Console.Write("Please enter a value between 0-10 for ingenuity: ");
inputIngenuity = Console.ReadLine();
if (!UInt32.TryParse(inputIngenuity, out validIngenuity))
{
Console.WriteLine();
Console.WriteLine("Input was not a valid value for ingenuity.");
}
else if (validIngenuity < 0 || validIngenuity > 10)
{
Console.WriteLine();
Console.WriteLine("Input was not a valid value for ingenuity.");
}
else if (validIngenuity > (attributePoints - validStrength - validIntelligence - validPersonality - validSpeed))
{
Console.WriteLine();
Console.WriteLine("You do not have enough attribute points remaining.");
}
else break;
}
Console.WriteLine();
Console.WriteLine("You have " + (attributePoints - validStrength - validSpeed - validPersonality - validIntelligence - validIngenuity) + " attribute points remaining");
Console.WriteLine();
Console.WriteLine(String.Format("Strength Value = {0}", validStrength));
Console.WriteLine(String.Format("Speed Value = {0}", validSpeed));
Console.WriteLine(String.Format("Intelligence Value = {0}", validIntelligence));
Console.WriteLine(String.Format("Personaility Value = {0}", validPersonality));
Console.WriteLine(String.Format("Ingenuity Value = {0}", validIngenuity));
Console.WriteLine();
Console.WriteLine("These are your attributes!");
while (true)
{
Console.Write("Do you accept these? Type 1 for Yes, Type 2 for No. If No then choose again: ");
areYouHappyWithChoices = Console.ReadLine();
if (!UInt32.TryParse(areYouHappyWithChoices, out validChoices))
Console.WriteLine("Please try again. Enter 1 for Yes and 2 for No");
else if (validChoices > 2 || validChoices < 1)
Console.WriteLine("Please try again. Enter 1 for Yes and 2 for No");
else if (areYouHappyWithChoices == "2")
chooseAttributePoints(); //this method contains the whole routine
else
Console.WriteLine("We may now begin the game!");
break;
}
UInt32[] attributePointArray = new UInt32[5] { validStrength, validSpeed, validIntelligence, validPersonality, validIngenuity };
return attributePointArray;
The while statement for ingenuity is repeated in the method for the other 4 attributes and works without issues. I'm envisioning later code that would have different results based on how strong the user is for example. Am I going in the right direction by trying to put the values into an array? Thank you.
That would be one way to do it, however I think you'd be better off having a class or struct created to represent the data. This way you'll keep the "strong typey ness" and context of what your data is, rather than simply an array index.
example:
public class Person
{
public int Strength { get; private set; }
public int Speed { get; private set; }
public int Intel { get; private set; }
public int Personality { get; private set; }
public int Ingenuity { get; private set; }
public Person (int strength, int speed, int intel, int personality, int ingenuity)
{
this.Strength = strength;
this.Speed = speed;
this.Intel = intel;
this.Personality = personality;
this.Ingenuity = ingenuity;
}
}
Then your assignment to array:
UInt32[] attributePointArray = new UInt32[5] { validStrength, validSpeed, validIntelligence, validPersonality, validIngenuity };
return attributePointArray;
Gets updated to:
return new Person(validStrength, validSpeed, validIntelligence, validPersonality, validIngenuity);
and your return type needs to be changed from uint[] to Person
This way, rather than having to remember that returnedArray[1] is Speed (or whatever) - you would simply use returnedPerson.Speed.
You should create an object type that wraps the attributes you want to return. The return type of your method will be your newly-created object type.

C# : how do I correctly clone a List<> to onther

I have a two list one is original and other one is copy of original one
List<Button> buttonList; // this is the original list
List<Button> copyButtonList;// this is the copy of button list; this use to sort the list
I want to sort the copyButtonList according to my custom insertion sort where I written in separate class
I clone the original list to copy list following way(s) and sorted it
copyButtonList = buttonList.ToList();
String s = SortEngine.insertionSort(copyButtonList);
msgList.Items.Add(s);
I also try following ways
copyButtonList = new List<Button>(buttonList);
and
foreach (var b in buttonList) {
copyButtonList.Add(b);
}
after that I tried to print the two list as follows
foreach(var b in buttonList){
msgList.Items.Add(b.Text);
}
foreach(var b in copyButtonList){
msgList.Items.Add(b.Text);
}
in the above three situations both list are sorted :(
I want just sort the copyButtonList only, Can anyone point out the my mistakes I done here ?
Updated : my insertion sort algorithm is below
public static String insertionSort(List<Button> button)
{
String key;
int i = 0;
int j;
String s = "";
for (j = 1; j < button.Count; j++)
{
key = button.ElementAt(j).Text;
i = j - 1;
while (i >= 0 && int.Parse(button.ElementAt(i).Text) > int.Parse(key))
{
button.ElementAt(i + 1).Text = button.ElementAt(i).Text;
i = i - 1;
}
button.ElementAt(i + 1).Text = key;
if (i == -1)
{
s=(button.ElementAt(i + 1).Text + " is the starting Item, keep this in before " + button.ElementAt(i + 2).Text);
}
else if (i == j - 1)
{
s=(button.ElementAt(i + 1).Text + " is the last Item, keep this in after " + button.ElementAt(i).Text);
}
else
{
s=(button.ElementAt(i + 1).Text + " is between " + button.ElementAt(i).Text + " and " + button.ElementAt(i + 2).Text);
}
}
if (button.Count == 1)
{
s= ("This is the first Item");
}
return s;
}
Actually speising's question is not dumb.
Since you are not changing the Button there is not need for deep cloning.
Your problem is probably somewhere else.
Here is an example
public class Customer
{
public string Name { get; set; }
public override string ToString()
{
return Name;
}
}
public class CustomerComparer : IComparer<Customer>
{
public int Compare(Customer x, Customer y)
{
return x.Name.CompareTo(y.Name);
}
}
void Print()
{
List<Customer> l1 = new List<Customer>();
l1.Add(new Customer() { Name="aa"});
l1.Add(new Customer() { Name = "cc" });
l1.Add(new Customer() { Name = "bb" });
List<Customer> l2 = new List<Customer>(l1);
l2.Sort(new CustomerComparer());
foreach (var item in l1)
Console.WriteLine(item);
Console.WriteLine();
foreach (var item in l2)
Console.WriteLine(item);
Console.ReadLine();
}
This prints
aa
cc
bb
and then
aa
bb
cc
Update
Your ARE changing the button so you need a deep copy.Use this to create the new list
using System.Linq;
copyButtonList = buttonList.Select(ee => new Button() { Text= ee.Text}).ToList();
By "Changing the button" i mean lines like this
button.ElementAt(i + 1).Text = key;
You may have 2 lists but they both "point"/have the same objects.When you change the Text of a button in list 1 it means that the object is changed also in list 2.
You need to understand what is a value type and what is a reference type and their differences. Here are some links that will help you
http://www.albahari.com/valuevsreftypes.aspx
What is the difference between a reference type and value type in c#?
Also run the following console application on your pc and see what is printed
using System;
public struct Point
{
public int X;
public Point(int initialValue) { X = initialValue; }
}
class Program
{
static void Main(string[] args)
{
Point point1 = new Point(5);
Console.WriteLine("Before:" + point1.X);
ChangePoint(point1);
Console.WriteLine("After:" + point1.X);
Console.ReadLine();
}
private static void ChangePoint(Point p)
{
p.X = 20;
}
}
Then just change the word "struct" to "class" and see what is printed.
You get different result because structs are value types and classes are reference types.
Your sorting algorithm modifies the Buttons, which are the same in both lists. if you really want to do it that way, you need to deep copy the objects, ie. make copies or each button, not just their references.
but a much better solution to sort the list would be to just sort the list, ie. switch the elements indices. (like button[i+1]=button[i])
You can use method mentioned here
List<YourType> oldList = new List<YourType>();
List<YourType> newList = new List<YourType>(oldList.Count);
oldList.ForEach((item)=>
{
newList.Add(new YourType(item));
});

More efficient looping? [closed]

Closed. This question is off-topic. It is not currently accepting answers.
Want to improve this question? Update the question so it's on-topic for Stack Overflow.
Closed 9 years ago.
Improve this question
So I'm writing a simple struct to act like an Array of strings but with some handy operators and other functions that I've always wanted to see in strings. Specifically the method I'm working on right now is the / operator. The problem is, it won't add on any remainders at the end like I want it to.
What it's supposed to do, is take an array of strings, like {"Hello", "Test1", "Test2", "Goodbye", "More?", "Qwerty"} and, say I want to divide by 4, it should return { {"Hello", "Test1", "Test2", "Goodbye"}, {"More?", "Qwerty"} } but it doesn't.
The whole class (the method I want to improve is the / operator, but if you see anything else I can work on please point it out) (I know barely any of it is commented. Sorry about that, didn't expect anyone else to see this code aside from me.):
public struct StringCollection
{
private String[] value;
public StringCollection(params String[] s)
{
this.value = s;
}
public StringCollection(StringCollection current, String ad)
{
if (current.value == null) {
current.value = new String[0] { };
}
this.value = new String[current.value.Length+1];
for (int i=0; i<this.value.Length; i++)
{
try {
this.value[i] = current[i];
} catch {
break;
}
}
this.value[this.value.Length-1] = ad;
}
public StringCollection(StringCollection x, params StringCollection[] y)
{
this.value = x.value;
for (int j=0;j<y.Length;j++)
{
for (int i=0;i<y[j].value.Length;i++)
{
this += y[j][i];
}
}
}
public static StringCollection[] operator /(StringCollection x, int y)
{
StringCollection[] result = null;
if (((int)x.value.Length/y) == ((double)x.value.Length)/y)
result = new StringCollection[y];
else
result = new StringCollection[y+1];
for (int j=0;j<y;j++)
{
for (int i=0;i<((int)x.value.Length/y);i++)
{
result[j] += x.value[i+(int)((x.value.Length/y)*j)];
}
}
if (((int)x.value.Length/y) != ((double)x.value.Length)/y)
{
// This is the part that isn't working.
for (int i=0;i<(((int)x.value.Length/y)*result[0].value.Length)-x.value.Length;i++)
{
result[result.Length-1] += x.value[i+((result[0].value.Length)*result.Length-2)];
}
}
return result;
}
public String this[int index]
{
get {
return this.value[index];
}
set {
this.value[index] = value;
}
}
}
What it does is basically takes your array (single array) and splits it into a bunch of arrays that are the same size, then it adds on the remainder in a new array at the end.
Firstly your question isn't really related to loops at all, or at least loops are only addressed in your code. You should have titled this differently.
Secondly your array adding/removing could be improved; i.e. adding 1 to array size every time and removing 1 then re-copying the entire array every time is a time-sink.
Now onto your question, your code should basically look like this:
//Make your return array
int retLen = x.Length / y;
//Add space for the remainder
if(x.Length % y != 0)
retLen++;
var ret = new StringCollection[retLen];
//Reusing variables is a good way to save memory, but watch naming conventions as this can be confusing
retLen = 0;
var tempCollection = new StringCollection();
for (int i = 0; i < x.Length; i++)
{
tempCollection = new StringCollection(tempCollection, x[i]);
if(i % y == 0 || i == x.Length - 1)
{
ret[retLen++] = tempCollection;
tempCollection = new StringCollection();
retLen = 0;
}
}
return ret;
I really don't like that you don't have a Add function in this struct, just so we're clear. the tempCollection = new StringCollection(tempCollection, x[i]); is f$*kin' TERRIBLE when it comes to time CPU time to create all those new objects.
Pretty sure you'll need to tweak that to make sure all items are entered properly, but that was a first attempt, so ... meh o.O Figured since no one was actually going to answer you I'd take the time.
EDIT: Found a bug, forgot to set retLen back to 0 when adding to ret

Categories

Resources