Programmering 2 Omvandling av strängar

Permalänk
Medlem

Du sparar aldrig boken som skapas i SkapaNyBok() till din lista.

Vad du behöver är något i stil med bokLista.Add(a) i vardera case-sats.

Därtill behöver du definiera bokLista globalt så att du kommer åt den från SkapaNyBok().

Edit: Med reservation för att jag kan ha missat något när jag läste din kod på mobilen

Visa signatur

Modermodem från ONOFF och bildskärmsutrustning från Electrolux. US Robotics 28.8K telefonuppringd internetförbindelse. Har en förkärlek för tysk tjejpop.

Permalänk

Gjort, men jag förstår inte hur jag ska definiera bokLista globalt.

Permalänk
Medlem
Skrivet av Field_trip:

Gjort, men jag förstår inte hur jag ska definiera bokLista globalt.

Som en static-variabel i Bokhyllan-klassen.

Men globala variabler är något man generellt bör undvika, även om de är vanliga i den här typen av nybörjaruppgifter. De är enkla att använda i små uppgifter eftersom de går att komma åt överallt, men blir snabbt en mardröm i lite större program just för att de går att komma åt överallt (d.v.s. man har ingen koll på var de ändras).

En snyggare lösning som är mer lik vad man skulle göra i "riktig" kod är att bara skicka med listan med böcker till dina funktioner som behöver den, d.v.s. låt SkapaNyBok ta listan med böcker som argument. Då kan du t.ex. ha flera olika samlingar med böcker utan problem, vilket blir krångligt om du använder en global bok-lista.

En ännu snyggare lösning är att skriva en klass som representerar en samling böcker, istället för att bara ha en lista som du måste hantera manuellt överallt.

Permalänk
Skrivet av perost:

Som en static-variabel i Bokhyllan-klassen.

Men globala variabler är något man generellt bör undvika, även om de är vanliga i den här typen av nybörjaruppgifter. De är enkla att använda i små uppgifter eftersom de går att komma åt överallt, men blir snabbt en mardröm i lite större program just för att de går att komma åt överallt (d.v.s. man har ingen koll på var de ändras).

En snyggare lösning som är mer lik vad man skulle göra i "riktig" kod är att bara skicka med listan med böcker till dina funktioner som behöver den, d.v.s. låt SkapaNyBok ta listan med böcker som argument. Då kan du t.ex. ha flera olika samlingar med böcker utan problem, vilket blir krångligt om du använder en global bok-lista.

En ännu snyggare lösning är att skriva en klass som representerar en samling böcker, istället för att bara ha en lista som du måste hantera manuellt överallt.

Äntligen, det löste sig nu.

Och nu till ett annat problem, det sista (tack och lov), mina böcker skrivs över när jag skapar en ny bok, jag har inte listat ut det än.

Permalänk
Skrivet av HappySatan:

Du sparar aldrig boken som skapas i SkapaNyBok() till din lista.

Vad du behöver är något i stil med bokLista.Add(a) i vardera case-sats.

Därtill behöver du definiera bokLista globalt så att du kommer åt den från SkapaNyBok().

Edit: Med reservation för att jag kan ha missat något när jag läste din kod på mobilen

bool minBool = true; // minbool är sann while (minBool) // så länge min bool är sann { // skriver ut menyn för typ av bok Console.Write("\n\tÄr boken en [1] Roman, [2] Tidskrift eller [3] Novellsamling?\n\t"); if (int.TryParse(Console.ReadLine(), out int Bokval)) // sifferinmatning för vår switch { switch (Bokval) { case 1: { Bok a = new Roman(Titel, Skribent, Utgivningsår); bokLista.Add(a); Console.Write("\n\tSparat!\n\t"); break; } case 2: { Bok a = new Tidskrift(Titel, Skribent, Utgivningsår); bokLista.Add(a); Console.Write("\n\tSparat!\n\t"); break; } case 3: { Bok a = new Novellsamling(Titel, Skribent, Utgivningsår); bokLista.Add(a); Console.Write("\n\tSparat!\n\t"); break; } default: { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("\n\tOgiltigt val!"); Console.ResetColor(); break; } } minBool = false; // loopen avslutas }

När jag skapar en ny bok så skrivs den ursprungliga boken över, undrar varför. Hur ser koden ut?

Permalänk
Medlem

Det fungerar som det skall, problemet är att när du skriver ut böckerna så clearar du consolen efter att varje bok skrivits ut vilket gör att endast den senaste boken visas. Sådana här fel är lätta att hitta om du ser till att kontrollera att det du tror händer(att böckerna skrivs över) är det som faktiskt händer(utskrifterna clearas i foreach loopen). Antingen via debugger eller en enkel print av liststorlek etc. vid passande ställe i koden, så skulle det snabbt gett en bra ledtråd till var felet kan ligga.

Skrivet av Field_trip:

bool minBool = true; // minbool är sann while (minBool) // så länge min bool är sann { // skriver ut menyn för typ av bok Console.Write("\n\tÄr boken en [1] Roman, [2] Tidskrift eller [3] Novellsamling?\n\t"); if (int.TryParse(Console.ReadLine(), out int Bokval)) // sifferinmatning för vår switch { switch (Bokval) { case 1: { Bok a = new Roman(Titel, Skribent, Utgivningsår); bokLista.Add(a); Console.Write("\n\tSparat!\n\t"); break; } case 2: { Bok a = new Tidskrift(Titel, Skribent, Utgivningsår); bokLista.Add(a); Console.Write("\n\tSparat!\n\t"); break; } case 3: { Bok a = new Novellsamling(Titel, Skribent, Utgivningsår); bokLista.Add(a); Console.Write("\n\tSparat!\n\t"); break; } default: { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("\n\tOgiltigt val!"); Console.ResetColor(); break; } } minBool = false; // loopen avslutas }

När jag skapar en ny bok så skrivs den ursprungliga boken över, undrar varför. Hur ser koden ut?

Permalänk
Skrivet av Hot Dogs:

Det fungerar som det skall, problemet är att när du skriver ut böckerna så clearar du consolen efter att varje bok skrivits ut vilket gör att endast den senaste boken visas. Sådana här fel är lätta att hitta om du ser till att kontrollera att det du tror händer(att böckerna skrivs över) är det som faktiskt händer(utskrifterna clearas i foreach loopen). Antingen via debugger eller en enkel print av liststorlek etc. vid passande ställe i koden, så skulle det snabbt gett en bra ledtråd till var felet kan ligga.

Tog bara bort console clear från foreach loopen, tack!

Permalänk

Tipsmaskinen, programmering 2

Alltså kan någon vänlig själ hjälpa mig i rätt riktning?

Ska implementera dessa funktioner

"Följande krav finns på ditt program:

Programmet ska vara byggt med Windows forms. Det ska finnas en textruta som visar en slumpvald boks ToString-override och en knapp som genererar ett nytt boktips. Textrutan ska informera användaren om titel, författare/utgivare samt typ av bok.
Du ska bygga en importeringsklass. En klass som hanterar importering av data från en textfil till sträng. Symbolerna ### fungerar som en separator. Importera textraderna och spara dem som böcker. Du får inte ändra textfilen.
Importerade texter ska sparas som böcker, av rätt underklass, i en boklista. Du behöver inte använda Bibliotekarie-klassen.
Böckernas ToString-override ska kunna visa huruvida boktipset är tillgängligt eller inte. Varje bok i textfilen innehåller ett true/false-värde. Denna avgör om boken är tillgänglig eller inte.
Ditt program ska hantera eventuella fel vid inläsning av textfilen. Om textfilen inte hittas ska ditt program hantera det och meddela användaren om problemet.
Tipsknappen ska bara plocka fram en slumpvald bok som visas för användaren, den ska inte generera böckerna som slumpas fram. Böckerna bör genereras antingen med en separat knapp eller när programmet startar. Tipsknappen ska bara plocka fram ett tips.
"

Är jag på rätt väg? Är helt lost.

using System; using System.IO; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace Tipsmaskinen { public partial class Form1 : Form { public Random rnd; List<Bok> bokLista = new List<Bok>(); List<string[]> SträngLista = new List<string[]>(); public Form1() { InitializeComponent(); rnd = new Random(); } private void button1_Click_1(object sender, EventArgs e) { FileLoader(); } public void FileLoader() { if (File.Exists("texter.txt")) { List<string> itemSaver = new List<string>(); StreamReader reader = new StreamReader("texter.txt", Encoding.Default, false); string item = ""; while ((item = reader.ReadLine()) != null) { itemSaver.Add(item); } foreach (string a in itemSaver) { string[] vektor = a.Split(new string[] { "####" }, StringSplitOptions.None); } } } } public class Bok { public string titel; public string författare; public string typ; public string utgivare; public bool tillgänglig; public Bok(string titel, string författare, string utgivare, bool tillgänglig) { this.titel = titel; this.författare = författare; this.utgivare = utgivare; this.tillgänglig = tillgänglig; } public override string ToString() { if (tillgänglig) { return titel + " " + författare + " " + utgivare + " " + "tillgänglig"; } else { return titel + " " + författare + " " + utgivare + " " + "otillgänglig"; } } // Bokens underklasser; roman, tidskrit och novellsamling public class Roman : Bok { public Roman(string titel, string skribent, string utgivare, bool tillgänglig) : base(titel, skribent, utgivare, tillgänglig) { } } public class Tidskrift : Bok { public Tidskrift(string titel, string skribent, string utgivare, bool tillgänglig) : base(titel, skribent, utgivare, tillgänglig) { } } public class Novellsamling : Bok { public Novellsamling(string titel, string skribent, string utgivare, bool tillgänglig) : base(titel, skribent, utgivare, tillgänglig) { } } } }

Använder VS in windows 10

Permalänk
Medlem

Lite väl generell fråga kanske, du får gärna vara lite mer specifik med vad det är du undrar över. Men för att ge lite tips på vad du bör se över i uppgiften:

Citat:

Programmet ska vara byggt med Windows forms. Det ska finnas en textruta som visar en slumpvald boks ToString-override och en knapp som genererar ett nytt boktips. Textrutan ska informera användaren om titel, författare/utgivare samt typ av bok.
Du ska bygga en importeringsklass. En klass som hanterar importering av data från en textfil till sträng. Symbolerna ### fungerar som en separator. Importera textraderna och spara dem som böcker. Du får inte ändra textfilen.
Importerade texter ska sparas som böcker, av rätt underklass, i en boklista. Du behöver inte använda Bibliotekarie-klassen.
Böckernas ToString-override ska kunna visa huruvida boktipset är tillgängligt eller inte. Varje bok i textfilen innehåller ett true/false-värde. Denna avgör om boken är tillgänglig eller inte.
Ditt program ska hantera eventuella fel vid inläsning av textfilen. Om textfilen inte hittas ska ditt program hantera det och meddela användaren om problemet.
Tipsknappen ska bara plocka fram en slumpvald bok som visas för användaren, den ska inte generera böckerna som slumpas fram. Böckerna bör genereras antingen med en separat knapp eller när programmet startar. Tipsknappen ska bara plocka fram ett tips."

Det verkar förresten inte finnas mycket mening med din itemSaver-lista i BokLoader, du läser bara in varje rad i en lista och sen går du direkt igenom listan och konverterar strängarna till böcker. Du kan lika gärna konvertera raderna till böcker direkt istället för att mellanlagra dem i en lista.

Permalänk
Skrivet av Field_trip:

Alltså kan någon vänlig själ hjälpa mig i rätt riktning?

private void button1_Click_1(object sender, EventArgs e) { FileLoader(); }

Här läser du in filen varje gång någon trycker på knappen. Det är dumt; det tar längre tid att läsa en textfil än att slå upp något som redan finns lagrat i en variabel. Läs istället in filen en gång för alla när programmet startas.

Skrivet av Field_trip:

public void FileLoader() { if (File.Exists("texter.txt")) { List<string> itemSaver = new List<string>(); StreamReader reader = new StreamReader("texter.txt", Encoding.Default, false);

Här öppnar du filen texter.txt i arbetskatalogen. Vet du vilken katalog som är arbetskatalogen? Det är inte alltid samma katalog, särskilt inte om någon väljer att starta programmet från kommandoraden. Om filen texter.txt inte skulle råka ligga i arbetskatalogen utan i någon annan katalog hittar inte programmet filen och du har inte behandlat vad som ska ske i så fall. En enkel lösning skulle kunna vara att skriva in hela sökvägen till filen.

Sedan använder du Encoding.Default. Microsoft varnar:

Citat:

Different computers can use different encodings as the default, and the default encoding can change on a single computer. If you use the Default encoding to encode and decode data streamed between computers or retrieved at different times on the same computer, it may translate that data incorrectly. In addition, the encoding returned by the Default property uses best-fit fallback to map unsupported characters to characters supported by the code page. For these reasons, using the default encoding is not recommended. To ensure that encoded bytes are decoded properly, you should use a Unicode encoding, such as UTF8Encoding or UnicodeEncoding. You could also use a higher-level protocol to ensure that the same format is used for encoding and decoding.

Med andra ord kanske programmet funkar fint på din dator, men flyttar du programmet till en rysk eller kinesisk dator är Encoding.Default något annat. Eftersom du har en färdig fil som du ska använda är det bättre att ange vilken teckenkodning den använder istället för att förlita sig på att Encoding.Default skulle vara rätt.

Skrivet av Field_trip:

while ((item = reader.ReadLine()) != null) { itemSaver.Add(item); } foreach (string a in itemSaver) { string[] vektor = a.Split(new string[] { "####" }, StringSplitOptions.None); }

Ett tips är att använda item.Split istället för a.split. På så vis behöver du överhuvudtaget inte blanda in någon itemSaver utan kan helt stryka det från programmet. När du har bildat vektor behöver du använda det som finns lagrat i vektor för att skapa böcker, tidskrifter, romaner och novellsamligar som du adderar till din bokLista. Du kan också behöva kolla att boken inte redan lagts till i boklistan, särskilt om du tänkt köra FileLoader() flera gånger.

Permalänk

Min lärares kommentar:
- Böckerna ges aldrig en bool när de skapas, så de kan inte skapas. Det behövs tre strängar och en bool.
Jag har ju 3 strängar och en bool, vad menar han med detta?

- Tipsknappen ska bara ge oss ett tips, det ska inte ladda in hela boklistan varje gång vi trycker på den. Listan med böcker bör bara laddas in en gång när programmet startar, inte varje gång vi trycker på tipsknappen. Tipsknappen bör bara ge oss en slumpvald bok.

Så här ser min kod ut nu.

using System; using System.IO; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace Tipsmaskinen { public partial class Form1 : Form { List<Bok> bokLista = new List<Bok>(); List<string[]> strängLista = new List<string[]>(); public Form1() { InitializeComponent(); FileLoader(); } private void button1_Click_1(object sender, EventArgs e) { Bok SlumpaBok = bokLista.SlumpaBok(); <-- här kommer jag inte längre } public void FileLoader() { if (File.Exists(@C:\Användare\MittNamn\Hämtade filer\texter.txt)) { List<string> itemSaver = new List<string>(); StreamReader reader = new StreamReader(@C:\Användare\MittNamn\Hämtade filer\texter.txt, Encoding.Default, false); string item = ""; while ((item = reader.ReadLine()) != null) { itemSaver.Add(item); } reader.Close(); foreach (string a in itemSaver) { string[] vektor = a.Split(new string[] { "####" }, StringSplitOptions.None); strängLista.Add(vektor); switch (vektor[2]) { case "1": bokLista.Add(new Roman(vektor[0], vektor[1], vektor[2]));<-- CS7036 C# There is no argument given that corresponds to the required formal parameter "tillgänglig" of Form1.Roman.Roman(string, string, string, bool) break; case "2": bokLista.Add(new Tidskrift(vektor[0], vektor[1], vektor[2])); <-- CS7036 C# There is no argument given that corresponds to the required formal parameter "tillgänglig" of Form1.Tidskrift.Tidskrift(string, string, string, bool) break; case "3": bokLista.Add(new Novellsamling(vektor[0], vektor[1], vektor[2])); <-- CS7036 C# There is no argument given that corresponds to the required formal parameter "tillgänglig" of Form1.Novellsamling.Novellsamling(string, string, string, bool) break; default: break; } } } } private void button2_Click(object sender, EventArgs e) { this.Close(); } private void textBox1_TextChanged(object sender, EventArgs e) { } public class Bok { public string titel; public string författare; public string typ; public string utgivare; public bool tillgänglig; public Bok(string titel, string författare, string utgivare, bool tillgänglig) { this.titel = titel; this.författare = författare; this.utgivare = utgivare; this.tillgänglig = tillgänglig; } } // Bokens underklasser; roman, tidskrit och novellsamling public class Roman : Bok { public Roman(string titel, string författare, string utgivare, bool tillgänglig) : base(titel, författare, utgivare, tillgänglig) { typ = "Roman"; } public override string ToString() { if (tillgänglig) { return "tillgänglig"; } else { return "otillgänglig"; } } } public class Tidskrift : Bok { public Tidskrift(string titel, string författare, string utgivare, bool tillgänglig) : base(titel, författare, utgivare, tillgänglig) { typ = "Tidskrift"; } public override string ToString() { if (tillgänglig) { return "tillgänglig"; } else { return "otillgänglig"; } } } public class Novellsamling : Bok { public Novellsamling(string titel, string författare, string utgivare, bool tillgänglig) : base(titel, författare, utgivare, tillgänglig) { typ = "Novellsamling"; } public override string ToString() { if (tillgänglig) { return "tillgänglig"; } else { return "otillgänglig"; } } } } }

Hjälp uppskattas.

Permalänk
Medlem
Skrivet av Field_trip:

Min lärares kommentar:
- Böckerna ges aldrig en bool när de skapas, så de kan inte skapas. Det behövs tre strängar och en bool.
Jag har ju 3 strängar och en bool, vad menar han med detta?

- Tipsknappen ska bara ge oss ett tips, det ska inte ladda in hela boklistan varje gång vi trycker på den. Listan med böcker bör bara laddas in en gång när programmet startar, inte varje gång vi trycker på tipsknappen. Tipsknappen bör bara ge oss en slumpvald bok.

Så här ser min kod ut nu.

using System; using System.IO; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace Tipsmaskinen { public partial class Form1 : Form { List<Bok> bokLista = new List<Bok>(); List<string[]> strängLista = new List<string[]>(); public Form1() { InitializeComponent(); FileLoader(); } private void button1_Click_1(object sender, EventArgs e) { Bok SlumpaBok = bokLista.SlumpaBok(); <-- här kommer jag inte längre } public void FileLoader() { if (File.Exists(@C:\Användare\MittNamn\Hämtade filer\texter.txt)) { List<string> itemSaver = new List<string>(); StreamReader reader = new StreamReader(@C:\Användare\MittNamn\Hämtade filer\texter.txt, Encoding.Default, false); string item = ""; while ((item = reader.ReadLine()) != null) { itemSaver.Add(item); } reader.Close(); foreach (string a in itemSaver) { string[] vektor = a.Split(new string[] { "####" }, StringSplitOptions.None); strängLista.Add(vektor); switch (vektor[2]) { case "1": bokLista.Add(new Roman(vektor[0], vektor[1], vektor[2]));<-- CS7036 C# There is no argument given that corresponds to the required formal parameter "tillgänglig" of Form1.Roman.Roman(string, string, string, bool) break; case "2": bokLista.Add(new Tidskrift(vektor[0], vektor[1], vektor[2])); <-- CS7036 C# There is no argument given that corresponds to the required formal parameter "tillgänglig" of Form1.Tidskrift.Tidskrift(string, string, string, bool) break; case "3": bokLista.Add(new Novellsamling(vektor[0], vektor[1], vektor[2])); <-- CS7036 C# There is no argument given that corresponds to the required formal parameter "tillgänglig" of Form1.Novellsamling.Novellsamling(string, string, string, bool) break; default: break; } } } } private void button2_Click(object sender, EventArgs e) { this.Close(); } private void textBox1_TextChanged(object sender, EventArgs e) { } public class Bok { public string titel; public string författare; public string typ; public string utgivare; public bool tillgänglig; public Bok(string titel, string författare, string utgivare, bool tillgänglig) { this.titel = titel; this.författare = författare; this.utgivare = utgivare; this.tillgänglig = tillgänglig; } } // Bokens underklasser; roman, tidskrit och novellsamling public class Roman : Bok { public Roman(string titel, string författare, string utgivare, bool tillgänglig) : base(titel, författare, utgivare, tillgänglig) { typ = "Roman"; } public override string ToString() { if (tillgänglig) { return "tillgänglig"; } else { return "otillgänglig"; } } } public class Tidskrift : Bok { public Tidskrift(string titel, string författare, string utgivare, bool tillgänglig) : base(titel, författare, utgivare, tillgänglig) { typ = "Tidskrift"; } public override string ToString() { if (tillgänglig) { return "tillgänglig"; } else { return "otillgänglig"; } } } public class Novellsamling : Bok { public Novellsamling(string titel, string författare, string utgivare, bool tillgänglig) : base(titel, författare, utgivare, tillgänglig) { typ = "Novellsamling"; } public override string ToString() { if (tillgänglig) { return "tillgänglig"; } else { return "otillgänglig"; } } } } }

Hjälp uppskattas.

Du skickar inte in någon bool när du skapar upp böckerna, därav felmeddelandet.

SlumpaBok är ingen metod som existerar för klassen List, så du kan inte göra ett anrop på det viset. Gör en ny metod likt FileLoader som slumpar fram en bok ur din lista.

Visa signatur

AMD Ryzen 7 1700X 3.8 GHz 20MB | ASUS PRIME X370-PRO | MSI GeForce GTX 1080 Gaming X 8GB | G.Skill 16GB DDR4 3200 MHz CL14 Flare X | Corsair RM650x 650W

Permalänk

Okej, är jag på rätt väg nu?

using System; using System.IO; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace Tipsmaskinen { public partial class Form1 : Form { List<Bok> bokLista = new List<Bok>(); public Form1() { InitializeComponent(); FileLoader(); } private void button1_Click_1(object sender, EventArgs e) { Random random = new Random(); string objekt = bokLista[random.Next(bokLista.Count)].ToString(); textBox1.Text = Convert.ToString(objekt); } public void FileLoader() { if (File.Exists("texter.txt")) { List<string> itemSaver = new List<string>(); StreamReader reader = new StreamReader("texter.txt", Encoding.Default, false); string item = ""; while ((item = reader.ReadLine()) != null) { itemSaver.Add(item); } reader.Close(); foreach (string a in itemSaver) { string[] vektor = a.Split(new string[] { "####" }, StringSplitOptions.None); string titel = vektor[0]; string författare = vektor[1]; string typ = vektor[2]; string utgivare = vektor[3]; bool tillgänglig = Convert.ToBoolean(vektor[3]); switch (typ) { case "1": bokLista.Add(new Roman(titel, författare, utgivare, tillgänglig)); break; case "2": bokLista.Add(new Tidskrift(titel, författare, utgivare, tillgänglig)); break; case "3": bokLista.Add(new Novellsamling(titel, författare, utgivare, tillgänglig)); break; default: break; } } } else { Console.WriteLine("Filen hittades inte."); } } private void button2_Click(object sender, EventArgs e) { this.Close(); } private void textBox1_TextChanged(object sender, EventArgs e) { textBox1.Text = ""; } public class Bok { public string titel; public string författare; public string typ; public string utgivare; public bool tillgänglig; public Bok(string titel, string författare, string utgivare, bool tillgänglig) { this.titel = titel; this.författare = författare; this.utgivare = utgivare; this.tillgänglig = tillgänglig; } } // Bokens underklasser; roman, tidskrit och novellsamling public class Roman : Bok { public Roman(string titel, string författare, string utgivare, bool tillgänglig) : base(titel, författare, utgivare, tillgänglig) { typ = "Roman"; } public override string ToString() { if (tillgänglig) { return "tillgänglig"; } else { return "otillgänglig"; } } } public class Tidskrift : Bok { public Tidskrift(string titel, string författare, string utgivare, bool tillgänglig) : base(titel, författare, utgivare, tillgänglig) { typ = "Tidskrift"; } public override string ToString() { if (tillgänglig) { return "tillgänglig"; } else { return "otillgänglig"; } } } public class Novellsamling : Bok { public Novellsamling(string titel, string författare, string utgivare, bool tillgänglig) : base(titel, författare, utgivare, tillgänglig) { typ = "Novellsamling"; } public override string ToString() { if (tillgänglig) { return "tillgänglig"; } else { return "otillgänglig"; } } } } }

Permalänk

När jag skrev nedanstående, hade jag inte ännu sett Field_trips inlägg från kl. 14:43. Jag refererar alltså endast till inlägget från kl. 12:58.

Skrivet av Field_trip:

Min lärares kommentar:
- Böckerna ges aldrig en bool när de skapas, så de kan inte skapas. Det behövs tre strängar och en bool.
Jag har ju 3 strängar och en bool, vad menar han med detta?

Titta på dessa rader i koden:

bokLista.Add(new Roman(vektor[0], vektor[1], vektor[2]));<-- CS7036 C# There is no argument given that corresponds to the required formal parameter "tillgänglig" of Form1.Roman.Roman(string, string, string, bool) bokLista.Add(new Tidskrift(vektor[0], vektor[1], vektor[2])); <-- CS7036 C# There is no argument given that corresponds to the required formal parameter "tillgänglig" of Form1.Tidskrift.Tidskrift(string, string, string, bool) bokLista.Add(new Novellsamling(vektor[0], vektor[1], vektor[2])); <-- CS7036 C# There is no argument given that corresponds to the required formal parameter "tillgänglig" of Form1.Novellsamling.Novellsamling(string, string, string, bool)

Gå sedan ner till public class Roman : Bok (m.fl.) och se hur de initieras. De ska ha tre strängar och en bool, men du stoppar bara in tre strängar. Jag antar att det framgår någonstans i vektor om din bool ska vara sann eller falsk. Tänk på att vektor bara innehåller strängar, så du måste omvandla till bool först.

En sak till:

switch (vektor[2])

Här kollar du om vektor[2] är 1, 2 eller 3 för att avgöra om det är en roman, tidskrift eller novellsamling. På de tre första raderna jag citerade anser du att vektor[2] istället innehåller namnet på romanens, tidskriftens eller novellsamlingens utgivare. Du verkar ha angivit fel index i vektor på endera stället.

Skrivet av Field_trip:

- Tipsknappen ska bara ge oss ett tips, det ska inte ladda in hela boklistan varje gång vi trycker på den. Listan med böcker bör bara laddas in en gång när programmet startar, inte varje gång vi trycker på tipsknappen. Tipsknappen bör bara ge oss en slumpvald bok.

Textfilen lästes varje gång du klickade på knappen i koden från i onsdags. I dagens kod läses textfilen bara en gång, så den delen verkar ha åtgärdats.

private void button1_Click_1(object sender, EventArgs e) { Bok SlumpaBok = bokLista.SlumpaBok(); <-- här kommer jag inte längre }

Böckerna finns redan inlagda i din bokLista. Du behöver alltså skriva kod som gör att en slumpmässig bok väljs ut i boklistan. Sedan kollar du vad detta är för bok och skriver ut uppgifterna om boken på skärmen.

---

Snabb kommentar om inlägget från kl. 14:43:

string utgivare = vektor[3]; bool tillgänglig = Convert.ToBoolean(vektor[3]);

På första raden innehåller vektor[3] information om bokens utgivare. På andra raden är vektor[3] istället en bool. Kolla indexvärdena.

Permalänk
Medlem
Skrivet av Field_trip:

Okej, är jag på rätt väg nu?

Ja, det är ett steg i rätt riktning i alla fall. Lite småsaker:

  • I din button1_Click_1-metod så konverterar du objekt till en sträng, men objekt är ju redan en sträng. Fundera gärna lite på om objekt är ett bra variabelnamn också

  • Jag ser fortfarande inte vad poängen med itemSaver-listan i FileLoader är, det gör bara koden onödigt komplicerad jämfört med att bara gå igenom filen direkt istället för att mellanlagra den i en lista.

  • Dina ToString-metoder i böckerna skriver just nu bara ut "tillgänglig" eller "otillgänglig", men ingen annan av den efterfrågade informationen.

Ett litet tips: C# har en ?: operator som returnerar ett av två värden beroende på ett villkor. Så istället för:

if (tillgänglig) { return "tillgänglig"; } else { return "otillgänglig"; }

så kan du skriva:

return tillgänglig ? "tillgänglig" : "otillgänglig";

Permalänk

Hur ser det ut nu?

using System; using System.IO; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace Tipsmaskinen { public partial class Form1 : Form { List<Bok> bokLista = new List<Bok>(); public Form1() { InitializeComponent(); FileLoader(); } private void button1_Click_1(object sender, EventArgs e) { Random random = new Random(); //istället för objekt valde jag att sätta variabelnnamnet till bokLoader string bokLoader = bokLista[random.Next(bokLista.Count)].ToString(); } public void FileLoader() { if (File.Exists("texter.txt")) { List<string> itemSaver = new List<string>(); StreamReader reader = new StreamReader("texter.txt", Encoding.Default, false); foreach (string a in itemSaver) { string[] vektor = a.Split(new string[] { "####" }, StringSplitOptions.None); string titel = vektor[0]; string författare = vektor[1]; string typ = vektor[2]; string utgivare = vektor[3]; bool tillgänglig = Convert.ToBoolean(vektor[4]); switch (typ) { case "1": bokLista.Add(new Roman(titel, författare, utgivare, tillgänglig)); break; case "2": bokLista.Add(new Tidskrift(titel, författare, utgivare, tillgänglig)); break; case "3": bokLista.Add(new Novellsamling(titel, författare, utgivare, tillgänglig)); break; default: break; } } } else { Console.WriteLine("Filen hittades inte."); } } private void button2_Click(object sender, EventArgs e) { this.Close(); } private void textBox1_TextChanged(object sender, EventArgs e) { } } public class Bok { public string titel; public string författare; public string typ; public string utgivare; public bool tillgänglig; public Bok(string titel, string författare, string utgivare, bool tillgänglig) { this.titel = titel; this.författare = författare; this.utgivare = utgivare; this.tillgänglig = tillgänglig; } } // Bokens underklasser; roman, tidskrit och novellsamling public class Roman : Bok { public Roman(string titel, string författare, string utgivare, bool tillgänglig) : base(titel, författare, utgivare, tillgänglig) { typ = "Roman"; } public override string ToString() { return tillgänglig ? "tällgänglig" : "otillgänglig"; } } public class Tidskrift : Bok { public Tidskrift(string titel, string författare, string utgivare, bool tillgänglig) : base(titel, författare, utgivare, tillgänglig) { typ = "Tidskrift"; } public override string ToString() { { return tillgänglig ? "tällgänglig" : "otillgänglig"; } } } public class Novellsamling : Bok { public Novellsamling(string titel, string författare, string utgivare, bool tillgänglig) : base(titel, författare, utgivare, tillgänglig) { typ = "Novellsamling"; } public override string ToString() { { return tillgänglig ? "tällgänglig" : "otillgänglig"; } } } }

Jag har en kod till som inte vill ge sig nu, den här: string bokLoader = bokLista[random.Next(bokLista.Count)].ToString();

Felmeddelandet lyder så här: Index was out of range. Must be non-negative and less than the size of the collection. Vad menar den här?

Jag tänker så att när button1 trycks ned så ska bokloader öka med 1, så bokloader++; efter switch satsen?

Permalänk
Medlem

@Field_trip: Din kod för att läsa in böcker fungerar inte nu, så bokLista.Count kommer alltid vara 0. Så ditt försök att slumpa fram en bok ger ett fel eftersom inget index du kan ge kommer vara giltigt för en tom lista.

Som jag skrev tidigare så är itemSaver-listan onödig, men av någon anledning så tog du bort själva inläsningen istället för den variabeln. Du kan läsa in böckerna med en likadan loop som du hade tidigare:

while ((item = reader.ReadLine()) != null) { // Skapa bok och lägg till i bok-listan }

Permalänk

Oj, råka ta bort hela istället för itemSaver.add

Nu har jag gjort så här

string item = ""; while ((item = reader.ReadLine()) != null) { Bok nyBok = new Bok; bokLista.Add(nyBok); } reader.Close();

Men new Bok; får detta felmeddelandet: A new expression requires (), [], or {} after type. Jag skrev det en hakparentes och det gick men jag antar att jag ska skriva in index nu? Felmeddelandet lyder; Array creation must have array size or array initializer

Permalänk
Medlem

@Field_trip: Du kan inte bara göra new Bok, du måste ju anropa konstruktorn korrekt. Men varför försöker du skriva om koden för att skapa böcker, du har ju redan kod för det?

Permalänk
Skrivet av perost:

@Field_trip: Din kod för att läsa in böcker fungerar inte nu, så bokLista.Count kommer alltid vara 0. Så ditt försök att slumpa fram en bok ger ett fel eftersom inget index du kan ge kommer vara giltigt för en tom lista.

Som jag skrev tidigare så är itemSaver-listan onödig, men av någon anledning så tog du bort själva inläsningen istället för den variabeln. Du kan läsa in böckerna med en likadan loop som du hade tidigare:

while ((item = reader.ReadLine()) != null) { // Skapa bok och lägg till i bok-listan }

Var det inte det du skrev?

För väl försöka imorgon igen, tack

Permalänk
Medlem
Skrivet av Field_trip:

Var det inte det du skrev?

För väl försöka imorgon igen, tack

Nej, jag skrev att du skulle sluta mellanlagra strängarna i en onödig lista och istället använda dem direkt för att skapa böcker. D.v.s. istället för som du har nu:

för varje rad i filen: lägg till raden i itemSaver för varje sträng i itemSaver: skapa en bok och lägg till den i bokLista

så kan du göra:

för varje rad i filen: skapa en bok och lägg till den i bokLista

Permalänk
Skrivet av Field_trip:

else { Console.WriteLine("Filen hittades inte."); }

Om du använder Console.WriteLine skrivs texten till standardutdataströmmen. Här bör man titta på vad detta innebär.

Om du skapar en konsolapplikation skrivs texten ut på skärmen (om du inte omdirigerar standardutdataströmmen någonstans). Om du inte startar programmet från kommandoraden tvingas det dessutom fram ett fönster där text kan skrivas ut.

Det här är dock ett Windows Forms-program. I Windows Forms-program skrivs texten inte ut på skärmen. För att se texten tvingades jag starta programmet från kommandoraden genom att skriva Tipsmaskinen.exe | more d.v.s. starta programmet och skicka vidare standardutdataströmmen till kommandot more som i sin tur skriver ut texten på skärmen.

Det är alltså i många fall dumt att använda Console.WriteLine i ett Windows Forms-program. Jag föreslår att du bekantar dig med MessageBox.Show istället.

Permalänk
Skrivet av Kommenterande 2:

Om du använder Console.WriteLine skrivs texten till standardutdataströmmen. Här bör man titta på vad detta innebär.

Om du skapar en konsolapplikation skrivs texten ut på skärmen (om du inte omdirigerar standardutdataströmmen någonstans). Om du inte startar programmet från kommandoraden tvingas det dessutom fram ett fönster där text kan skrivas ut.

Det här är dock ett Windows Forms-program. I Windows Forms-program skrivs texten inte ut på skärmen. För att se texten tvingades jag starta programmet från kommandoraden genom att skriva Tipsmaskinen.exe | more d.v.s. starta programmet och skicka vidare standardutdataströmmen till kommandot more som i sin tur skriver ut texten på skärmen.

Det är alltså i många fall dumt att använda Console.WriteLine i ett Windows Forms-program. Jag föreslår att du bekantar dig med MessageBox.Show istället.

Tack

Permalänk
Skrivet av perost:

Nej, jag skrev att du skulle sluta mellanlagra strängarna i en onödig lista och istället använda dem direkt för att skapa böcker. D.v.s. istället för som du har nu:

för varje rad i filen: lägg till raden i itemSaver för varje sträng i itemSaver: skapa en bok och lägg till den i bokLista

så kan du göra:

för varje rad i filen: skapa en bok och lägg till den i bokLista

Tog bort itemSaver.Add

Det sitter still, kommer inte vidare men är det så här du menar?

public partial class Form1 : Form { List<Bok> bokLista = new List<Bok>(); List<string[]> vectorList = new List<string[]>(); public Form1() { InitializeComponent(); FileLoader(); // Anropar metoden för att läsa in vår textfil } private void button1_Click_1(object sender, EventArgs e) { Random random = new Random(); bokLista[random.Next(bokLista.Count)].ToString(); } public void FileLoader() { bokLista = new List<Bok>(); if (File.Exists("texter.txt")) { var itemSaver = new List<string>(); StreamReader reader = new StreamReader("texter.txt", Encoding.Default, false); foreach (string a in itemSaver) { string item = ""; while ((item = reader.ReadLine()) != null) { string[] vektor = a.Split(new string[] { "####" }, StringSplitOptions.None); vectorList.Add(vektor); string titel = vektor[0]; string författare = vektor[1]; string typ = vektor[2]; string utgivare = vektor[3]; bool tillgänglig = Convert.ToBoolean(vektor[4]); switch (typ) { case "1": bokLista.Add(new Roman(titel, författare, utgivare, tillgänglig)); break; case "2": bokLista.Add(new Tidskrift(titel, författare, utgivare, tillgänglig)); break; case "3": bokLista.Add(new Novellsamling(titel, författare, utgivare, tillgänglig)); break; default: break; } Console.ReadLine(); } } } else { MessageBox.Show("Filen hittades tyvärr inte."); } }

Permalänk
Medlem
Skrivet av Field_trip:

Tog bort itemSaver.Add

Det sitter still, kommer inte vidare men är det så här du menar?

public partial class Form1 : Form { List<Bok> bokLista = new List<Bok>(); List<string[]> vectorList = new List<string[]>(); public Form1() { InitializeComponent(); FileLoader(); // Anropar metoden för att läsa in vår textfil } private void button1_Click_1(object sender, EventArgs e) { Random random = new Random(); bokLista[random.Next(bokLista.Count)].ToString(); } public void FileLoader() { bokLista = new List<Bok>(); if (File.Exists("texter.txt")) { var itemSaver = new List<string>(); StreamReader reader = new StreamReader("texter.txt", Encoding.Default, false); foreach (string a in itemSaver) { string item = ""; while ((item = reader.ReadLine()) != null) { string[] vektor = a.Split(new string[] { "####" }, StringSplitOptions.None); vectorList.Add(vektor); string titel = vektor[0]; string författare = vektor[1]; string typ = vektor[2]; string utgivare = vektor[3]; bool tillgänglig = Convert.ToBoolean(vektor[4]); switch (typ) { case "1": bokLista.Add(new Roman(titel, författare, utgivare, tillgänglig)); break; case "2": bokLista.Add(new Tidskrift(titel, författare, utgivare, tillgänglig)); break; case "3": bokLista.Add(new Novellsamling(titel, författare, utgivare, tillgänglig)); break; default: break; } Console.ReadLine(); } } } else { MessageBox.Show("Filen hittades tyvärr inte."); } }

Du använder fortfarande itemSaver i din loop. Kolla igenom din kod noga och ta bort det överallt, fundera sedan över vad det är du faktiskt vill göra.

Det finns absolut ingen anledning att mellanlagra någon information mellan inläsning från fil till skapande av Bok.
Du har kommit ett steg på vägen genom att ta bort itemSaver.Add, men just nu loopar du över en tom lista.

Sedan undrar jag också vad din Console.ReadLine() är tänkt att åstadkomma?

Visa signatur

AMD Ryzen 7 1700X 3.8 GHz 20MB | ASUS PRIME X370-PRO | MSI GeForce GTX 1080 Gaming X 8GB | G.Skill 16GB DDR4 3200 MHz CL14 Flare X | Corsair RM650x 650W

Permalänk
Skrivet av noMad17:

Du använder fortfarande itemSaver i din loop. Kolla igenom din kod noga och ta bort det överallt, fundera sedan över vad det är du faktiskt vill göra.

Det finns absolut ingen anledning att mellanlagra någon information mellan inläsning från fil till skapande av Bok.
Du har kommit ett steg på vägen genom att ta bort itemSaver.Add, men just nu loopar du över en tom lista.

Sedan undrar jag också vad din Console.ReadLine() är tänkt att åstadkomma?

Har vant mig med att använda readline för att stanna upp program i konsolapplikationer.

Okej, har kollat igenom koden igen och tog bort alla rader som innefatta itemSaver, sedan såg jag en kommentar från dig som jag tror jag hade hoppat över eler inte såg, jag har skrivit item.Split.

public void FileLoader() { if (File.Exists("texter.txt")) { StreamReader reader = new StreamReader("texter.txt", Encoding.Default, false); string item = ""; while ((item = reader.ReadLine()) != null) { string[] vektor = item.Split(new string[] { "####" }, StringSplitOptions.None); vectorList.Add(vektor); string titel = vektor[0]; string författare = vektor[1]; string typ = vektor[2]; string utgivare = vektor[3]; bool tillgänglig = Convert.ToBoolean(vektor[4]); switch (typ) { case "1": bokLista.Add(new Roman(titel, författare, utgivare, tillgänglig)); break; case "2": bokLista.Add(new Tidskrift(titel, författare, utgivare, tillgänglig)); break; case "3": bokLista.Add(new Novellsamling(titel, författare, utgivare, tillgänglig)); break; default: break; } } } else { MessageBox.Show("Filen hittades tyvärr inte."); } }

Så här ser den ut nu, går det åt rätt håll?

Hur kan jag göra nu för att faktiskt lägga in böcker i bokLista.Count?

Permalänk
Medlem
Skrivet av Field_trip:

Har vant mig med att använda readline för att stanna upp program i konsolapplikationer.

Okej, har kollat igenom koden igen och tog bort alla rader som innefatta itemSaver, sedan såg jag en kommentar från dig som jag tror jag hade hoppat över eler inte såg, jag har skrivit item.Split.

public void FileLoader() { if (File.Exists("texter.txt")) { StreamReader reader = new StreamReader("texter.txt", Encoding.Default, false); string item = ""; while ((item = reader.ReadLine()) != null) { string[] vektor = item.Split(new string[] { "####" }, StringSplitOptions.None); vectorList.Add(vektor); string titel = vektor[0]; string författare = vektor[1]; string typ = vektor[2]; string utgivare = vektor[3]; bool tillgänglig = Convert.ToBoolean(vektor[4]); switch (typ) { case "1": bokLista.Add(new Roman(titel, författare, utgivare, tillgänglig)); break; case "2": bokLista.Add(new Tidskrift(titel, författare, utgivare, tillgänglig)); break; case "3": bokLista.Add(new Novellsamling(titel, författare, utgivare, tillgänglig)); break; default: break; } } } else { MessageBox.Show("Filen hittades tyvärr inte."); } }

Så här ser den ut nu, går det åt rätt håll?

Hur kan jag göra nu för att faktiskt lägga in böcker i bokLista.Count?

Nu ser det bättre ut, ja.

Du kan även ta bort vectorList då det enda du använder den till är att mellanlagra resultatet av din item.Split, vilket även detta är helt onödigt.

bokLista.Count är endast ett fält som talar om hur många element din lista innehåller, själva tilläggandet gör du ju redan i din switch genom t.ex. bokLista.Add()

Visa signatur

AMD Ryzen 7 1700X 3.8 GHz 20MB | ASUS PRIME X370-PRO | MSI GeForce GTX 1080 Gaming X 8GB | G.Skill 16GB DDR4 3200 MHz CL14 Flare X | Corsair RM650x 650W

Permalänk

Okej, tog bort det.

Det är fortfarande ett problem, böckerna läggs fortfarande inte till, jag får ett IndexOtOfRange felmeddelande här:

private void button1_Click_1(object sender, EventArgs e) { Random random = new Random(); bokLista[random.Next(bokLista.Count)].ToString(); <-- 'Index was out of range. Must be non-negative and less than the size of the collection }

Något fattas men jag kan inte klura ut det. Det läggs inte till böcker trots att jag har bokLista.Add inom min switch.

Permalänk
Medlem
Skrivet av Field_trip:

Okej, tog bort det.

Det är fortfarande ett problem, böckerna läggs fortfarande inte till, jag får ett IndexOtOfRange felmeddelande här:

private void button1_Click_1(object sender, EventArgs e) { Random random = new Random(); bokLista[random.Next(bokLista.Count)].ToString(); <-- 'Index was out of range. Must be non-negative and less than the size of the collection }

Något fattas men jag kan inte klura ut det

Säkerställ att koden som läser böcker från filen faktiskt körs (d.v.s. sätt en breakpoint någonstans i kodblocket och kör programmet i debug-läge).

En annan sak att ha i åtanke är att listor är 0-indexerade, d.v.s. första indexet är 0.
List.Count talar om hur många element listan innehåller, men detta värde kommer alltid att vara 1 större än det högsta indexet.

T.ex:
Du har en lista som innehåller fyra element. Dess index är då 0, 1, 2, 3 medan Count kommer att ge 4 som svar.
När du försöker komma åt ett element i listan på följande vis:
bokLista[bokLista.Count]
kommer du att få ett IndexOutOfRange eftersom det inte finns något index 4.

Kolla på argumentet i random.Next och se om du ser något som skulle kunna bli tokigt.

Ett ord
Visa signatur

AMD Ryzen 7 1700X 3.8 GHz 20MB | ASUS PRIME X370-PRO | MSI GeForce GTX 1080 Gaming X 8GB | G.Skill 16GB DDR4 3200 MHz CL14 Flare X | Corsair RM650x 650W

Permalänk
Medlem
Skrivet av noMad17:

Kolla på argumentet i random.Next och se om du ser något som skulle kunna bli tokigt.

Random.Next returnerar ett slumptal som är större eller lika med 0 samt mindre än argumentet (eller 0 om argumentet är 0). Så just den biten är nog rätt så länge som listan inte är tom.

Men jo, debuggern är nog rätt väg att gå annars. Här är en kort guide för hur debuggern används.