Pieniä kysymyksiä ohjelmoinnista

Minun pitää lukea tiedostosta nuo rivit ja muuttaa ne eri muotoon, mitkä kirjoitetaan toiseen tiedostoon. Eli tästä tulee ohjelma mikä muuttaa konfiguration toiseen laitevalmistajan muotoon. Olisin pistänyt tähän mallikonfiguraation, mutta ei ollut yhtään tallessa.

Eli:

---- TÄMÄ TEKSTI ON KONFIGURAATION KESKELLÄ, ELI TEKSTIÄ ON YLÄ-/ ALAPUOLELLA (GLOBAALIT KOMENNOT YMS) ----

vlan 100
untagged 1,2
tagged 25

---------------------------------------------------------------------------------------------------------------------------------------

Poimitaan edellisestä konfiguraatiosta tiedot ja muutetaan alla olevaan muotoon. Tämä kirjoitetaan uuteen tiedostoon, josta tulee toisen laitevalmistajan konfiguraatio:

interface Gigabitethernet1/0/1
switchport mode access
switchport acces vlan 100

interface Gigabitethernet1/0/2
switchport mode access
switchport acces vlan 100

interface Gigabitethernet1/0/25
switchport mode trunk
switchport trunk allowed vlan 100

Itse olen töissä tehnyt vastaavia harjoitteita hyödyntäen tätä CiscoConfParse -kirjastoa, joka nimestään huolimatta taipuu moneen.
 
Miten python pitäisi rakentaa, jos haluan syöttää uusia parametrejä while-loopissa / sleep-odotuksessa? Eli tuossa while-aikana olisi mahdollista syöttää uusi odotusaika tai 'pause' komento mikä jäädyttää loopin, tai 'exit' mikä lopettaa sen.

Pääohjelmani muodostuu esimerkin mukaisesti, ja while-looppi intervalli n. 5min. Jos on myös ehdotus millä saan absoluuttisen tarkasti tuon toteutumaan 5min välein, niin senkin voisin ottaa vastaan, vaikka ihan mielenkiinnosta miten se tehtäisiin.

Koodi:
from datetime import datetime

def main():
    transfer_interval = 300
    while(True):
        startinseconds = datetime.now().timestamp()
        
        #...
        #datan siirtoa netin yli, taulukoiden yhdistämistä, kestää ~10sec normaalisti
        #koodirivejä ~60
        #...
        
        sleep_time = transfer_interval-(datetime.now().timestamp() - startinseconds)
        time.sleep(sleep_time)
 
Miten python pitäisi rakentaa, jos haluan syöttää uusia parametrejä while-loopissa / sleep-odotuksessa? Eli tuossa while-aikana olisi mahdollista syöttää uusi odotusaika tai 'pause' komento mikä jäädyttää loopin, tai 'exit' mikä lopettaa sen.

Pääohjelmani muodostuu esimerkin mukaisesti, ja while-looppi intervalli n. 5min. Jos on myös ehdotus millä saan absoluuttisen tarkasti tuon toteutumaan 5min välein, niin senkin voisin ottaa vastaan, vaikka ihan mielenkiinnosta miten se tehtäisiin.

Koodi:
from datetime import datetime

def main():
    transfer_interval = 300
    while(True):
        startinseconds = datetime.now().timestamp()
     
        #...
        #datan siirtoa netin yli, taulukoiden yhdistämistä, kestää ~10sec normaalisti
        #koodirivejä ~60
        #...
     
        sleep_time = transfer_interval-(datetime.now().timestamp() - startinseconds)
        time.sleep(sleep_time)
Tehtävän ratkaisussa joutuu tutustumaan joko säikeisiin tai tapahtumalooppiin. Pelkkä time.sleep() on liian simppeli, torkkujen aikana ohjelma ei tee mitään.

Säikeiden käyttöön liittyy paljon kikkoja ja rajoituksia. Pythonissa on kuitenkin vakiona tkinter-framework, joka varsinaisesti on tarkoitettu graafisen käyttöliittymän tekemiseen. Sen ytimenä olevaa tapahtumalooppia voi tässäkin hyödyntää:

Python:
import tkinter as tk

root = tk.Tk()
root.title("tämä on vain hassu esimerkki")

seconds = 10
running = False

def task():
    # tämä on toistettava tehtävä
    print("Täällä taas: intervalli nyt", seconds)
    root.after(1000 * seconds, task)

def start():
    global running, seconds
    # tässä konfiguroidaan
    s = input("Intervalli sekunteina? ")
    if s.isdecimal(): seconds = int(s)
    if not running:
        running = True
        task()

button = tk.Button(root, text="Toistuvaistyön\nkäynnistys",
    font="Calibri 24 bold", command=start)
button.pack(padx=100, pady=100)
tk.mainloop()
 
Viimeksi muokattu:
Tehtävän ratkaisussa joutuu tutustumaan joko säikeisiin tai tapahtumalooppiin. Pelkkä time.sleep() on liian simppeli, torkkujen aikana ohjelma ei tee mitään.

Säikeiden käyttöön liittyy paljon kikkoja ja rajoituksia. Pythonissa on kuitenkin vakiona tkinter-framework, joka varsinaisesti on tarkoitettu graafisen käyttöliittymän tekemiseen. Sen ytimenä olevaa tapahtumalooppia voi tässäkin hyödyntää:

Python:
import tkinter as tk

root = tk.Tk()
root.title("tämä on vain hassu esimerkki")

seconds = 10
running = False

def task():
    # tämä on toistettava tehtävä
    print("Täällä taas: intervalli nyt", seconds)
    root.after(1000 * seconds, task)

def start():
    global running, seconds
    # tässä konfiguroidaan
    s = input("Intervalli sekunteina? ")
    if s.isdecimal(): seconds = int(s)
    if not running:
        running = True
        task()

button = tk.Button(root, text="Toistuvaistyön\nkäynnistys",
    font="Calibri 24 bold", command=start)
button.pack(padx=100, pady=100)
tk.mainloop()
Yksinkertaisesta esimerkistä tulee vielä yksinkertaisempi käytettäessä tkinterin sijasta threading-kirjastoa.
Tulostus tosin menee tässä sotkuksi, kun on vain yksi konsoli. Siksikin tkinter-ratkaisu on ehkä parempi. Mutta idea siis on tässäkin se, että toistettava funktio käynnistää aina lopuksi erillisen prosessin/säikeen/munakellon, joka tietyn ajan kuluttua käynnistää funktion uudelleen.
Python:
import threading

def task():
    print(f"Täällä taas. Intervalli nyt {seconds} sekuntia")
    threading.Timer(seconds, task).start()

running = False
seconds : int
while True:
    s = input("Intervalli sekunteina? ")
    if s.isdecimal():
        seconds = int(s)
        if not running:
            running = True
            task()
 
Viimeksi muokattu:
Kyllä, tuolla threadingillä rokkaa. Minulla tuossa pääohjelmassa ei ole sinänsä mitään palautettavaa konsoliin, sillä lokiin kerrytän tietoa missä mennään/mitä tehty. Tein konsoliin pienen käyttöliittymän, mistä voi lukea lokia, asettaa intervalliajan, yms parametrejä pääohjelmaan. Johtuen allekirjoittaneesta (aka python-noob), minun pythonin rakenne on vähän väärä/epäpythonmäinen, joten en tuota timeriä käyttänyt sillä tuo pääohjelma sisälsi myös virhetilanneodotuksen (joka on 30min "jäähtymisaika"). Tuo toi toisen ongelman, jos tuon pääohjelman pysäyttää/lopettaa, niin piti threadingille antaa lisämuuttuja/juokseva numero joka käynnistykselle, jotta sen sai käynnistettyä useampaan otteeseen. Tosin näin jälkikäteen, tuolla timerillä sen kyllä olisi saaanut toimimaan kun olisin vain palauttanut virhetilanne booleanin pääohjelmasta ja sen ulkopuolella hoidellut odotuksen... Voi olla että teen tuosta rakenteesta oikeamman.
Jokatapauksessa iso kiitos vinkeistä!
 
Kyllä, tuolla threadingillä rokkaa. Minulla tuossa pääohjelmassa ei ole sinänsä mitään palautettavaa konsoliin, sillä lokiin kerrytän tietoa missä mennään/mitä tehty. Tein konsoliin pienen käyttöliittymän, mistä voi lukea lokia, asettaa intervalliajan, yms parametrejä pääohjelmaan. Johtuen allekirjoittaneesta (aka python-noob), minun pythonin rakenne on vähän väärä/epäpythonmäinen, joten en tuota timeriä käyttänyt sillä tuo pääohjelma sisälsi myös virhetilanneodotuksen (joka on 30min "jäähtymisaika"). Tuo toi toisen ongelman, jos tuon pääohjelman pysäyttää/lopettaa, niin piti threadingille antaa lisämuuttuja/juokseva numero joka käynnistykselle, jotta sen sai käynnistettyä useampaan otteeseen. Tosin näin jälkikäteen, tuolla timerillä sen kyllä olisi saaanut toimimaan kun olisin vain palauttanut virhetilanne booleanin pääohjelmasta ja sen ulkopuolella hoidellut odotuksen... Voi olla että teen tuosta rakenteesta oikeamman.
Jokatapauksessa iso kiitos vinkeistä!
Koska en tunne ongelmaasi, en ihan ymmärtänyt selitystäsi. Eikä minun tarvitsekaan; toivottavasti itse ymmärrät. Mutta tässä täydellisyyden vuoksi sellainen tkinter-versio, jossa on hieman parannettu käyttöliittymä. Tutkittavaksi, jos kiinnostaa.
Python:
import tkinter as tk

root = tk.Tk()
root.title("tämä on vain hassu esimerkki")
root.resizable(0, 0)
# oletusfontti
root.option_add("*font", "Calibri 16")

frame = tk.Frame(root)
frame.pack(padx=50, pady=(20,50))
tk.Label(frame, text="Toistuvaistyö", font="Calibri 24 bold").pack(anchor="w")
f = tk.Frame(frame)
f.pack(pady=10)
tk.Label(f, text="Väliaika: ").pack(side="left")
interval = tk.Entry(f, width=4)
interval.pack(side="left")
tk.Label(f, text=" sekuntia").pack(side="left")
button = tk.Button(frame, text="Aloita", command=lambda:start())
button.pack(anchor="w")

seconds = 10
running = False

interval.delete(0, 'end')
interval.insert(0, str(seconds))

def task():
    print("Tehdään jotain")
    print(f"Jatketaan noin {seconds} sekunnin kuluttua")
    root.after(1000 * seconds, task)

def start():
    global running, seconds
    s = interval.get()
    if s.isdecimal(): seconds = int(s)
    if not running:
        running = True
        button["text"] = "Jatka"
        task()

tk.mainloop()
 
JavaScript:
    const testCalorieRange = () => {
      if (formValues.targetCalories.some((i) => Number(i) < 1500)) {
        return <Heading>You should have at least 1500kcal a day</Heading>;
      }
    }
    
    testCalorieRange();
    return //something jsx

En ymmärrä miksei tuo testCalorieRange() ei koskaan palauta tuota rimpsua vaan aina komponentti palauttaa tuon //something jsx. Logilla pääsee kyllä tuon if lauseen sisälle silloin kuin kuuluukin mutta tuo <Heading> ei vaan palaudu millään.
 
JavaScript:
    const testCalorieRange = () => {
      if (formValues.targetCalories.some((i) => Number(i) < 1500)) {
        return <Heading>You should have at least 1500kcal a day</Heading>;
      }
    }
   
    testCalorieRange();
    return //something jsx

En ymmärrä miksei tuo testCalorieRange() ei koskaan palauta tuota rimpsua vaan aina komponentti palauttaa tuon //something jsx. Logilla pääsee kyllä tuon if lauseen sisälle silloin kuin kuuluukin mutta tuo <Heading> ei vaan palaudu millään.

Tuntematta nyt tarkemmin tuota koko koodia, niin miksi tuo ei palauttaisi tuota something.jsx viimeisenä?
Se on tuon funktion palautus, riippumatta siitä, että nuolifunktion sisällä halutaan välillä palauttaa jotain.

Voisiko tuo mennä
JavaScript:
const testCalorieRange = () => {
      if (formValues.targetCalories.some((i) => Number(i) < 1500)) {
        return <Heading>You should have at least 1500kcal a day</Heading>;
      } else {
        return // something jsx
      }
    }
    
    testCalorieRange();
 
JavaScript:
    const testCalorieRange = () => {
      if (formValues.targetCalories.some((i) => Number(i) < 1500)) {
        return <Heading>You should have at least 1500kcal a day</Heading>;
      }
    }
   
    testCalorieRange();
    return //something jsx

En ymmärrä miksei tuo testCalorieRange() ei koskaan palauta tuota rimpsua vaan aina komponentti palauttaa tuon //something jsx. Logilla pääsee kyllä tuon if lauseen sisälle silloin kuin kuuluukin mutta tuo <Heading> ei vaan palaudu millään.
Kyllähän se varmaan palauttaa sen, mutta koska sille palautteelle ei tehdä mitään niin ei se mihinkään silloin tulostu. testCalorieRange-kutsu pitäisi olla tuon return //something jsx sisällä jos sen haluaa tulostuvan.
 
En ymmärrä miksei tuo testCalorieRange() ei koskaan palauta tuota rimpsua vaan aina komponentti palauttaa tuon //something jsx. Logilla pääsee kyllä tuon if lauseen sisälle silloin kuin kuuluukin mutta tuo <Heading> ei vaan palaudu millään.

Sulla on vähän puutteellinen esimerkki että näkisi vähän enemmän, mitä oikeastaan haluat. Kuten tuossa jo sanottiin, se testCalorieRange(); kyllä evaluoituun oikeaksi elementiksi, mutta et palauta sitä tai käytä sitä palautusarvoa missään, joten sillä ei tehdä yhtään mitään. Se vaan katoaa käyttämättömänä. Haluat ehkä jotain tällaista, joka on aika yleinen tapa tehdä tuollaisia ehdollisia elementtejä:

Koodi:
function isEnoughCalories(calories) {
  if ( calories >= 1500) {
    return true;
  }
  return false;
}

const Foo = ({ calories }) => {
  return (
    <div>
      {!isEnoughCalories(calories) && <p>You should eat more!</p>}
      <p>This is shown regardless...</p>
    </div>
  );
}
 
joo kiitos teille, tuo return tosiaan puuttui tavallaan tuosta, nyt pitää tuota koodia vähän muokata että se toimii halutulla tavalla.
 
Onko teillä muuten preferenssiä restin ja graphqln välillä? Itse valitsin graphql ekaan web appiin, mutta täytyy sanoa että ole tullut vielä kertaakaan käytettyä mitään mistä graphql olisi ollut paljon hyötyä. Hirveä säätö on ollut vaan saada kaikki codegenit ja nexukset ynnä muut toimimaan.

Saako restillä helposti niin kuin type safetyn frontin ja backin välille? Siitä on kumminkin ollut hyötyä.
 
Tein kotiautomaatioon Windowsiin Visual Studiolla tuollaisen pienen gui:n, jossa kaksi nappulaa; start ja stop. Mulla on toisessa cpp -filessä funktio, jonka haluan pyörivän niin kauan kunnes stoppia painetaan. Saan sen käynnistymään kyllä hyvin starttinappulalla, mutta stoppia en saa toimimaan. Start-nappi on button1 ja lähettää nollan ja käynnistää while-loopin, stop-nappula on button2 ja lähettää ykkösen, jolloin while-loopin ei pitäisi pyöriä. Voi olla, että olen täysin hakoteillä tämän ratkaisuni kanssa, kun koitan välittää funktiolle numeroa, jonka mukaan while -looppi joko pyörii tai ei pyöri. Mikähän olisi koodareiden tapa tehdä tällainen?

form.h
Koodi:
private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) {
     saturaatio_mittaus(0);     
    }
}
private: System::Void button2_Click(System::Object^ sender, System::EventArgs^ e) {
     saturaatio_mittaus(1);
}

mittaus.cpp
Koodi:
int saturaatio_mittaus(int seis) {
  while(seis == 0) {
     //ajetaan koodia
  }
}
 
^sulla pitäisi olla esim globaali seis-muuttuja, joka sitten asetetaan ykköseksi tuossa button2_clickissä. Nythän se kutsuu samaa funktiota kun button1_click, joka siis pyörii koko ajan, eikä sen funktion seis-muuttuja muutu miksikään.
 
^ Kiitti! Koitanpa askarrella sillälailla tuota.

Edit: En saa näkymään form.h:ssa määritettyä seis-muuttujaa mittaus.cpp:ssä. Laitoin form.h:n alkuun "extern int seis;" ja klikkauksella asetetaan sille arvo. Mittaus.cpp sanoo: 'seis': undeclared identifier.

Edit2: Aa, piti vissiin vielä mittaus.cpp:ssä esitellä "int seis;" vaikka form.h:ssa oli jo "extern int seis;"?
 
Viimeksi muokattu:
Yritän kääntää Synergyä Ubuntu 21.10:lle seuraamalla näitä ohjeita: Compiling · symless/synergy-core Wiki

Tarvittavien pakettien asennus onnistui ja QT Creator 4.14.1 starttaa nätisti, mutta ohjeessa kohta "Edit the Qt kit "Environment" field under Tools -> Options -> Build & Run -> Kits and add BOOST_ROOT=/home/<user>/boost" aiheuttaa kysymysmerkkejä, kun en löydä tuolta Creatorista oikein paikkaa minne tuo pitäisi lisätä.

Polun seuraaminen onnistuu tuonne Tools -> Options asti ja sitten tökkää kun Build & Run alta ei löydy Kits -kohtaa, eikä myöskään Enviroment-kenttää. Enviroment ja Kits -ovat omia valintojaan vasemmassa reunassa, mutta niiden alta en myöskään löydä mitään järkevää paikka, minne tuo "BOOST_ROOT=/home/<user>/boost" voisi sijoittaa.

Eli mihin tuo oikein lisätään?

valikko.png
 
Yritän kääntää Synergyä Ubuntu 21.10:lle seuraamalla näitä ohjeita: Compiling · symless/synergy-core Wiki

Tarvittavien pakettien asennus onnistui ja QT Creator 4.14.1 starttaa nätisti, mutta ohjeessa kohta "Edit the Qt kit "Environment" field under Tools -> Options -> Build & Run -> Kits and add BOOST_ROOT=/home/<user>/boost" aiheuttaa kysymysmerkkejä, kun en löydä tuolta Creatorista oikein paikkaa minne tuo pitäisi lisätä.

Polun seuraaminen onnistuu tuonne Tools -> Options asti ja sitten tökkää kun Build & Run alta ei löydy Kits -kohtaa, eikä myöskään Enviroment-kenttää. Enviroment ja Kits -ovat omia valintojaan vasemmassa reunassa, mutta niiden alta en myöskään löydä mitään järkevää paikka, minne tuo "BOOST_ROOT=/home/<user>/boost" voisi sijoittaa.

Eli mihin tuo oikein lisätään?

valikko.png

Jos tarkoitus on vaan kääntää se niin mikset seuraa sitä ohjesivun lopussa olevaa kohtaa, CLI ja Linux? Ei tarvitse minkään vieraan IDEn kanssa värkätä.
 
Jos tarkoitus on vaan kääntää se niin mikset seuraa sitä ohjesivun lopussa olevaa kohtaa, CLI ja Linux? Ei tarvitse minkään vieraan IDEn kanssa värkätä.

Putkiaivot sanoo, että tuolla muuttujalla on jotain merkitystä kääntämisessä...

Pitää kokeilla, kunhan promillet laskee :).
 
Mulla on tässä kotiautomaatiojutussa Visual Studiolla tehty Windows GUI, jossa on toimiva sarjaporttikommunikaatio. Nyt minun pitäisi päästä lukemaan ja kirjoittamaan guissa (MyForm.h) avattua sarjaporttia mittaus.cpp:llä. Onko se mahdollista kun setuppi on tällähetkellä tällainen ja tuolla on noita privateja tms.? Vai pitääkö koittaa kaikki toiminnallisuus sisällyttää tuohon guin MyForm.h:n?

Gui jossa sarjaporttikommunikaatio toimii nyt:
form.h:
Koodi:
#pragma once
#include <fstream>
#include <iostream>
#include "mittaus.h"

namespace Project1 {
    using namespace System;
    using namespace System::IO::Ports;

public ref class MyForm : public System::Windows::Forms::Form
    {
    public:
        MyForm(void)
        {
            InitializeComponent();
            findPorts();
        }

protected:
private: System::IO::Ports::SerialPort^ serialPort1;

#pragma region Windows Form Designer generated code 
        void InitializeComponent(void)
        {
          this->components = (gcnew System::ComponentModel::Container());
          this->serialPort1 = (gcnew System::IO::Ports::SerialPort(this->components));
        }
#pragma endregion
    private: void findPorts(void)
    {
        array<Object^>^ objectArray = SerialPort::GetPortNames();
    }
private: System::Void button7_Click(System::Object^ sender, System::EventArgs^ e) {
    //add sender name
    String^ name = this->serialPort1->PortName;
    //grab text and store in send buffer
    String^ message = "hello";
    //write to serial
    if (this->serialPort1->IsOpen)
        this->serialPort1->WriteLine(message);
    else
        this->textBox2->Text = "Port Not Opened";
}

Mulle on epäselvää, että miten miten voisin lähettää esim. tuon hello -stringin mittaus.cpp:stä jo valmiiksi avattuun sarjaporttiin. Vai onnistuuko se mitenkään ilman isompaa remonttia?
 
Viimeksi muokattu:
Kuka muistaa, minkä nimiset kaksi kirjaa oli näillä spekseillä:

Joskus 2007-2009 lainasin kirjastosta kaksi suomenkielistä kirjaa peliohjelmointiin liittyen, jossa ekassa käytiin läpi koodipuolta, ja siinä tehtiin Assemblyllä "Haunted Mall" niminen merkkipohjainen esimerkkipeli. Tämä toinen kirja oli pidempi jossa käytiin tarkemmin läpi pelien design- ja suunnittelupuolta. Yhtään en muista tekijää, julkaisuvuotta, tai oliko kirjojen kannet valkoiset, mustat tai jonkun muun väriset.

EDIT: Ensimmäisen osan nimi on "Opeta itsellesi peliohjelmointi" ja se on julkaistu vuonna 1996. Ja tuo esimerkkipeli The Haunted Mall tehtiinkin VB:llä, eikä asmilla. Toinen kirja saattoi olla "Tehokäyttäjän opas - peliohjelmointi"
 
Viimeksi muokattu:
Mulla on tässä kotiautomaatiojutussa Visual Studiolla tehty Windows GUI, jossa on toimiva sarjaporttikommunikaatio. Nyt minun pitäisi päästä lukemaan ja kirjoittamaan guissa (MyForm.h) avattua sarjaporttia mittaus.cpp:llä. Onko se mahdollista kun setuppi on tällähetkellä tällainen ja tuolla on noita privateja tms.? Vai pitääkö koittaa kaikki toiminnallisuus sisällyttää tuohon guin MyForm.h:n?

Gui jossa sarjaporttikommunikaatio toimii nyt:
form.h:
Koodi:
#pragma once
#include <fstream>
#include <iostream>
#include "mittaus.h"

namespace Project1 {
    using namespace System;
    using namespace System::IO::Ports;

public ref class MyForm : public System::Windows::Forms::Form
    {
    public:
        MyForm(void)
        {
            InitializeComponent();
            findPorts();
        }

protected:
private: System::IO::Ports::SerialPort^ serialPort1;

#pragma region Windows Form Designer generated code
        void InitializeComponent(void)
        {
          this->components = (gcnew System::ComponentModel::Container());
          this->serialPort1 = (gcnew System::IO::Ports::SerialPort(this->components));
        }
#pragma endregion
    private: void findPorts(void)
    {
        array<Object^>^ objectArray = SerialPort::GetPortNames();
    }
private: System::Void button7_Click(System::Object^ sender, System::EventArgs^ e) {
    //add sender name
    String^ name = this->serialPort1->PortName;
    //grab text and store in send buffer
    String^ message = "hello";
    //write to serial
    if (this->serialPort1->IsOpen)
        this->serialPort1->WriteLine(message);
    else
        this->textBox2->Text = "Port Not Opened";
}

Mulle on epäselvää, että miten miten voisin lähettää esim. tuon hello -stringin mittaus.cpp:stä jo valmiiksi avattuun sarjaporttiin. Vai onnistuuko se mitenkään ilman isompaa remonttia?
Ehdotan että siirrät sarjaportin käsittelyn kokonaan unmanaged-puolelle (mittaus.cpp), jolloin managed c++ / winforms -osastoon jää vain GUI eli ne pari nappia. Tai sitten opiskelet aika paljon lisää. Tai kirjoitat koko homman uudelleen esimerkiksi pythonilla, jolloin neuvojakin löytyy netistä paremmin.
 
^Kiitti. Kerkesin alkaa koittamaan reference funktiokutsulla, mutta en tiedä saanko sillä toimimaan. Mutta opinpahan ehkä jotain uutta. Pitänee sen jälkeen koittaa siirtää sarjaporttihomma kokonaan sinne mittaus.cpp puolelle.
 
^Kiitti. Kerkesin alkaa koittamaan reference funktiokutsulla, mutta en tiedä saanko sillä toimimaan. Mutta opinpahan ehkä jotain uutta. Pitänee sen jälkeen koittaa siirtää sarjaporttihomma kokonaan sinne mittaus.cpp puolelle.
Koska kysymyksessä ilmeisesti on harrasteprojekti eikä ensisijaisesti c++-opiskelu, niin toistan ehdotukseni Pythonista. Sillä saa yksinkertaisen tkinter-käyttöliittymän helposti tehtyä, ja sarjaportinkin ohjelmointi on selkeää:


Jos kuitenkin haluat pitäytyä Microsoftin välineissä, niin .NET-käyttöliittymän ohjelmointi sujuu vähimmällä vaivalla C#-kielellä joko WPF- tai WinForms-kirjaston avulla, ja kaiken muunkin toiminnallisuuden voinee toteuttaa ilman c++-natiivikoodia.
 
Kiitti. Olen itseasiassa tehnyt tämän saman projektin aiemmin aika pitkälle Pythonilla, mutta nyt kun aloin lisäämään tähän toiminnallisuuksia niin taustalla oli halu myös oppia C++:aa. Pitää seuraavaksi koittaa myös noilla mainitsemillasi kielillä :)

Mutta taas törmäsin ongelmaan. Saan int arvot liikkumaan tiedostojen välillä, mutta en stringejä.

form.h:
Koodi:
extern int measureValue;
extern std::string measureType;

int main(){
    measureValue = 1;
    measureType = "testi"
}

mittaus.cpp:
Koodi:
int measureValue;
string measureType;

int measure() {
//Täällä kun lukee intin, se on oikein. Mutta kun lukee stringin, se on tyhjä.

}

Reference pass to function - systeemi ei tässä oikein toimi, kun funktioita mittaus.cpp:ssä on monia ja enkä haluaisi tehdä jokaiselle funktiolle omaa nappulaa, jolla lähetän stringin. Olisi hyvä, että jokainen funktio voisi lukea stringin samoin kuin lukee intinkin, mutta en oikein ymmärrä miksei extern string toimi samalla tavalla kuin int. Kääntäjä ei valita mitään, mutta string on tyhjä mittaus.cpp:ssä.
 
Kiitti. Olen itseasiassa tehnyt tämän saman projektin aiemmin aika pitkälle Pythonilla, mutta nyt kun aloin lisäämään tähän toiminnallisuuksia niin taustalla oli halu myös oppia C++:aa. Pitää seuraavaksi koittaa myös noilla mainitsemillasi kielillä :)

Mutta taas törmäsin ongelmaan. Saan int arvot liikkumaan tiedostojen välillä, mutta en stringejä.

form.h:
Koodi:
extern int measureValue;
extern std::string measureType;

int main(){
    measureValue = 1;
    measureType = "testi"
}

mittaus.cpp:
Koodi:
int measureValue;
string measureType;

int measure() {
//Täällä kun lukee intin, se on oikein. Mutta kun lukee stringin, se on tyhjä.

}

Reference pass to function - systeemi ei tässä oikein toimi, kun funktioita mittaus.cpp:ssä on monia ja enkä haluaisi tehdä jokaiselle funktiolle omaa nappulaa, jolla lähetän stringin. Olisi hyvä, että jokainen funktio voisi lukea stringin samoin kuin lukee intinkin, mutta en oikein ymmärrä miksei extern string toimi samalla tavalla kuin int. Kääntäjä ei valita mitään, mutta string on tyhjä mittaus.cpp:ssä.
No ainakin tuolta mainista puuttuu puolipiste stringin perästä. Luulisi kyllä että kääntäjä olisi tuon huomannut.
 
Kiitti. Olen itseasiassa tehnyt tämän saman projektin aiemmin aika pitkälle Pythonilla, mutta nyt kun aloin lisäämään tähän toiminnallisuuksia niin taustalla oli halu myös oppia C++:aa. Pitää seuraavaksi koittaa myös noilla mainitsemillasi kielillä :)

Mutta taas törmäsin ongelmaan. Saan int arvot liikkumaan tiedostojen välillä, mutta en stringejä.

form.h:
Koodi:
extern int measureValue;
extern std::string measureType;

int main(){
    measureValue = 1;
    measureType = "testi"
}

mittaus.cpp:
Koodi:
int measureValue;
string measureType;

int measure() {
//Täällä kun lukee intin, se on oikein. Mutta kun lukee stringin, se on tyhjä.

}

Reference pass to function - systeemi ei tässä oikein toimi, kun funktioita mittaus.cpp:ssä on monia ja enkä haluaisi tehdä jokaiselle funktiolle omaa nappulaa, jolla lähetän stringin. Olisi hyvä, että jokainen funktio voisi lukea stringin samoin kuin lukee intinkin, mutta en oikein ymmärrä miksei extern string toimi samalla tavalla kuin int. Kääntäjä ei valita mitään, mutta string on tyhjä mittaus.cpp:ssä.

Hei! Kokeilin tuota koodia seuraavilla täydennyksillä, eli ensin kirjoitan main funktiossa molemmat arvot, tulostan ne tuolla measure funktiossa, ylikirjoitan arvot ja lopuksi tulostan uudelleen main funktion lopussa:
mittaus.h:mittaus.cppmain.cpp
C++:
#pragma once

void measure();
C++:
#include <iostream>
#include <string>
#include "mittaus.h"

int measureValue;
std::string measureType;

void measure() {
    std::cout << measureValue << measureType << std::endl;
    measureValue = 2;
    measureType = "onnistui";
}
C++:
#include <iostream>
#include <string>
#include "mittaus.h"

extern int measureValue;
extern std::string measureType;

int main(){
    measureValue = 1;
    measureType = "testi";
    measure();
    std::cout << measureValue << measureType << std::endl;
}

g++ 11.2.1 kääntäjällä tulos:
$ g++ main.cpp mittaus.cpp $ ./a.out 1testi 2onnistui

Koodi näyttäisi toimivan oletetulla tavalla. Voisiko ongelma olla nimialueissa? Oletko mahdollisesti määrittänyt saman muuttujanimen eri nimialueissa, jolloin kääntäjä ei näe ongelmaa, mutta muutat toisen nimialueen muuttujaa ja yrität sitten myöhemmin käyttää toista. Tässä esimerkki:

mittaus.hmittaus.cppmain.cpp
C++:
#pragma once
namespace mittaus {
void measure();
}
C++:
#include <iostream>
#include <string>
#include "mittaus.h"

int measureValue;
std::string measureType;

namespace mittaus {
std::string measureType;

void measure() {
    std::cout << measureValue << measureType << std::endl;
    measureValue = 2;
    measureType = "onnistui";
}
}
C++:
#include <iostream>
#include <string>
#include "mittaus.h"

extern int measureValue;
extern std::string measureType;

int main(){
    measureValue = 1;
    measureType = "testi";
    mittaus::measure();
    std::cout << measureValue << measureType << std::endl;
}

Tämän jälkeen tulos näyttää seuraavalta:

$ g++ main.cpp mittaus.cpp $ ./a.out 1 2testi

Nuiden arvojen siirtoon voisi myös käyttää C++ oliopohjaisuutta ja olion attribuutteja eli muuttujia ja halutessa näille asettaja ja lukija (setter/getter) funktioita. Silloin kaikilla luokan funktioilla säilyy myös näkyvyys nuihin muuttujiin. Vielä jos nuo measureType tyypit on vakioita ei tuota string muotoista tyyppiä välttämättä tarvita vaan esimerkiksi enumeroitu tyyppi (enum) riitäisi hyvin:
Koodi:
enum measureType { temperature, speed, brightness };
 
Yritän kääntää Synergyä Ubuntu 21.10:lle seuraamalla näitä ohjeita: Compiling · symless/synergy-core Wiki

Tarvittavien pakettien asennus onnistui ja QT Creator 4.14.1 starttaa nätisti, mutta ohjeessa kohta "Edit the Qt kit "Environment" field under Tools -> Options -> Build & Run -> Kits and add BOOST_ROOT=/home/<user>/boost" aiheuttaa kysymysmerkkejä, kun en löydä tuolta Creatorista oikein paikkaa minne tuo pitäisi lisätä.

Polun seuraaminen onnistuu tuonne Tools -> Options asti ja sitten tökkää kun Build & Run alta ei löydy Kits -kohtaa, eikä myöskään Enviroment-kenttää. Enviroment ja Kits -ovat omia valintojaan vasemmassa reunassa, mutta niiden alta en myöskään löydä mitään järkevää paikka, minne tuo "BOOST_ROOT=/home/<user>/boost" voisi sijoittaa.

Eli mihin tuo oikein lisätään?

valikko.png
Veikkaan, että pitäs laittaa tänne:
Screenshot_20220110_123109.png
 
Hei! Kokeilin tuota koodia seuraavilla täydennyksillä, eli ...

Kiitti ystävällisestä ja perusteellisesta vastauksesta :) Olin tehnyt koodiin mokan, jolle olin jostain syystä täysin sokea. En osannut kopioida sitä edes tuohon ongelmakuvaukseen. Eli alustin tuon stringin vielä toistamiseen ja tässä taitaa extern nollautua:

Koodi:
extern int measureValue;
extern std::string measureType;

int main(){
    measureValue = 1;
    std::string measureType = "testi";   //eli "std::string" oli tässä liikaa :)
}
 
Kiitti ystävällisestä ja perusteellisesta vastauksesta :) Olin tehnyt koodiin mokan, jolle olin jostain syystä täysin sokea. En osannut kopioida sitä edes tuohon ongelmakuvaukseen. Eli alustin tuon stringin vielä toistamiseen ja tässä taitaa extern nollautua:

Koodi:
extern int measureValue;
extern std::string measureType;

int main(){
    measureValue = 1;
    std::string measureType = "testi";   //eli "std::string" oli tässä liikaa :)
}

Tarkalleenottaen tuossa ei externiin kosketa lainkaan, sen sijaan määritellään main-funktioon uusi muuttuja samalla nimellä ja alustetaan se. Tämä on näkyvissä ainoastaan tuon funktion scopessa.
 
Kysymys pythonin aloittelijalta.

Seuraavalla koodinpätkällä yritän saada listan eri harrastukset eli hobbyt erotettua pilkulla:

hobby_list = " "
for hobby in hobbies:
hobby_list += " ".join(hobby)


Print (hobby_list) kuitenkin tällä hetkellä tuottaa seuraanvanlaista tulosta c,o,d,i,n,gr,o,c,k, ,c,l,i,m,b,i,n,gr,e,a,d,i,n,g ja tavoitteena olisi coding, rock climbing, reading. Uskoakseni vika on join-methodin käytössä.
 
Huomaa myös, että join haluaa argumentikseen luettelon (list). Jos sille antaa merkkijonon (string), niin se käsittelee sen merkkien luettelona. Siten esim.

print(", ".join("huuhaa"))

tulostaa

h, u, u, h, a, a
 
Kiitos vastauksista! En nyt valitettavasti kuitenkaan saanut ratkaisua vielä pelittämään. Laitan tehtävänannon ja nykyisen vastauskyhäelmän kokonaisuudessaan. Elikkäs kyseessä on itse asiassa JSON tiedoston käsittely.

Tehtävänanto on seuraavanlainen: Let's have a look at a JSON file, which contains some information about students in the following format:
[
{
"name": "Peter Pythons",
"age": 27,
"hobbies": [
"coding",
"knitting"
]
},
{
"name": "Jean Javanese",
"age": 24,
"hobbies": [
"coding",
"rock climbing",
"reading"
]
}
]

Please write a function named print_persons(filename: str), which reads a JSON file in the above format, and prints the contents as shown below. The file may contain any number of entries.

Peter Pythons 27 years (coding, knitting)

Jean Javanese 24 years (coding, rock climbing, reading)

Minun koodinpätkä on tällä hetkellä seuraava:

import json

def print_persons(filename: str):
with open(filename) as new_file:
data = new_file.read()
persons = json.loads(data)

for person in persons:
name = person["name"]
age = person["age"]
hobbies = person["hobbies"]

hobby_list = " "
for hobby in hobbies:
hobby_list += hobby
print(f"{name} {age} years {(hobby_list)}")



Ongelmana on että tulostus tapahtuu seuraavasti tällä erää:

Peter Pythons 27 years codingknitting kun tavoite olisi Peter Pythons 27 years (coding, knitting).

Varmaan jokin aika simppeli ratkaisu löytyy, ja olen tuota join-metodia yrittänyt käyttää, mutta ei vaan lähde. millään.. Tänään pitäisi palauttaa ja hikeä alkaa jo pukkaamaan.
 
@Anduz koodia suuremmin muuttamatta, lisää nämä pilkut siihen hobby muuttujan perään loopissa, kun muodostat hobby_list muuttujaa ja trimmaa viimeinen pois tai käytä @Paapaa :n kertomaa tapaa joinata ne nippuun pilkkujen kanssa.
 
Ongelmana on että tulostus tapahtuu seuraavasti tällä erää:

Peter Pythons 27 years codingknitting kun tavoite olisi Peter Pythons 27 years (coding, knitting).

Mielestäni annoin sen vastauksen jo :D Eli ota tuo for-luuppi kokonaan pois. Et tarvitse sitä, et mitään hobby_list-muuttujaa.. Ja sulla taitaa olla normi- ja aaltosulkeet väärinpäin. Eli normisulkeet sun pitää printata, älä laita niitä aaltosulkeiden sisään. Aaltosulkeiden sisällä oleva interpoloidaan. Öbaut näin (en testannut):

Koodi:
...
hobbies = ", ".join(person["hobbies"])
print(f"{name} {age} years ({hobbies})")
 
Kannattaa muuten käyttää code-lohkoja, varsinkin Pythonin kanssa, niin säilyy sisennykset:
Koodi:
import json

def print_persons(filename: str):
with open(filename) as new_file:
  data = new_file.read()
persons = json.loads(data)

for person in persons:
  name = person["name"]
  age = person["age"]
  hobbies = person["hobbies"]
  hobby_list = " "
  for hobby in hobbies:
    hobby_list += hobby
  print(f"{name} {age} years {(hobby_list)}")
Ja tosiaan, joinaa tuo hobbies:
Koodi:
print(', '.join(hobbies))
 
Joo, kyllä! Vähillä unilla meni ajatukset hetkeksi jumiin, vastaus oli tosiaan jo @Paapaa ensimmäisessä kommentissa. Kiitos kaikille paljon avusta ja vinkeistä! Arvostan kovasti. Ja tehtävätkin nyt paketissa. Leppoisaa vkl:ää kaikille :)
 
Viimeksi muokattu:
Osaisikohan joku auttaa regexin kanssa?

Minulla on stringejä, jotka on suurinpiirtein tämän näköisiä:
"AAA111:Ford BBB-111:Volvo CCC-111:Naapurin auto"

Haluaisin saada tuosta siis nämä auton rekisterinumeroilta näyttävät stringit: "AAA111", "BBB-111", "CCC-111"
Eli siis kaikki teksti välilyönnin ja ":" merkin välillä. Lisäksi kaikki ennen ensimmäistä ":" merkkiä. "Rekisterinumeron" formaatti ja pituus on vapaa, mutta se ei voi sisältää merkkiä ":" tai välilyönti.

PHP on ohjelmointikieli, eli pitäisi sitä tukeva regex olla.
 
Viimeksi muokattu:
Osaisikohan joku auttaa regexin kanssa?

Minulla on stringejä, jotka on suurinpiirtein tämän näköisiä:
"AAA111:Ford BBB-111:Volvo CCC-111:Naapurin auto"

Haluaisin saada tuosta siis nämä auton rekisterinumeroilta näyttävät stringit: "AAA111", "BBB-111", "CCC-111"
Eli siis kaikki teksti välilyönnin ja ":" merkin välillä. Lisäksi kaikki ennen ensimmäistä ":" merkkiä. "Rekisterinumeron" formaatti ja pituus on vapaa, mutta se ei voi sisältää merkkiä ":" tai välilyönti.

PHP on ohjelmointikieli, eli pitäisi sitä tukeva regex olla.
Meniskö tällä.
PHP:
$s = "AAA111:Ford BBB-111:Volvo CCC-111:Naapurin auto";
preg_match_all("/[A-Z]{3}-?\d{3}/", $s, $m);
var_dump($m);
Edit. En lukenut kunnolla. Kaipaa vähän muokkausta.
 
Osaisikohan joku auttaa regexin kanssa?

Minulla on stringejä, jotka on suurinpiirtein tämän näköisiä:
"AAA111:Ford BBB-111:Volvo CCC-111:Naapurin auto"

Haluaisin saada tuosta siis nämä auton rekisterinumeroilta näyttävät stringit: "AAA111", "BBB-111", "CCC-111"
Eli siis kaikki teksti välilyönnin ja ":" merkin välillä. Lisäksi kaikki ennen ensimmäistä ":" merkkiä. "Rekisterinumeron" formaatti ja pituus on vapaa, mutta se ei voi sisältää merkkiä ":" tai välilyönti.

PHP on ohjelmointikieli, eli pitäisi sitä tukeva regex olla.
Näin nyt ainakin, $matches[2] sisältää rekkarit

PHP:
preg_match_all("/(([^:\s]+):)+/", "AAA111:Ford BBB-111:Volvo CCC-111:Naapurin auto", $matches);
 
Niin ja jos ei pakko ole regexiä käyttää, nii explode.
 
Viimeksi muokattu:
Miten JavaScriptissä pystyy tsekkaamaan onko muuttuja mappi? Minulla on tietorakenne joka näyttää jokseenkin tällaiselta:
Koodi:
{
  a: 1,
  b: "foo",
  c: { d: "bar", e: { f: 42}}
}
Ja pitäisi käydä tuo läpi. Periaatteessa pitäisi olla simppeli rekursio, mutta internet ei suostu paljastamaan oikeaa tapaa huomata, milloin arvo onkin toinen Mappi.
 
Saakohan seuraavan funktion params-parametrin tyypistä tulevaa valitusta (implisiittisesti any) pois? Funktio kyllä tuntuisi toimivan.
Koodi:
        const queryParams = (params, prefix = "") => {
            let retval: string[] = [];
            if (params) {
                if (prefix !== "") {
                    prefix = prefix + '_';
                }
                Object.keys(params).map(k => {
                    if (typeof params[k] === "object" && params[k] !== null) {
                        queryParams(params[k], prefix + k).map(value => retval.push(value));
                    } else {
                        retval.push(prefix + encodeURIComponent(k) + "=" + encodeURIComponent(params[k]));
                    }
                })
            }
            return retval;
        }
Tuo siis käsitelee tämän näköistä tietorakennetta (nuo vakiot on kaikki stringejä):
Koodi:
    const [lazyParams, setLazyParams]: [DataTablePFSEvent, (lazyParams: DataTablePFSEvent) => void] = React.useState<DataTablePFSEvent>({
        first: 0,
        rows: 50,
        page: 0,
        sortField: "name",
        sortOrder: 1,
        multiSortMeta: null,
        filters: {
            global: { value: null, matchMode: FilterMatchMode.CONTAINS },
            name: { operator: FilterOperator.AND, constraints: [{ value: null, matchMode: FilterMatchMode.STARTS_WITH }] },
            dob: { operator: FilterOperator.AND, constraints: [{ value: null, matchMode: FilterMatchMode.EQUALS }] },
            dod: { operator: FilterOperator.AND, constraints: [{ value: null, matchMode: FilterMatchMode.EQUALS }] },
            nationality: { value: null, matchMode: FilterMatchMode.EQUALS },
            work_count: { value: null, matchMode: FilterMatchMode.EQUALS },
            story_count: { value: null, matchMode: FilterMatchMode.EQUALS },
            roles: { value: null, matchMode: FilterMatchMode.EQUALS }
        }
    });
Ajan tuon joinin läpi, niin saan tällaisen rimpsun (jos nyt jotakuta kiinnostaa):
Koodi:
first=0&rows=50&sortField=name&sortOrder=1&filters_global_value=null&filters_global_matchMode=contains&filters_name_operator=and&filters_name_constraints_0_value=null&filters_name_constraints_0_matchMode=startsWith&filters_dob_operator=and&filters_dob_constraints_0_value=null&filters_dob_constraints_0_matchMode=equals&filters_dod_operator=and&filters_dod_constraints_0_value=null&filters_dod_constraints_0_matchMode=equals&filters_nationality_value=null&filters_nationality_matchMode=equals&filters_work_count_value=null&filters_work_count_matchMode=equals&filters_story_count_value=null&filters_story_count_matchMode=equals&filters_roles_value=null&filters_roles_matchMode=equals&page=0&pageCount=101
 
Saakohan seuraavan funktion params-parametrin tyypistä tulevaa valitusta (implisiittisesti any) pois?
En tiedä typescriptistä mutta olisko koska tuossa kutsu funktiolle sekä parametrilla params että rekursiivisesti params[k], tyyppiä on vaikea päätellä.

Jos toi rakenne on vakio, voihan .filters käsitellä erikseen, jolloin tuo on helpompi analysoida.
 
Kokeilin tuota. Siis TS:ssä voi kyllä antaa useamman eri tyypin vaihtoehdoksi, mutta en saanut tuota toimimaan millään määrittelyillä. Ilman tyyppiä tuo siis toimii vaikka editori tuosta valittaakin.
 
Kokeilin tuota. Siis TS:ssä voi kyllä antaa useamman eri tyypin vaihtoehdoksi, mutta en saanut tuota toimimaan millään määrittelyillä. Ilman tyyppiä tuo siis toimii vaikka editori tuosta valittaakin.

Implicit any -varoitus tulee lintteriltä kun et anna mitään tyyppiä ja kääntäjä olettaa silloin tyypiksi any:n. Mutta jos tuo funktio syö ihan minkä tahansa objektin sisään (kuten jotkut funktiot syövät), niin oikea tapa on silloin eksplisiittisesti antaa se tyyppi, eli esim. (params: Object, prefix = ""). Tai jos se syö ihan mitä tahansa, niin sitten annat tyypiksi any:n, eksplisiittisesti.
 
JavaScript:
const queryParams = (params: Record<string, unknown>, prefix = "") => {

luulisi ainakin toimivan? Itse käytän tuota välttääkseni implicit anyn. Yleensä riittää
 

Statistiikka

Viestiketjut
253 994
Viestejä
4 415 687
Jäsenet
73 280
Uusin jäsen
viio

Hinta.fi

Back
Ylös Bottom