C# method to check if ID exists and after display Data Inserted - c#

I'm trying to create a CRUD menu that allows me to insert data at an array and also search it by id.
However I'm trying to create a method that allow to check if id exists and after to display the output.
The problem is that the method isn't correct enough for me to display it across other methods, and also at a switch statement. The problem is it repeats two times in row what is the Id you want to check.
Here's the code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace menu
{
class Program
{
private static int id = 1;
enum dataInsert { ID, NAME, SURNAME, ADDRES };
static void Main(string[] args)
{
string[,] matrix = new string[10, 4];
insertData(matrix);
searchId(matrix);
visualizeByid(matrix);
}
static int generateId()
{
return id++;
}
static void insertData(string[,] matrix)
{
int n = generateId();
for (int j = 1; j < matrix.GetLength(1); j++)
{
matrix[n - 1, 0] = Convert.ToString(n);
Console.Write($"Insert {Enum.GetName(typeof(dataInsert), j)}: ");
matrix[n - 1, j] = Console.ReadLine();
}
}
static int searchId(string[,] matrix)
{
int choosenId, index = -1;
do
{
Console.Write("Insert Id to visualize: ");
} while (!int.TryParse(Console.ReadLine(), out choosenId));
for (int i = 0; i < matrix.GetLength(0); i++)
{
if (Convert.ToString(choosenId) == matrix[i, 0])
{
index = i;
}
}
return index;
}
static void visualizeByid(string[,] matrix)
{
int pos = searchId(matrix);
for (int i = pos; i < pos + 1; i++)
{
for (int j = 0; j < matrix.GetLength(1); j++)
{
Console.Write($"{matrix[i, j]}\t");
}
Console.WriteLine();
}
}
}
}

The reason "Insert Id to visualize: " is displayed twice is because your program is calling static int searchId(string[,] matrix) twice in a row:
In Main
static void Main(string[] args)
{
string[,] matrix = new string[10, 4];
insertData(matrix);
searchId(matrix); //Here
visualizeByid(matrix); //Called immediately after
}
And visualizeByid
static void visualizeByid(string[,] matrix)
{
int pos = searchId(matrix); //Here
...
}
You should be able to get your expected result by removing the call to searchId from Main.

Unless I'm misunderstanding, it looks like you have an array of objects. Even if those are simply a name and id.
public class Obj
{
public int Id { get; set; }
public string Name { get; set; }
}
Then you have an array, although you could also use a list.
List<Obj> Objects = new List<Obj>();
To check the list/array by Id you can simply use Linq
if (Objects.Where(o => o.Id == IdToCheck).Count() == 0)
{
//Insert new object
Objects.Add(NewObject);
}

Related

C#: Storage of instances in the class; get NullReferenceException when trying to get theirs value

I am a new to OOP and C#. Here is a small experiment I made:
Using System;
class A
{
public int X { get; set; }
public static A[] a = new A[10];
public static int i = 0;
public A()
{
this.X = -2;
}
public A(int x)
{
this.X = x;
}
public static void Add(A b)
{
if (i < 10) a[i] = b;
i++;
return;
}
public void Reveal()
{
Console.WriteLine(X);
}
public static void Show()
{
for (int j=0; j<=10; ++j)
{
a[j].Reveal();
}
}
}
I tried creating a class that has its instances stored inside, up to 10 objects. When invoke the A.Show() a NullReferenceException is thrown: "Object reference not set to an instance of an object." As I guess, it must be the object a[j] is created, then destroyed immediately. So it give a[j] a null value, hence the result?
*This is my main method:
int val = 0;
while (val != -1)
{
Console.Write("create a new object. new value: ");
val = Console.ReadLine();
A a = new A(val);
A.Add(a);
};
A.Show();
Console.ReadKey();
return;
Please pay attention to the upper bound condition of the loop:
for (int j=0; j<=10; ++j)
{
a[j].Reveal();
}
array a has 10 items assigned,but this code shows you have 11 items beginning from 0 to 10, so change it to just lower than 10.And also try to compare
So the correct code can be as follows :
public static void Show()
{
for (int j = 0; j < 10; ++j)
{
a[j]?.Reveal();//Or if(a[j] != null)
}
}
and also make amendment to line that reads the input of client,that must be as follow:
val = int.Parse(Console.ReadLine());//If you are sure that the input
is truly convertible to int,or
int.TryParse(Console.ReadLine() , out int value);
if(value != 0)
{
val = value;
A a = new A(val);
A.Add(a);
}
else
{
throw new Exception();
}
You're incrementing i before assigning a[i], so a[0] is null because it will always start initializing a at 1.
Try changing the add method to this:
public static void Add(A b)
{
if (i < 10)
{ //braces are important for readability
a[i] = b;
}
i++;
return;
}

Closures with anonymous methods in a for loop

I am trying to understand closures, already read some materials but.. then i tried this.
As far as i understand, a class is generated containing the specific anonymous method (in my case, the one writing to the console) and the int variable j. How does it store all the j values in only one class? Are there many instances of this kind of class generated behind the scenes?
class Program
{
public static List<Action> actions = new List<Action>();
static void Main(string[] args)
{
AddActions(10);
actions[0]();
actions[1]();
Console.ReadLine();
}
public static void AddActions(int count)
{
for (int i = 0; i < count; i++)
{
int j = i;
actions.Add(delegate()
{
Console.Write("{0} ", j);
});
}
}
}
with result: 0 1
Here is your code decompiled into classes rather than lambdas.
private class Program
{
public static List<Action> actions;
static Program()
{
Program.actions = new List<Action>();
}
private static void Main(string[] args)
{
Program.AddActions(10);
Program.actions[0]();
Program.actions[1]();
Console.ReadLine();
}
public static void AddActions(int count)
{
for (int index = 0; index < count; ++index)
{
Program.\u003C\u003Ec__DisplayClass2_0 cDisplayClass20 = new Program.\u003C\u003Ec__DisplayClass2_0();
cDisplayClass20.j = index;
Program.actions.Add(new Action((object)cDisplayClass20, __methodptr(\u003CAddActions\u003Eb__0)));
}
}
private sealed class \u003C\u003Ec__DisplayClass2_0
{
public int j;
public \u003C\u003Ec__DisplayClass2_0()
{
base.\u002Ector();
}
internal void \u003CAddActions\u003Eb__0()
{
Console.Write("{0} ", (object)this.j);
}
}
}
As you can see, for example iteration of the loop you get a new instance of new Program.\u003C\u003Ec__DisplayClass2_0();.
Yes, many instances are generated.
You need an the extra variable j in the scope of the loop body because the variable i has a scope of the method's body, and only a single closure object would be generated for it.
void Main()
{
AddActions(10);
var closure1 = functions[0]();
var closure2 = functions[1]();
Console.WriteLine(object.ReferenceEquals(closure1, closure2));
// False
}
public static void AddActions(int count)
{
for (int i = 0; i < count; i++)
{
int j = i;
functions.Add(delegate()
{
Console.WriteLine(j);
Expression<Func<int>> exp = () => j;
Console.WriteLine(exp.ToString());
var m = (MemberExpression)exp.Body;
var c = (ConstantExpression)m.Expression;
Console.WriteLine(c.Value.ToString());
return c.Value;
});
}
}
public static List<Func<object>> functions = new List<Func<object>>();
Result
0
() => value(UserQuery+<>c__DisplayClass1_0).j
UserQuery+<>c__DisplayClass1_0
1
() => value(UserQuery+<>c__DisplayClass1_0).j
UserQuery+<>c__DisplayClass1_0
False

Fibonacci with huge numbers in c#

I`m trying to find the first fib number to contain 1000 digits. Because i have no data-type capeable of holding such a number, i created a class called hugeNumber which holds the digits in a list, with a decimal base. I get a stack overflow at the generation of the list for the "hugenum" class - I am not sure why (is it really not the right way to do it? Is there a better way?)
Here's my code:
class hugeNum
{
List<int> digits = new List<int>();
public hugeNum(int basic)
{
digits.Add(basic);
}
public hugeNum()
{
}
public static hugeNum operator +(hugeNum first, hugeNum second)
{
hugeNum generated = new hugeNum();
hugeNum finalIter = null;
int carry = 0;
int i = 0;
for (i = 0; i<second.digits.Count && i<first.digits.Count; i++)
{
generated.digits.Add(first.digits[i] + second.digits[i] + carry);
if (generated.digits[i] >= 10)
{
carry = 1;
generated.digits[i] -= 10;
}
else
carry = 0;
}
finalIter = first;
if (i==first.digits.Count)
{
finalIter = second;
}
while (i<finalIter.digits.Count)
{
generated.digits.Add(finalIter.digits[i]);
i++;
}
return generated;
}
public int amountOfDigits()
{
return this.digits.Count;
}
}
class Program
{
public static int fibHugesUntilIter(hugeNum huge1, hugeNum huge2, int reqDigits, int iter)
{
if (huge2.amountOfDigits() == reqDigits)
return iter;
return fibHugesUntilIter(huge2, huge1 + huge2, reqDigits, iter + 1);
}
static void Main(string[] args)
{
Console.WriteLine(fibHugesUntilIter(new hugeNum(1), new hugeNum(1), 1000, 1));
}
}
You can use BigInteger without recursion:
public static int FibHugesUntil(BigInteger huge1, BigInteger huge2, int reqDigits)
{
int number = 1;
while (huge2.ToString().Length < reqDigits)
{
var huge3 = huge1 + huge2;
huge1 = huge2;
huge2 = huge3;
number++;
}
return number;
}
static void Main(string[] args)
{
Console.WriteLine(FibHugesUntil(BigInteger.Zero, BigInteger.One, 1000));
}
Answer: 4782

Not all code paths return a value and how to display methods in C#

I'm trying to find the "Median","Maximum","Minimum","Average","Sum of numbers" and if there is any duplicates in the array. I ran into issues in the beginning when I made my methods and tried calling them in the main method. This produced "An object reference is required to access non-static member" so to combat this I made all the variables public static. Wasn't the best option but it worked. So I tackled the rest and when tried to display that I have duplicates I get "not all code paths return a value" So any help on how to fix this and any way to clean up the code will very helpful.
using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;
public class Test
{
public static int maxNum;
public static int minNum;
public static double avgNum;
public static long sumNum;
public static double median;
public static int MaxNum(int[] randArray)
{
maxNum = randArray.Max();
Console.WriteLine("This is the maximum value: " + maxNum);
return maxNum;
}
public static int MinNum(int[] randArray)
{
minNum = randArray.Min();
Console.WriteLine("This is the minimum value: " + minNum);
return minNum;
}
public static long SumNum(int[] randArray)
{
for(int x =0; x < randArray.Length;x++)
sumNum = sumNum +randArray[x];
Console.WriteLine("This is the sum of values: " + sumNum);
return sumNum;
}
public static double Average(int[] randArray)
{
avgNum = randArray.Average();
Console.WriteLine("This is the average of the values: " + avgNum);
return avgNum;
}
public static int GetMedian(int[] randArray)
{
int size = randArray.Length;
int mid = size / 2;
double median = (size % 2 != 0) ? (double)randArray[mid] : ((double)randArray[mid] + (double)randArray[mid - 1]) / 2;
Console.WriteLine("This is the median value:" + median);
return Convert.ToInt32((median));
}
public static bool ContainDups(int[] randArray)
{
for (int i = 0; i < randArray.Length; i++)
{
for (int j = i + 1; j < randArray.Length; j++)
{
if (randArray [i] == randArray [j])
return true;
}
}
return false;
}
public static int ShowDups(int[] randArray)
{
if(ContainDups(randArray) == true)
{
Console.WriteLine("Contains duplicate numbers");
}
else
{
Console.WriteLine("No duplicate numbers");
}
}
public static void Main()
{
int[] randArray = new int[1000];
Random r = new Random();
for(int i = 0; i < randArray.Length; i++)
{
randArray[i] = r.Next();
}
Array.Sort(randArray);
for (int i = 0; i < 1000; i++)
{
// Console.WriteLine(","+randArray[i]);
}
MaxNum(randArray);
MinNum(randArray);
SumNum(randArray);
Average(randArray);
GetMedian(randArray);
ContainDups(randArray);
ShowDups(randArray);
}
}
This method public static int ShowDups(int[] randArray) doesn't return anything. You just write to te console a message and you don't return an int as it is expected by the signature of your method.
First if all the class members are static, just make the class to be static instead .
Secondly, if you have no intention to return value in your function and just write to console, then use void instead of int

How do I sort these arrays of objects in ascending order in C#?

Here is my array of objects
Game[] gameConsoles = new Games[5];
// paramaters are name of the console and game ID
gameConsoles[0] = new Games("Playstation 4", 101);
gameConsoles[1] = new Games("Xbox 1", 108);
gameConsoles[2] = new Games("PS Vita", 110);
gameConsoles[3] = new Games("Wii U", 104);
gameConsoles[4] = new Games("3DS", 102);
for (int i = 0; i < gameConsoles.Length; i++)
{
gameConsoles[i].display();
}
It will basically display all 5 objects in each message box but how do I make it so that it can display them based on the game ID order in ascending?
My sorting algorithm I used when I sorted a regular array of numbers.
public void ascendingOrder()
{
// helper class
double temp = 0;
for (int j = 0; j < numbers.Length; j++)
{
for (int i = 0; i < numbers.Length - 1; i++)
{
if (numbers[i] > numbers[i + 1])
{
temp = numbers[i];
numbers[i] = numbers[i + 1];
numbers[i + 1] = temp;
}
}
}
}
You can use use LINQ OrderBy.
foreach(var item in gameConsole.OrderBy(r=> r.GameID))
{
item.display();
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication3
{
class Program
{
static void Main(string[] args)
{
SortedDictionary<int, Game> gameConsoles = new SortedDictionary<int, Game>();
gameConsoles.Add(101, new Game("Playstation 4", 101));
gameConsoles.Add(108, new Game("Xbox 1", 108));
gameConsoles.Add(110, new Game("PS Vita", 110));
gameConsoles.Add(104, new Game("Wii U", 104));
gameConsoles.Add(102, new Game("3DS", 102));
foreach (KeyValuePair<int, Game> item in gameConsoles)
{
Console.WriteLine(item.Value.ToString());
}
Console.ReadKey();
}
}
public class Game
{
public Game(string name, int id)
{
Id = id;
Name = name;
}
public int Id { get; set; }
public string Name { get; set; }
public override string ToString()
{
return string.Format("Id: {0} Name: {1}", Id, Name);
}
}
}
There are three common ways to order items in .NET:
Using LINQ (your comments suggest that this is not allowed for the purposes of your assignment)
Implementing IComparable<Games> in your Games class, or
Providing an instance of IComparer<Games> to the Sort method.
Here is how you implement IComparable<Games>:
class Games : IComparable<Games> {
public int CompareTo(Games other) {
return GameId.CompareTo(other.GameId);
}
}
Now your Games would sort based on GameId.
Here is how you use an external IComparer<Games>:
class CompareGamesOnId : IComparer<Games> {
int Compare(Games a, Games b) {
return a.GameId.CompareTo(b.GameId);
}
}
You call Sort like this:
Array.Sort(games, new CompareGamesOnId());
You could use a 1 liner for this. LINQ is good for operations which do not affect the set.
gameConsoles.OrderBy(gc => gc.GameID).ToList().ForEach(g => g.display());
Implement IComparable on Games and use the .Sort method?IComparable
You can try LINQ without using the dreaded => symbol, although of course, it is not recommended for simplicity purposes. However, this explains what exactly is => doing,
foreach (var item in gameConsole.OrderBy(delegate(Game g) { return g.GameId; }))
{
item.display();
}

Categories