Permalänk

Programmering C# hjälp

Jag har precis börjat läsa en kurs som heter grundläggande programmering och ska göra ett projekt där vi ska skapa ett register över fotbollsspelare och sedan lite funktioner till detta.

Jag är nästa klar men har fastnat med tre saker...
Första är en sökfunktion där jag vill att det ska räcka att söka på en bokstav för att en viss spelare ska komma upp. Nu måste man skriva in hela namnet på spelaren och stavar man inte rätt så kommer det inte upp någon spelare...
Koden jag använder ser ut såhär:

public static void FindSpelareByNamn() { Console.Write("Ange Namn: "); string searchPhrase = Console.ReadLine(); Spelarinfo foundSpelarinfo = GetSpelareByNamn(searchPhrase); if (foundSpelarinfo != null) { PrintSpelarinfo(foundSpelarinfo); } else { Console.WriteLine("Hittade ingen spelare med det namnet."); } } public static Spelarinfo GetSpelareByNamn(string namn) { Console.WriteLine("Namn" + "\t" + "Ålder" + "\t" + "Position" + "\t" + "Vikt" + "\t" + "Längd" + "\t" + "Nummer" + "\t"); for (int i = 0; i < spelare.Length; i++) { if (spelare[i].namn.Equals(namn)) { return spelare[i]; } } return null; }

Hade velat alltså att det ska gå att söka på enbart t.ex. Z så kommer Zlatan Ibrahimovic upp...

Det andra är att när jag sedan får upp mitt spelarregister så hamnar rubrikerna helt galet...
Ser ut såhär nu:

Namn Ålder Vikt Längd Position Nummer Zlatan Ibrahimovic 28 95 205 Forward 10

De hamnar liksom inte under rubrikerna...

Tack på förhand!

Permalänk
Medlem

Problemet ligger i spelare[i].namn.Equals(namn). Du behöver göra denna delen annorlunda.

Titta på de metoder som finns tillgängliga på ett sträng-objekt:

https://msdn.microsoft.com/en-us/library/system.string_method...

Permalänk
Medlem

String innehåller en extension metod du kan använda dig av som heter "contains". Den metoden söker genom strängen och letar efter en bokstav eller sträng som matchar det du matar in.

Se: https://msdn.microsoft.com/en-us/library/dy85x1sa(v=vs.110).a...

Kan även vara värt att bestämma om man vill jämföra stora och små bokstäver också. String.ToLower() kan användas för att jämföra strängar oavsett case.

Permalänk
Medlem

För formateringen så använder du ju ett tabspace mellan varje kolumn. Om data i ena kolumnen inte är lika långt som i nästa kolumn så blir det ju snett. Du får fundera ut ett sätt att formatera varje kolumn i konstant bredd.

Titta på metoden String.Format

Permalänk
Medlem

en enkel sak du kan göra är att använda contains funktionen for strängar. exempelvis.

spelare[i].namn.Contains(namn);

en ytterligare sak som kan vara trevligt är att inte bry dig om versaler. Ett sätt att göra detta är att helt enkelt konvertera båda strängarna till endast stora eller små boksätver.

spelare[i].namn.ToUpper().Contains(namn.ToUpper());

Visa signatur

| Ryzen 5800x | Asus prime x470 pro | Asus rtx 3080 tuf oc | Gskill 32gb 3,6ghz | aw3225qf |

Permalänk
Medlem
Skrivet av laht:

...
Kan även vara värt att bestämma om man vill jämföra stora och små bokstäver också. String.ToLower() kan användas för att jämföra strängar oavsett case.

Det stämmer väl inte riktigt?

ToLower() gör ju texten till lowercase. Om man matar in i UPPERCASE eller BlanDat så kommer det inte att bli en träff om man inte gör om även input?

Permalänk

@MickeBoy:

Tack så jätte mycket! Löste det!

Permalänk
Medlem

Försök att använda den metod där man kan ange att inte bry sig om case:

https://msdn.microsoft.com/en-us/library/e6883c06(v=vs.110).a...

Permalänk

Får inte till det med rubrikerna...

Vi fick en ett exempel på kod av våran föreläsare men förstår inte riktigt hur man ska använda den...
Den ser ut såhär:
Console.WriteLine("{0, ‐30} {1, ‐2} {2, ‐15} {3, ‐3} {4, ‐3} {5, -3}",
nyperson.namn, nyperson.ålder, nyperson.position, nyperson.längd,
nyperson.vikt, nyperson.nummer);

Min fråga då är vad vi ska skriva istället nyperson som han har använt.

Och koden för spelartruppen ser ut såhär och de rubriker vi har nu:
Men det blir knas som sagt när vi kör programmet...

public static void PrintSpelare(Spelarinfo[] spelareToPrint)
{

Console.WriteLine("Namn" + "\t" + "Ålder" + "\t" + "Position" + "\t" + "Vikt" + "\t" + "Längd" + "\t" + "Nummer" + "\t");

for (int i = 0; i < spelareToPrint.Length; i++)
{
PrintSpelarinfo(spelareToPrint[i]);
}
}

public static void PrintSpelarinfo(Spelarinfo spelarinfo)
{
Console.WriteLine(spelarinfo.namn + "\t" + spelarinfo.ålder + "\t" + spelarinfo.position + "\t" + spelarinfo.vikt + "\t" + spelarinfo.längd + "\t" + spelarinfo.nummer);
}

Permalänk
Medlem
Skrivet av Emilia_Johanness:

Får inte till det med rubrikerna...

Vi fick en ett exempel på kod av våran föreläsare men förstår inte riktigt hur man ska använda den...
Den ser ut såhär:
Console.WriteLine("{0, ‐30} {1, ‐2} {2, ‐15} {3, ‐3} {4, ‐3} {5, -3}",
nyperson.namn, nyperson.ålder, nyperson.position, nyperson.längd,
nyperson.vikt, nyperson.nummer);

Min fråga då är vad vi ska skriva istället nyperson som han har använt.

Och koden för spelartruppen ser ut såhär och de rubriker vi har nu:
Men det blir knas som sagt när vi kör programmet...

public static void PrintSpelare(Spelarinfo[] spelareToPrint)
{

Console.WriteLine("Namn" + "\t" + "Ålder" + "\t" + "Position" + "\t" + "Vikt" + "\t" + "Längd" + "\t" + "Nummer" + "\t");

for (int i = 0; i < spelareToPrint.Length; i++)
{
PrintSpelarinfo(spelareToPrint[i]);
}
}

public static void PrintSpelarinfo(Spelarinfo spelarinfo)
{
Console.WriteLine(spelarinfo.namn + "\t" + spelarinfo.ålder + "\t" + spelarinfo.position + "\t" + spelarinfo.vikt + "\t" + spelarinfo.längd + "\t" + spelarinfo.nummer);
}

nyperson är instansen av klassen. Motsvarar spelarinfo i din kod.

Permalänk

@MickeBoy:
När jag byter ut det till spelarinfo så får jag i errorlist att:
The name 'spelarinfo' does not exist in the current context.

Permalänk
Medlem
Skrivet av Emilia_Johanness:

@MickeBoy:
När jag byter ut det till spelarinfo så får jag i errorlist att:
The name 'spelarinfo' does not exist in the current context.

Jag tänker mig att du i så fall anropar metoden från ett ställe där du inte har tillgång till variabeln 'spelarinfo'.

För formateringen:

Vad blir utskriften av:

Console.WriteLine(String.Format("{0, -25} {1, -3}", "Kalle Andersson", 25));
Console.WriteLine(String.Format("{0, -25} {1, -3}", "Per Albin", 54));
Console.WriteLine(String.Format("{0, -25} {1, -3}", "Nils-Peter Abrahamsson", 77));

Och varför?

Permalänk
Medlem
Skrivet av MickeBoy:

Det stämmer väl inte riktigt?

ToLower() gör ju texten till lowercase. Om man matar in i UPPERCASE eller BlanDat så kommer det inte att bli en träff om man inte gör om även input?

Utgick ifrån att man gör det på allt som ska jämföras heh

Permalänk
Medlem

.StartsWith() innehåller parameters för att ignorera upper/lowercase, se https://msdn.microsoft.com/en-us/library/ms131452(v=vs.110).a...

Skickades från m.sweclockers.com

Visa signatur

Oldschool [å:ldsku:l] adj. Användandet av datorprodukter som är äldre än 3 månader.

Permalänk
Medlem

Kolumnformat i konsollutskrifter är lite bökigt när man har olika längd på värdena. Du får hur många tecken det längsta namnet är och sedan använda det för att antingen fylla på med tecken på namn som är kortare eller flytta cursor positionen så långt innan nästa .write()

Skickades från m.sweclockers.com

Visa signatur

Oldschool [å:ldsku:l] adj. Användandet av datorprodukter som är äldre än 3 månader.

Permalänk

Delete funktion att ta bort spelare via deras nummer på ryggen

Har en till fråga angående att ta bort spelare i vårat program via nummer.

Koden ser ut såhär:
public static void DeleteSpelare(int nummer)
{
Spelarinfo[] nyVector = new Spelarinfo[spelare.Length - 1];
for (int i = 0; i < nummer; i++)
{
nyVector[i] = spelare[i];
}
for (int i = nummer + 1; i < spelare.Length; i++)
{
nyVector[i - 1] = spelare[i];
}
spelare = nyVector;

}

Sedan skriver vi i i vårat menyval såhär för att anropa metoden:

else if (choice == 4)
{

Console.WriteLine("Skriv in numret för spelaren du vill ta bort:");
int nummer = int.Parse(Console.ReadLine());
DeleteSpelare(nummer);

}

Problemet är att det kommer inget på errorlist men när vi ska ta bort en viss spelare kommer det sedan upp:

An unhandled exception of type 'System.IndexOutOfRangeException' occurred in ManU3.exe

Additional information: Indexet låg utanför gränserna för matrisen.

Förstår inte riktigt problemet..

Permalänk
Medlem
Skrivet av Emilia_Johanness:

Har en till fråga angående att ta bort spelare i vårat program via nummer.

Koden ser ut såhär:
public static void DeleteSpelare(int nummer)
{
Spelarinfo[] nyVector = new Spelarinfo[spelare.Length - 1];
for (int i = 0; i < nummer; i++)
{
nyVector[i] = spelare[i];
}
for (int i = nummer + 1; i < spelare.Length; i++)
{
nyVector[i - 1] = spelare[i];
}
spelare = nyVector;

}

Sedan skriver vi i i vårat menyval såhär för att anropa metoden:

else if (choice == 4)
{

Console.WriteLine("Skriv in numret för spelaren du vill ta bort:");
int nummer = int.Parse(Console.ReadLine());
DeleteSpelare(nummer);

}

Problemet är att det kommer inget på errorlist men när vi ska ta bort en viss spelare kommer det sedan upp:

An unhandled exception of type 'System.IndexOutOfRangeException' occurred in ManU3.exe

Additional information: Indexet låg utanför gränserna för matrisen.

Förstår inte riktigt problemet..

Den nya arrayen är ett element kortare än spelare-arrayen, men iterationerna sker mellan 0 och spelare.Length (en för mycket).

Att använda for-loopar för att göra sånt här ger ofta kod som är svårläst och benägen att innehålla buggar. Ett bättre alternativ är att använda ett LINQ-uttryck:

var nyVector = spelare.Where((item, index) => index != nummer).ToArray();

Visa signatur

Kom-pa-TI-bilitet

Permalänk

@Teknocide:

Aa okej, förstår dock inte riktigt vart jag ska lägga den koden och om jag ska ta bort något?

Tack för hjälpen!

Permalänk
Medlem

Hej!

Problemet är ju att du behandlar det inmatade numret som index i listan. Det blir fel om du inte har en spelare för varje nummer.

Är data så tillrättalagt?

Annars så ska du ju kopiera över varje spelare vars nummer inte matchar inmatningen, d.v.s. för det inmatade numret (vars spelare du inte ska kopiera över så gäller ju att spelare[i].Nummer = nummer.

Permalänk
Medlem
Skrivet av Teknocide:

Den nya arrayen är ett element kortare än spelare-arrayen, men iterationerna sker mellan 0 och spelare.Length (en för mycket).

Att använda for-loopar för att göra sånt här ger ofta kod som är svårläst och benägen att innehålla buggar. Ett bättre alternativ är att använda ett LINQ-uttryck:

var nyVector = spelare.Where((item, index) => index != nummer).ToArray();

Jag tänker om man har precis börjat med en kurs i programmering och inte har gjort något förut så är det bättre att försöka lära sig grunderna först. Då tror jag att det bara ställer till det att introducera alternativa lösningar.

Permalänk
Medlem

Hela raderafunktionen verkar defekt; du kan ju inte ha spelarnas tröjnummer som index i vektorn med alla spelare.

Om du ska ta bort t ex Kalle som har tröjnummer 5 och Maja som har nummer 7 och du börjar med att ta bort Kalle i index 5 så ploppar ju alla ovanför ner ett snäpp så att Ida som tidigare låg i index 6 nu hamnar i 5:an och Maja hamnar på index 6 och om du nu försöker ta bort nummer 7 så blir det ju inte Maja utan snubben som tidigare låg i 8an och då kommer säkert den att lacka ur...
Dessutom vem vill ligga i index 0 och bli kallad för nollan? För att inte tala om att alla ovan Maja nu måste byta tröjor med varann.

Det enda vettiga är att lägga in tröjnummer som en egenskap i SpelarInfo (på precis samma sätt som du nu har namnet) och sedan när du ska ta bort en spelare så söker du efter spelaren med det aktuella tröjnumret pss som du tidigare sökte efter ett namn (men nu blir det mycket enklare eftersom du slipper fundera på skiftläge eller stavning) typ

for (i = spelare.Length; --i >= 0;)
if (spelare[i].tröjnummer == nummerSomSkaRaderas)
{
DeleteSpelare (i);
break;
}

Permalänk

@oxxyyd:

vi har en egenskap som heter nummer i Spelarinfo, denna är då den du kallar "tröjnummer", fast den heter bara nummer, men får det ändå inte att fungera typ...

Permalänk
Medlem
Skrivet av oxxyyd:

Hela raderafunktionen verkar defekt; du kan ju inte ha spelarnas tröjnummer som index i vektorn med alla spelare.

Om du ska ta bort t ex Kalle som har tröjnummer 5 och Maja som har nummer 7 och du börjar med att ta bort Kalle i index 5 så ploppar ju alla ovanför ner ett snäpp så att Ida som tidigare låg i index 6 nu hamnar i 5:an och Maja hamnar på index 6 och om du nu försöker ta bort nummer 7 så blir det ju inte Maja utan snubben som tidigare låg i 8an och då kommer säkert den att lacka ur...
Dessutom vem vill ligga i index 0 och bli kallad för nollan? För att inte tala om att alla ovan Maja nu måste byta tröjor med varann.

Det enda vettiga är att lägga in tröjnummer som en egenskap i SpelarInfo (på precis samma sätt som du nu har namnet) och sedan när du ska ta bort en spelare så söker du efter spelaren med det aktuella tröjnumret pss som du tidigare sökte efter ett namn (men nu blir det mycket enklare eftersom du slipper fundera på skiftläge eller stavning) typ

for (i = spelare.Length; --i >= 0;)
if (spelare[i].tröjnummer == nummerSomSkaRaderas)
{
DeleteSpelare (i);
break;
}

Det är ju i princip sant.

Problemet blir när DeleteSpelare ska implementeras.
Eftersom lösningen använder en array så kommer .Length inte att returnera antalet som finns i listan utan antalet "slots" som arrayen är skapad med.

Den lösning som jag tänker mig är sådan att man börjar kopiera ut alla spelare ur listan som inte har matchande nummer i en for-loop.
När man når aktuellt nummer så hoppar man över detta och fortsätter att kopiera de positioner som ligger efter i listan. För att veta vart man ska börja tänker jag att man håller koll på hur många som redan har kopierats. När man hoppat över positionen som ska tas bort startar man en ny for-loop och kopierar resten. Det finns kanske andra sätt, men detta var det första jag kom på.

Permalänk
Medlem

@Emilia_Johanness: Ok det låter ju vettigt upplagt i alla fall då. Kan du inte bara skita i DeleteSpelare-funktionen och gör så här:

for (int i = 0; i < spelare.Length; i++)
{
if (spelare[i].nummer == nummerSomSkaRaderas)
for (; i < spelare.Length - 1; i++)
spelare[i] = spelare[ i +1];
}

Alltså när du stegat fram till spelaren som ska raderas, som t ex har index 6 i vektorn (tröjnumret kan ju vara något helt annat), så flyttas alla ovanför ned ett snäpp, dvs detta händer i innersta loopen om antalet spelare är 10 (alltså du har en vektor från 0..9)

spelare[6] = spelare[7]
spelare[7] = spelare[8]
spelare[8] = spelare[9]

Det översta cellen, (spelare[9]), blir då över och där kan du ju stoppa in en avbytare eller sätt till null så har du en plats över för nästa spelarförvärv...

Permalänk
Medlem
Skrivet av oxxyyd:

@Emilia_Johanness: Ok det låter ju vettigt upplagt i alla fall då. Kan du inte bara skita i DeleteSpelare-funktionen och gör så här:

for (int i = 0; i < spelare.Length; i++)
{
if (spelare[i].nummer == nummerSomSkaRaderas)
for (; i < spelare.Length - 1; i++)
spelare[i] = spelare[ i +1];
}

Alltså när du stegat fram till spelaren som ska raderas, som t ex har index 6 i vektorn (tröjnumret kan ju vara något helt annat), så flyttas alla ovanför ned ett snäpp, dvs detta händer i innersta loopen om antalet spelare är 10 (alltså du har en vektor från 0..9)

spelare[6] = spelare[7]
spelare[7] = spelare[8]
spelare[8] = spelare[9]

Det översta cellen, (spelare[9]), blir då över och där kan du ju stoppa in en avbytare eller sätt till null så har du en plats över för nästa spelarförvärv...

Om man gör på det sättet och tar bort t.ex. 2 spelare hur ska man veta att dessa är raderade och man ska jobba vidare med listan?

Permalänk
Medlem

@MickeBoy: Förstår inte riktigt frågan... Om man vill att vektorn ska återspegla antalet spelare är det väl bara att krympa vektorn till önskad längd typ
spelare.Length -= 2

om man tagit bort 2 stycken

Permalänk
Medlem
Skrivet av oxxyyd:

@MickeBoy: Förstår inte riktigt frågan... Om man vill att vektorn ska återspegla antalet spelare är det väl bara att krympa vektorn till önskad längd typ
spelare.Length -= 2

om man tagit bort 2 stycken

I C#, åtminstone den version som jag kör, är .Length egenskapen på en array readonly.

Permalänk
Medlem

Ok, men då finns väl något annat sätt att krympa listan. Om det t ex är en generisk lista typ List<SpelarInfo> spelare, så kan du ju använda removeRange och ta bort de sista 2.

Permalänk
Medlem
Skrivet av oxxyyd:

Ok, men då finns väl något annat sätt att krympa listan. Om det t ex är en generisk lista typ List<SpelarInfo> spelare, så kan du ju använda removeRange och ta bort de sista 2.

Ja det är klart att det går att lösa.

Av de exempel som finns postade tidigare i tråden framgår det dock tydligt att det är frågan om en array, så jag tänker att problemet måste lösas för en sådan.

Trådskaparen vill ju ha programmeringshjälp i den första kursen med de första uppgifterna och då känns inte som rätt läge att be hen ändra strukturen på programmet.

Men jag håller med om att om jag skulle göra lösningen själv så skulle jag absolut också välja en liknande lösning för att det är smidigare att jobba med.

Permalänk
Medlem

Så här kan din kod se ut med de metoder ni använder:

public static void DeleteSpelare(int nummer) { Spelarinfo[] nyVector = new Spelarinfo[spelare.Length - 1]; int idx = 0; // skapar ett nytt indexnummer for (int i = 0; i < spelare.Length; i++) // loopar igenom alla spelare { // om tröjnumret INTE är det som vi ska ta bort, då lägger vi till spelaren i den nya arrayen if( spelare[i].nummer != nummer){ nyVector[idx] = spelare[i]; // lägg till spelaren idx++; // öka indexet med en } } spelare = nyVector; }

tänk på att koden inte innehåller någon errorcheck, så om någon anger ett tröjnummer som inte finns så kraschar programmet. Men det kommer ni nog att lära er framöver.

Visa signatur

Oldschool [å:ldsku:l] adj. Användandet av datorprodukter som är äldre än 3 månader.