I want to create a program where I can save cars based of their models, types and license plates. I try to save all of this information inside a dictionary but they aren't saved as to when I search for them
through the 2nd option ("2. Search Vehicle") they aren't found. Here is my code:
What should I do in order for my code to work? I want to be able to search for the cars through their license plates (Swedish license plates, ABC123) but I can't figure out why the dictionary values aren't saved which I enter through my ReadLines()
Dictionary<string, string> newVehicle = new Dictionary<string, string>();
bool sunfleetAdminTools = true;
Dictionary<string, string> newVehicle = new Dictionary<string, string>();
do
{
WriteLine("1. Add Vehicle");
WriteLine("2. Search Vehicle");
WriteLine("3. Log Out");
ConsoleKeyInfo keyInput = ReadKey(true);
Clear();
switch (keyInput.Key)
{
case ConsoleKey.D1:
Clear();
bool invalidCarCredentials = true;
do
{
Write("Registration Number: ");
string regNumber = ReadLine();
newVehicle["Registration Number"] = regNumber;
Write("Brand: ");
string brand = ReadLine();
newVehicle["Brand"] = brand;
Write("Model: ");
string vehicleModel = ReadLine();
newVehicle["Model: "] = vehicleModel;
Write("Type (Sedan, Compact, Subcompact): ");
string vehicleType = ReadLine();
newVehicle["Type: "] = vehicleType;
Write("Autopilot (Yes, No): ");
string autoPilot = ReadLine();
newVehicle["Autopilot: "] = autoPilot;
Clear();
foreach (KeyValuePair<string, string> kvp in newVehicle)
{
WriteLine("Car {0}: {1}", kvp.Key, kvp.Value);
}
WriteLine("Is this correct? (Y)es (N)o");
ConsoleKeyInfo newInput = ReadKey(true);
if (newInput.Key == ConsoleKey.Y)
{
Clear();
WriteLine("Vehicle registered.");
Thread.Sleep(2000);
Clear();
break;
}
else if (newInput.Key == ConsoleKey.N)
{
Clear();
}
} while (invalidCarCredentials);
break;
case ConsoleKey.D2:
Write("Search for vehicle by license plate: ");
string searchingForVehicle = ReadLine();
if (newVehicle.ContainsValue(searchingForVehicle))
{
WriteLine("Value found.");
foreach (KeyValuePair<string, string> kvp in newVehicle)
{
WriteLine("Car {0}: {1}", kvp.Key, kvp.Value);
}
}
else
{
WriteLine("Car not found.");
Thread.Sleep(2000);
}
Clear();
break;
case ConsoleKey.D3:
Clear();
WriteLine("Logging out...");
Thread.Sleep(1000);
sunfleetAdminTools = false;
Environment.Exit(0);
break;
}
} while (sunfleetAdminTools);
but they aren't saved
You stepped into an interesting trap of dictionary syntactic suggar. It has to do with the way you try to add values to the dictionary:
newVehicle["Registration Number"] = regNumber;
If the dictionary is empty, then the key "Registration Number" will be created and saved with regNumber as key value pair. On the other hand if this key already exists, then the value on this key will be simply overwritten!
This is why your problem arises and you get the impression that the values are not saved. You should always be able to find the last values that you have entered.
If you would have used the oldscool way of adding values:
newVehicle.Add("Registration Number", regNumber);
this would have led to an exception that the key already exists. You would have immideately realised that this cannot work.
What should I do in order for my code to work?
You should addapt an object oriented approach and encapsulate all information that belong together in one class:
public class VehicleRepresentation
{
public string RegistrationNumber { get; set; }
public string Brand { get; set; }
public string Model { get; set; }
public string Type { get; set; }
public bool AutoPilot { get; set; }
}
Now you can use a List<VehicleRepresentation> allVehicles to collect all your cars.
VehicleRepresentation vehicle = new VehicleRepresentation();
Console.Write("Registration Number: ");
vehicle.RegistrationNumber = Console.ReadLine();
Console.Write("Brand: ");
vehicle.Brand = Console.ReadLine();
Console.Write("Model: ");
vehicle.Model = Console.ReadLine();
Console.Write("Type (Sedan, Compact, Subcompact): ");
vehicle.Type = Console.ReadLine();
Console.Write("Autopilot (Yes, No): ");
vehicle.AutoPilot = Console.ReadLine() == "Yes";
Console.Clear();
allVehicles.Add(vehicle);
Edit:
Addition by WSC:
typically you'd want to create an enum for vehicle.Type rather than a list of user entered strings. Getting that from user input might be a bit cumbersome in a console environment, however.
Search:
The searching can be implemented in different ways. If you want to keep your loop
foreach(var veh in allVehicles)
{
if(veh.RegistrationNumber == searchingForVehicle)
{
WriteLine("Value found.");
// write here all the information you want to display.
}
}
You can of course use also LINQ for filtering. But that you can figure out on your own I guess.
Related
static void AddContact()
{
string path = #"C:\Users\...\Desktop\Projekte\C# Übungen\ContactList/contacts.txt";
string name, address;
int phoneNumber;
bool addingContact = true;
string response;
List<string> ContactList = File.ReadAllLines(path).ToList();
while(addingContact)
{
System.Console.Write("Name: ");
name = Console.ReadLine();
System.Console.Write("Nummer: ");
phoneNumber = int.Parse(Console.ReadLine());
System.Console.Write("Adresse: ");
address = Console.ReadLine();
ContactList.Add($"Name: {name}");
ContactList.Add($"Nummer: {phoneNumber}");
ContactList.Add($"Adresse: {address} \n---------------------------------");
foreach (var contact in ContactList)
{
File.WriteAllLines(path, ContactList);
}
Console.Clear();
System.Console.WriteLine("Contact added successfully! Would you like to Add another Contact? (y)(n)");
response = Console.ReadLine().ToLower();
if(response == "y")
{
Console.Clear();
}
else
{
addingContact = false;
}
}
Console.WriteLine("Good bye!");
}
static void ShowContact()
{
string path = #"C:\Users\...\Desktop\Projekte\C# Übungen\ContactList/contacts.txt";
string response;
System.Console.WriteLine("Would you like to see all contacts (0) or a specific one (1)?");
response = Console.ReadLine();
switch (response)
{
case "0":
File.ReadAllLines(path);
break;
case "1":
System.Console.WriteLine("Type the name of the user: ");
string username = Console.ReadLine();
File.ReadAllLines(path)
break;
}
}
Thats everything. In the switch Statement at case 1 is where the problem is. I want it to look something like this if the user types John for example:
Name: John
Number: 233
Address: lolol 23
I already tried out something but i stopped in the middle of writing it because i realized that i dont actually know how to code that so i made my way over to stackoverflow to ask for help, thanks. Please be polite and i know that this code isnt the best, im a beginner.
Edit: I just found out that ShowContacts doesnt work at all
Edit 2: Fixed it with a foreach loop and List
List<string> contacts = File.ReadAllLines(path).ToList();
System.Console.WriteLine("Would you like to see all contacts (0) or a specific one (1)?");
response = Console.ReadLine();
switch (response)
{
case "0":
foreach (var contact in contacts)
{
Console.WriteLine(contact);
}
break;
}
Okay, if each item is broken down by three values consider chunking the data by three than iterate the results.
Change the Debug.WriteLine to Console.WriteLine below for your code.
Extension method for chunking
public static class ListExtensions
{
public static List<List<T>> ChunkBy<T>(this List<T> source, int chunkSize)
=> source
.Select((value, index) => new { Index = index, Value = value })
.GroupBy(x => x.Index / chunkSize)
.Select(grp => grp.Select(v => v.Value).ToList())
.ToList();
}
File contents
John
111
John's address
Mary
222
Mary's address
Bill
333
Bill's address
Code to first assert data is divisible by three than read the data, no assertion of data types or if null values are performed.
var contents = File.ReadAllLines("TextFile1.txt");
if (contents.Length % 3 == 0)
{
var results = contents.ToList().ChunkBy(3);
foreach (var list in results)
{
Debug.WriteLine($" Name: {list[0]}");
Debug.WriteLine($" Number: {list[1]}");
Debug.WriteLine($"Address: {list[2]}");
}
}
else
{
Debug.WriteLine("Malformed");
}
Edit: placed into a method
private static void ViewAllContacts()
{
var fileName = "TextFile1.txt";
if (File.Exists(fileName))
{
var contents = File.ReadAllLines(fileName);
if (contents.Length % 3 == 0)
{
var results = contents.ToList().ChunkBy(3);
foreach (var list in results)
{
Debug.WriteLine($" Name: {list[0]}");
Debug.WriteLine($" Number: {list[1]}");
Debug.WriteLine($"Address: {list[2]}");
}
}
else
{
Debug.WriteLine("Malformed");
}
}
else
{
Debug.WriteLine($"{fileName} not found");
}
}
Save your contact to json format, like this:
using System;
using System.Collections.Generic;
using System.Text.Json;
using System.IO;
namespace JsonTester
{
// Open Package Manager Console:
// Tools >> Nuget Package Manager >> Package Manager Console
//
// Install libraries through Package Manager Console:
// PM > Install-Package System.Text.Json -Version 6.0.1
internal class Program
{
static List<Contact> contactList = new List<Contact>();
static readonly string MY_CONTACT = #"D:\MyContact.txt";
class Contact {
public string Name { get; set; }
public string Number { get; set; }
public string Address { get; set; }
}
static void EnterContact() {
var contact = new Contact();
Console.WriteLine("Name: ");
contact.Name = Console.ReadLine();
Console.WriteLine("Number: ");
contact.Number = Console.ReadLine();
Console.WriteLine("Address: ");
contact.Address = Console.ReadLine();
contactList.Add(contact);
}
static void SaveContact() {
if (contactList.Count > 0) {
foreach (Contact contact in contactList) {
String strContactJson = JsonSerializer.Serialize(contact);
File.AppendAllText(MY_CONTACT, strContactJson + "\n");
}
}
}
static void ReadContact()
{
try
{
Console.WriteLine("Read contact list:\n");
String[] strContactJsonArr = File.ReadAllLines(MY_CONTACT);
if (strContactJsonArr.Length > 0)
{
foreach (String s in strContactJsonArr)
{
Contact contact = JsonSerializer.Deserialize<Contact>(s);
if (contact != null)
{
Console.WriteLine("Name: " + contact.Name);
Console.WriteLine("Number: " + contact.Number);
Console.WriteLine("Address: " + contact.Address);
Console.WriteLine("");
}
}
Console.WriteLine("Found {0} contacts\n\n", strContactJsonArr.Length);
}
}
catch (Exception) {
Console.WriteLine("Contact list is empty\n");
}
}
static bool SearchContact(String name)
{
try
{
String[] strContactJsonArr = File.ReadAllLines(MY_CONTACT);
if (strContactJsonArr.Length > 0)
{
foreach (String s in strContactJsonArr)
{
Contact contact = JsonSerializer.Deserialize<Contact>(s);
if (contact != null)
{
if (contact.Name.Equals(name)) {
Console.WriteLine("");
Console.WriteLine("Name: " + contact.Name);
Console.WriteLine("Number: " + contact.Number);
Console.WriteLine("Address: " + contact.Address);
Console.WriteLine("");
return true;
}
}
}
}
}
catch (Exception)
{
}
return false;
}
static void Main(string[] args)
{
while (true)
{
Console.WriteLine("- Press S for search contact.\n- Press N for new contact.\n- Press R for read contact list.\n");
ConsoleKeyInfo key = Console.ReadKey(true);
if (key.KeyChar == 's' || key.KeyChar == 'S')
{
Console.WriteLine("Searching contact.");
Console.Write("Enter name: ");
String name = Console.ReadLine();
bool isFounded = SearchContact(name);
if (isFounded)
{
Console.WriteLine("Contact is found\n");
}
else
{
Console.WriteLine("Contact isn't found!\n");
}
}
else if (key.KeyChar == 'n' || key.KeyChar == 'N')
{
EnterContact();
SaveContact();
}
else if (key.KeyChar == 'r' || key.KeyChar == 'R') {
ReadContact();
}
}
}
}
}
Console Output:
MyContact.txt (contact save in JSON format):
I am trying to find duplicates from user inputs. I am trying to add customers with their first name, last name, and phone number. If all three of the information already exists, I want to throw an appropriate message saying {firstname}, {lastname}, and {phonenumber} already exists. Any idea how to do it?
//this code is on functions class.
public bool addCustomer(params)
{
if (numCustomer < maxCustomer)
{
Random rnd = new Random();
int id = rnd.Next(10000, 99999);
clist[numCustomer] = new Customer(params);
numCustomer++;
return true;
}
return false;
}
//Menu class to prompts user to choose an option
switch (input)
{
case 1: // Add Customer
Console.Clear();
string fName;
string lName;
long phone;
Console.WriteLine("Adding new customer...\nPlease enter the following:");
Console.Write("First Name: ");
fName = Console.ReadLine();
Console.Write("Last Name: ");
lName = Console.ReadLine();
Console.Write("Phone Number (no dashes or spaces): ");
phone = Convert.ToInt64(Console.ReadLine());
m.addCustomer(fName, lName, phone);
Console.WriteLine("\nPress any key to go back to the Customer Menu...");
Console.ReadKey();
customerMenu();
break;
...
}
I'm coding a game for a university project similar to Subway Surfers. I have everything working precisely but my problem comes in a bookmarks option I coded.
When you lose in the game you have to enter a name and this is written and saved on a text file in the format <int score> <string name>, for example:
11245 Lucas
10123 Marco
2394 Ricky
So then in the menu of the game you can select bookmarks and the text file is read and shown on the screen one score under the other with the name that was written in each game.
Now my problem is that I want the bookmarks to be ordered, with the highest on top, but I do not know how I can do that as I have an int and a string in each line and they are related therefore I can't have one file for the scores and one file for the names as therefore when I order the scores I lost the info regarding who achieved each score.
What can I do to solve this?
EDIT:
I'm adding the part of the code related to my question.
This is the method that shows the bookmarks
static void ReadBookmark()
{
Console.Clear();
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine("BOOKMARKS");
string myfile = #"bookmarks.txt";
if (File.Exists(myfile) == false)
{
Console.WriteLine("\n");
Console.ForegroundColor = ConsoleColor.White;
Console.WriteLine("NO BOOKMARKS. PLAY SOME GAMES!");
Console.Write("\nPRESS A KEY TO RETURN...");
Console.ReadKey();
}
else
{
Console.WriteLine("\n");
Console.ForegroundColor = ConsoleColor.Green;
using (StreamReader sr = File.OpenText(myfile))
{
string s = "";
while ((s = sr.ReadLine()) != null)
{
Console.WriteLine($"\t{s}");
}
}
Console.ForegroundColor = ConsoleColor.White;
Console.Write("\n\nPRESS A KEY TO RETURN...");
Console.ReadKey();
}
}
And here is the code where the name and score are written on the file.
public void SaveBookmark(int score, string name)
{
string myfile = #"bookmarks.txt";
using (StreamWriter sw = File.AppendText(myfile))
{
sw.WriteLine($"{score} {name}");
}
}
You can split each line on whitespace and then use int.Parse to get the numeric value of the first part, and then OrderByDescending using that value:
var orderedLines = File.ReadLines(myfile)
.OrderByDescending(line => int.Parse(line.Split()[0]))
.ToList();
Full example of what to do safely, finished before you posted your code.
This will allow the names to have a space in them.
public List<ScoreItem> GetScores()
{
var scoreList = new List<ScoreItem>();
using (var fs = File.OpenRead("myPath"))
using (var sr = new StreamReader(fs))
{
while (!sr.EndOfStream)
{
var line = sr.ReadLine();
if (string.IsNullOrWhiteSpace(line)) continue;
var scoreMatch = Regex.Match(line, #"\A\d*");
if (!scoreMatch.Success)
throw new Exception($"Failed to parse score from line [{line}].");
var nameMatch = Regex.Match(line, #"(?<!\A\d*).*\Z");
if (!nameMatch.Success)
throw new Exception($"Failed to parse name from line [{line}].");
if (!int.TryParse(scoreMatch.Value, out var score))
throw new Exception($"Failed to cast score to a number from line [{line}].");
scoreList.Add(new ScoreItem {Name = nameMatch.Value, Score = score});
}
return scoreList.OrderByDescending(s => s.Score).ToList();
}
}
public class ScoreItem
{
public string Name { get; set; }
public int Score { get; set; }
}
I'm currently having issue on editing an existing username and password that i stored in a list.
Declarations:
public static Administrator Cadmin = new Administrator("", "", "", "");
public static Staff Cstaff = new Staff("", "", "", "");
public static Administrator Ladmin = new Administrator("", "", "", "");
public static Staff Lstaff = new Staff("", "", "", "");
public static string NCName;
public static string NCPassword;
List<User> UserList = new List<User>();
Executing code:
Console.WriteLine("Which user would you like to edit?");
string ruser = Console.ReadLine();
bool Ustop = false;
while (!Ustop)
{
foreach (User u in UserList)
{
if (ruser == Cadmin.CName)
{
Console.WriteLine("Please key in the existing password of the selected username");
string epass = Console.ReadLine();
if (epass == Cadmin.CPassword)
{
Console.WriteLine("Create new Administrator Username:");
NCName = Console.ReadLine();
Console.WriteLine("\nCreate new Administrator Password: ");
NCPassword = Console.ReadLine();
ruser.Replace(ruser, NCName);
epass.Replace(epass, NCPassword);
}
else
{
Console.WriteLine("Password that you key in is invalid!");
}
}
else
{
Console.WriteLine("Username that you key in did not exist!");
Console.WriteLine("Please key in a valid username");
}
}
}
I understood that you have issues on storing data in currently filled List, so here are one solution, use for instead if foreach, and then you can edit the specific member of the list, using it's index (I considered that CAdmin is inherited from User and User class has properties for CName and CPassword):
bool Ustop = false;
while (!Ustop)
{
for (var i = 0; i< UserList.Count ; i++ )
{
User u = UserList[i];
if (ruser == u.CName)
{
Console.WriteLine("Please key in the existing password of the selected username");
string epass = Console.ReadLine();
if (epass == u.CPassword)
{
Console.WriteLine("Create new Administrator Username:");
NCName = Console.ReadLine();
Console.WriteLine("\nCreate new Administrator Password: ");
NCPassword = Console.ReadLine();
u.CName = NCName;
u.CPassword = NCPassword;
}
else
{
Console.WriteLine("Password that you key in is invalid!");
}
}
else
{
Console.WriteLine("Username that you key in did not exist!");
Console.WriteLine("Please key in a valid username");
}
}
}
I need to create a program that will take the users name and "password". If they match the program will say you are in if not, that you're out. I wrote it for 1 user, but I don't know how to make multiple users in one program. My code is below. Thanks for your help :)
Console.WriteLine("Enter your Name");
Console.WriteLine("Enter your Pswrd");
string name = Console.ReadLine();
string pswrd = Console.ReadLine();
string myname = "John";
string mypswrd = "123456";
if (name == myname & pswrd == mypswrd)
{
Console.WriteLine("You are logged in");
}
else
{
Console.WriteLine("Incorrect name or pswrd");
}
Console.ReadLine();
//building the user "database" each pair is <user,password>
Dictionary<string, string> users = new Dictionary<string, string>();
users.Add("John", "123456");
//Here you should add more users in the same way...
//But i would advise reading them from out side the code (SQL database for example).
Console.Writeline("Enter your Name");
string name = Console.ReadLine();
Console.WriteLine("Enter your Passward");
string password = Console.ReadLine();
if (users.ContainsKey(name) && users[name] == password)
{
Console.WriteLine("You are logged in");
}
else
{
Console.WriteLine("Incorrect name or password");
}
Console.ReadLine();
This should work (contains no checks to see if the entered values are correct or not, you should add this kind of safety yourself :)):
Dictionary<string, string> namesToCheck = new Dictionary<string, string>
{
{"John", "123456"},
{"Harry", "someotherpassword"}
};
Console.WriteLine("Enter your Name");
string name = Console.ReadLine();
Console.WriteLine("Enter your Pswrd");
string pswrd = Console.ReadLine();
if (namesToCheck.ContainsKey(name) && namesToCheck[name] == pswrd)
{
Console.WriteLine("You are logged in");
}
else
{
Console.WriteLine("Incorrect name or pswrd");
}
Console.ReadLine();
Why not use arrays?
Console.WriteLine("Enter your Name");
Console.WriteLine("Enter your Pswrd");
string name = Console.ReadLine();
string pswrd = Console.ReadLine();
string[] names = "James,John,Jude".Split(Convert.ToChar(","));
string[] passes = "Pass1, Word2, Password3".Split(Convert.ToChar(","));
for (int i = 0; i<names.Length, i++)
{
if (names[i] == name && passes[i] == pswrd)
{
Console.WriteLine("You are logged in");
}
else
{
Console.WriteLine("Incorrect name or pswrd");
}
}
This will work with the following name/pswrd combinations:
James/Pass1, John/Word2, Jude/Password3
For a bigger list I suggest you use external text file and read lines in each.