Vill du vara del av diskussionerna i forumet, ställa frågor eller hjälpa andra? Registrera dig här!

Förklaring: ta bort en vektor från en lista med fler vektorer

Trädvy Permalänk
Medlem
Registrerad
Nov 2019

Förklaring: ta bort en vektor från en lista med fler vektorer

Hej! Jag som otroligt många andra behöver hjälp med loggboken, den är en uppgift i Programmering 1. Jag har en känsla av att jag har gjort så otroligt fel och tänkte att ni kunde göra input över vad jag har klantat till.

I dagsläget så får jag inte till det med att ta bort det inlägg som jag har valt själv. Skriver jag bara "kjgdöobg" så försvinner det första inlägget. Skriver jag allt korrekt så funkar det som det ska. Jag trodde tryParse fångar upp felaktiga svar?

Jag undrar också över min sökalgoritm. Hur skulle man gå tillväga om man vill söka på datum?

Jag skulle bli oerhört tacksam om jag fick en förklaring till detta!!!

using System; using System.Collections.Generic; //Den här lägger jag till för att kunna använda mig av listor. namespace Loggboken { class MainClass { //*************************************************************************************************************************** public static void Main(string[] args) { List<string[]> blogEntry = new List<string[]> { };//Här skapar jag min lista och döper den till blogEntry. Jag deklarerar den även som en string-lista. DateTime time = DateTime.Now;// Här deklarerar jag dagens datum och döper det till time. int menu;//Här deklarerar jag menyvalet till en int, för att senare kunna använda i switchen. bool isRunning = true; //Skapar ett boolean värde och sätter det till sant, döper den till isRunning. På det sättet loopar menyn tills användaren trycker på avsluta. while (isRunning) //*************************************************************************************************************************** { Console.WriteLine("**********Hej och välkomna till Bloggen!**********"); Console.WriteLine("Gör ett av följande val: \n[1]Skriv ett nytt logginlägg \n[2]Skriv ut alla logginlägg \n[3]Sök bland titlar på logginläggen \n[4]Ta bort inlägg \n[5]Avsluta programmet"); Int32.TryParse(Console.ReadLine(), out menu);//Mitt menyval, här använder jag mig av TryParse för att fånga upp felaktiga svar. Jag konverterar sedan min svar till en int. //*************************************************************************************************************************** switch (menu) { case 1: string[] post = new string[3]; //För att spara värderna i "post" behöver jag deklarera den i case 1. Jag talar även om för programmet att den innehåller 3 vektorer. Console.Clear();//Rensar undan menyn Console.WriteLine(time.ToLongDateString()); // Här skriver jag ut datumet. Console.WriteLine("Lägg till rubrik: "); post[0] = Console.ReadLine(); //Döper vektor 1 till post[0] och berättar att posten är vad användaren skriver in. Console.WriteLine(" Skriv text nedan: "); post[1] = Console.ReadLine();//Döper vektor 2 till post[1]. post[2] = Convert.ToString(time); // Här sparar jag datumet i vektor 3. blogEntry.Add(post);// Här sparas min alla vektorerna i min lista. Console.Clear(); break; //*************************************************************************************************************************** case 2: Console.Clear(); foreach (string[] entry in blogEntry) //För varje logginlägg i loggen.... { Console.WriteLine("{0}\n{1}\n{2}", entry[0], entry[1], entry[2]);// ......Skriv ut alla logginlägg och inkludera rubrik, inlägg samt datum. Console.ReadLine(); Console.Clear(); } break; //*************************************************************************************************************************** case 3: Console.Clear(); Console.WriteLine("Skriv in en titel på ett inlägg: "); string result = Console.ReadLine(); //Tar användarens sökord och konverterar till en string som jag döper till result foreach (string[] entry in blogEntry) if (entry[0] == result || entry[1] == result) { Console.WriteLine("{0}\n{1}\n{2}", entry[0], entry[1], entry[2]); Console.ReadLine(); } Console.Clear(); break; //*************************************************************************************************************************** case 4: Console.Clear(); Console.WriteLine("Vill du ta bort alla loggar eller bara en?" + "\n[J] för JA ta bort alla loggar \n[N] för NEJ ta bara bort en av mina loggar"); string answer = Console.ReadLine(); int yourChoice; if (answer == "j" || answer == "J") { blogEntry.Clear(); Console.Clear(); } else if (answer == "n" || answer == "N") { Console.Clear(); foreach (string[] entry in blogEntry) { Console.WriteLine("{0}\n{1}\n{2}", entry[0], entry[1], entry[2]); } Console.WriteLine("\nVänligen skriv titeln på det inlägg du vill ta bort"); int.TryParse(Console.ReadLine(), out yourChoice); blogEntry.RemoveAt(yourChoice); Console.Clear(); } else { Console.WriteLine("Klicka på enter för att återgå till huvudmenyn"); Console.ReadLine(); Console.Clear(); } break; //*************************************************************************************************************************** case 5: Console.Clear();//Här sätter jag while-loopen till falskt för att avsluta programmet. isRunning = false; break; //*************************************************************************************************************************** default: //Defaulten fångar upp om användaren skriver in annat än vad som går att välja i switchen. Console.WriteLine("Fel! Försök igen"); Console.ReadLine(); break;

Trädvy Permalänk
Medlem
Registrerad
Apr 2002

Gällande TryParse så är själva idén att den returnerar ett booleskt värde som säger om den lyckades eller ej. Du bör med andra ord använda returvärdet.

AMD Ryzen7 3800X || Gigabyte X570 Ultra || Evga GTX 1080Ti || Crucial Ballistix Sport 3200 64GB || Samsung 950 Pro 512GB || Samsung 960 Pro 1024GB || XB270HU 1440p IPS G-Sync

Trädvy Permalänk
Medlem
Registrerad
Nov 2019

@evil penguin:
Jävligt sant. Har ju gjort det i menyvalet. Ska fixa till! Tack!

Trädvy Permalänk
Medlem
Plats
Linköping
Registrerad
Jun 2007

Gällande att söka efter inlägg så har du ju för tillfället följande kod:

Console.WriteLine("Skriv in en titel på ett inlägg: "); string result = Console.ReadLine(); //Tar användarens sökord och konverterar till en string som jag döper till result foreach (string[] entry in blogEntry) if (entry[0] == result || entry[1] == result) { Console.WriteLine("{0}\n{1}\n{2}", entry[0], entry[1], entry[2]); Console.ReadLine(); }

För det första är det lite dålig stil att skriva en foreach utan "måsvingar" ({ }) på det här sättet, särskilt när du lagt in en tom rad mellan foreach- och if-satsen. Koden blir svårare att läsa, och det är väldigt lätt hänt att det blir fel om du vill lägga till mer kod inne i loopen:

foreach (string[] entry in blogEntry) Console.WriteLine(entry[0]); // Skriv ut alla titlar. if (entry[0] == result || entry[1] == result) // Oops, if-satsen hör inte längre till foreach-satsen. ...

För det andra så gör koden inte vad utskriften säger att den kommer göra. Utskriften frågar efter en titel, men du söker efter antingen en titel eller en text. Du har samma problem när du tar bort inlägg, där du frågar efter en titel men läser in ett index.

Men när det gäller att söka efter datum så söker du för tillfället på titel (entry[0]) samt text (entry[1]). Så att klura ut hur du söker efter datum entry[2] borde inte vara något större problem.

Sen är en lista med strängar ett tämligen dåligt val av datastruktur för ett inlägg, eftersom blir oklart i koden vad t.ex. entry[0] egentligen representerar. Jag utgår ifrån att det är ett krav i uppgiften att ni ska göra så, men ett sätt du kan göra koden tydligare är att använda konstanter. Du kan t.ex. lägga till konstanter i början av din klass:

class MainClass { private const int TITLE = 0; private const int TEXT = 1; private const int DATE = 2; public static void Main(string[] args) ...

Istället för att skriva t.ex. entry[0] så kan du då istället skriva entry[TITLE], vilket gör det mycket tydligare vad koden faktiskt gör.

Trädvy Permalänk
Medlem
Plats
Sthlm
Registrerad
Jul 2001

Du har delvis rätt i vad TryParse gör.
Den kommer att tilldela värdet den parsar till variabeln du anger om går, annars får den defaultvärdet (för en int ät det 0).

Men, för att veta om det gick bra eller inte så måste du kolla returvärdet från den. True innebär att den kunde parsa, medan false innebär att det var ett ogiltigt värde.

Dvs om du skriver in "a", så kommer den sätta värdet till 0, och returnera false. Eftersom du inte kollar att det inte gick så kommer det att ta bort det första inlägget (index 0).

Skickades från m.sweclockers.com

Pain, Agony, Suffering, Torment. When the Rune is invoked, even the earth shall resonate its anguish.
Torment of the mind. Torment of the body. Torment of the soul. All will be made clear when the circle is drawn.

Trädvy Permalänk
Medlem
Registrerad
Nov 2019

@perost: Aha!! mycket mer logiskt! tack!

Men bara för att förtydliga. När jag ska ta bort ett inlägg är det:

foreach (string[] entry in blogEntry) { Console.WriteLine("{0}\n{1}\n{2}", entry[0], entry[1], entry[2]); Console.WriteLine("\nVänligen skriv titeln på det inlägg du vill ta bort"); string title = Console.ReadLine(); if (title == entry[0]) { blogEntry.RemoveAt(entry); } Console.Clear(); }

entry som jag ska tar bort? eller är det post? Som jag förstår det står är ju blogEntry hela listan och för att ta bort i listan måste jag ju använda mig av RemoveAt. Frågan är vad indexet är jag ska ta bort heter? för det blir ju hela vektorn?
Dum fråga kanske, men jag fattar ju inte hehe

Trädvy Permalänk
Medlem
Plats
Linköping
Registrerad
Jun 2007

@zcelador: RemoveAt tar ett index, så koden du visar där kompilerar inte eftersom entry är en lista med strängar. Om du vill ta bort ett element som har ett visst värde så kan du använda Remove istället, men det fungerar ju inte i det här fallet eftersom användaren då måste mata in exakt rätt titel, text samt datum för det inlägg den vill ta bort.

Om du ersätter RemoveAt med Remove i din kod ovan så skulle det fungera, men logiken du har är då:

för varje inlägg i listan: läs in en titel från användaren om titeln matchar inlägget vi är på just nu, ta bort inlägget

D.v.s. istället för att ta bort ett inlägg med en viss titel så låter du användaren gissa titeln på varje inlägg, och tar bort inläggen som användaren gissar rätt på.

Vad du istället bör göra är något liknande:

läs in en titel från användaren för varje inlägg i listan: om titeln på inlägget matchar titeln användaren skrev in: ta bort inlägget avsluta loopen

Du kan lösa detta genom att använda Remove, men problemet med det är att Remove måste söka igenom listan och jämföra värdet du angivit med varje element tills den hittar rätt element. D.v.s. samma sak som du redan måste göra för att hitta rätt inlägg, fast mindre effektivt eftersom Remove måste kontrollera att hela inlägget matchar. Ett mycket effektivare sätt att lösa det på är att hålla reda på vilket index du är på i listan, och istället använda RemoveAt när du väl hittar rätt inlägg.

Trädvy Permalänk
Medlem
Registrerad
Nov 2019

@perost:
Menar du såhär?

Console.WriteLine("\nVänligen skriv titeln på det inlägg du vill ta bort"); int title; //här är användarens svar en int som jag döper till title. bool type = int.TryParse(Console.ReadLine(), out title); if (type) // { if (title >= 0 && title < blogEntry.Count) { blogEntry.RemoveAt(title); // ta bort det inlägget Console.Clear(); } } else Console.WriteLine("Du måste skriva in rätt titel"); // annars skriv ut detta Console.ReadLine(); Console.Clear();

Känns som att jag inte riktigt vet vad det är jag ska ta bort för index.

Trädvy Permalänk
Medlem
Plats
Linköping
Registrerad
Jun 2007
Skrivet av zcelador:

Menar du såhär?

Nej, nu har du samma problem med att utskriften säger en sak medan koden gör något helt annat.

Skrivet av zcelador:

Känns som att jag inte riktigt vet vad det är jag ska ta bort för index.

Säg att jag ger dig en lista med strängar:
{"äpple", "päron", "banan", "kiwi", "melon", "ananas", "mango", "apelsin", "aprikos"}

Om jag sen frågar dig vilken plats i listan mango finns på, hur skulle du ta reda på det? Inte i kod alltså, utan bara hur du personligen skulle ta reda på det. Detta är samma problem du behöver lösa, med skillnaden att istället för en lista med strängar så har du en lista med "inlägg".