» »

[c#] Majhen problemček

[c#] Majhen problemček

Cvenemir ::

Lep pozdrav.

public void povprecnaPlaca(string user)
        {
            //Preberemo datoteko po vrsticah
            string[] lines = System.IO.File.ReadAllLines("imena.txt");

            int salary = 0;
            int totalSalary = 0;
            int averageSalary = 0;
            int counter = 0;
 
            foreach (string line in lines)
            {
                //Razdelimo posamezno vrstico na besede
                string[] words = line.Split('\t');
                
                //Preverimo ujemanje z vnešenim uporabnikom
                if (words[0] == user)
                {                    
                    bool number = Int32.TryParse(words[1], out salary);//Pretvorimo string v število int32                    
                    totalSalary += salary;//Izračun skupne plače  
                    counter++;
                }
                averageSalary = totalSalary / counter;    
            }            
            Console.WriteLine("Povprečna plača uporabnika znaša: {0}", averageSalary);
        }


Zanima me zakaj v IF stavku ne poveča števca. Pogoj se v zanki izpolni dvakrat, števec pa ostane na 0. Kam naj premaknem vrstico counter++; ? Rešitev je verjetno zelo preprosta, ampak ne kapne mi. Hvala za pomoč.

darkolord ::

Takole "na uč" koda izgleda v redu. Postavi breakpoint na pogoj in preveri, zakaj ni izpolnjen.

Pa averageSalary lahko premakneš izven zanke, da ti ne računa brezveze na vsaki vrstici.

sandmat ::

malo neumesno: če uporabljaš tryparse je dobro, če dejansko uporabiš informacijo o tem, ali se je string dalo sparsat. Sicer napiši le salary = int.Parse(words[1]);

Daj en minimalen example txt datoteke, kjer stvar ne dela. Koda izgleda ok.

Cvenemir ::

Ime Placa
MIRKO 1000
MAJA 2000
MIRKO 1100
MAJA 2100
MIRKO 1500
MAJA 2500
MIRKO 1900
MAJA 2900

Takle primer .txt datoteke recimo. Stringi so ločeni s tabulatorjem. V breakpointu je pogoj izpolnjen.

Problem rešen. Hvala za pomoč.

Zgodovina sprememb…

  • spremenil: Cvenemir ()

win64 ::

kar pravi sandmat.
Ko pride do napake pri pretvorbi bo v salary ostala stara vrednost. tako, da boš prištel prejšnjo vrednost.
Napako pri zaokroževanju imaš, ker uporabljaš samo cela števila
Nize se primerja: user.Equals(words[0])

Kaj ti izpiše program?

darkolord ::

Nize se primerja: user.Equals(words[0])
Če že, string.Equals(user, words[0]), v nasprotnem primeru se sesuje, če je user null.

Sicer pa, operator == je za stringe identičen zgoraj omenjenemu.

keworkian ::

Kaj dobiš notr v funkcijo a je MIRKO ali je mirko ali je mIrKo ali kaj?
Obscenities in B-Flat

Zgodovina sprememb…

MrBrdo ::

Sej je rekel da je problem rešen, kaj zdej palamudite...
MrBrdo

Iluvatar ::

Jaz zmeraj rad palamudim, sploh ko vidim, kako se nekateri lepo trudijo, pa na dolgo in na široko rešujejo neke probleme z zankami in števci, hkrati pa, če jih vprašaš zakaj programirajo v .NET in C# takoj izustijo: "jah to je top-noch jezik, imaš polno nekih advanced stvari", seveda te nikoli ne uporabljajo. Sicer pa, kaj pametujem, saj sem bil tudi sam začetnik in sem delal podobne bedarije.
No fantje, ko boste enkrat, na malo višjem nivoju (beri Pro) boste tak problem rešili v par vrsticah. Seveda boste znali uporabljati tudi tiste "advanced" zadeve. Jaz bi ta problem rešil kar z Linq in vgrajenimi funkcijami. Microsoft je dal, dajmo ga uporabljat.
Če predpostavljamo da imamo datoteko ImeUserja ["tabulator"] celoštevilčna cifra, potem bi jaz tako napisal program.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Bedarije.Net
{
    class Program
    {
        static void Main(string[] args)
        {
            povprecnaPlacaZLinq("MIRKO");
        }

        public static void povprecnaPlacaZLinq(string user)
        {
            //Preberemo datoteko po vrsticah
           var lines = System.IO.File.ReadAllLines("imena.txt");
            var userLines =
                lines.ToList().FindAll(x => x.Split('\t')[0].ToLower() == user.ToLower()).Select(
                    z => Int32.Parse(z.Split('\t')[1])).
                    ToList();

            Console.WriteLine("Povprečna plača uporabnika {0} znaša: {1}", user,userLines.Average());
        }
    }
}

Program bi izpisal: Povprečna plača uporabnika MIRKO znaša: 1375
Seveda, če bi imeli datoteko s takimi podatki ki jih je Cvenemir prej lepo zapisal.

Tako malo za intermezzo, da boste dobili malo občutka, kako se dajo lepo te stvari še malo drugače (beri elegantno) urediti :)

win64 ::

Ja pri tem, pa narediš za vsako vrstico dva splita, in celoten seznam dvakrat konvertiraš in potem greš še enkrat skozi, da izračunaš povprečje. Prav tako se bo program sesul, ko v drugem stolpcu ne bo številke.

Majhni popravki, če že hočemo linq, ki povečajo stabilnost in ne pretvarja seznama.
Je pa "klasično" programiranje v tem primeru bolj hitro, pri meni za faktor 5.
public static string[] lines = new string[]{
                "MIRKO\t1000",
                "MAJA\t2000",
                "MIRKO\t1100",
                "MAJA\t2100",
                "MIRKO\t1500",
                "MAJA\t2500",
                "MIRKO\t1900",
                "MAJA\t2900"
            };

        public static double povprecnaPlacaLinq(string user)
        {
            if (string.IsNullOrEmpty(user)) throw new ArgumentNullException("user");
            IEnumerable<string> av = lines.Where(l => l.Split('\t')[0].ToLower().Equals(user));
            if (av.Count() == 0) return 0;
            return av.Average(l => Int32.Parse(l.Split('\t')[1]));
        }
        public static double povprecnaPlaca(string user)
        {
            if (string.IsNullOrEmpty(user)) throw new ArgumentNullException("user");
            string[] splittedLine;
            int current,sum = 0,count=0;
            bool parsed;
            foreach (string line in lines)
            {
                splittedLine = line.Split('\t');
                if (user.Equals(splittedLine[0]))
                {
                    parsed = Int32.TryParse(splittedLine[1], out current);
                    if (!parsed) throw new Exception("Nepravilna vrstica:"+line);
                    sum += current;
                    count++;
                }
            }
            return (double)sum / (double)count;
        }

static void Main(string[] args)
        {
            string user = "mirko";
            user = user.ToLower();
            DateTime start,end;
            start = DateTime.Now;
            for (int i = 0; i < 10000; i++)
                povprecnaPlacaLinq(user);
            end = DateTime.Now;
            Console.WriteLine("Čas:" + (end - start).TotalMilliseconds);

            start = DateTime.Now;
            for (int i = 0; i < 10000; i++)
                povprecnaPlaca(user);
            end = DateTime.Now;
            Console.WriteLine("Čas:" + (end - start).TotalMilliseconds);

        }

darkolord ::

Je pa "klasično" programiranje v tem primeru bolj hitro, pri meni za faktor 5.
Ja, ker enkrat kličeš ToLower(), enkrat pa ne. Potem je razlika samo še za faktor 2 (zaradi dvojnega splittanja).


Vredno ogleda ...

TemaSporočilaOglediZadnje sporočilo
TemaSporočilaOglediZadnje sporočilo
»

Visual C# problem

Oddelek: Programiranje
302913 (2085) mladec
»

C# INSERT statment ne vpise podatkov

Oddelek: Programiranje
111037 (911) darkolord
»

branje iz datoteke c#

Oddelek: Programiranje
141561 (1290) darkolord
»

[c] Enaki datoteki

Oddelek: Programiranje
7936 (796) Spura
»

[C#] branje ter urejanje podatkov

Oddelek: Programiranje
181505 (1280) maticm

Več podobnih tem