Vinnaren i pepparkakshustävlingen!
  • 1
  • 2
2021-12-15, 19:10
  #1
Medlem
Om man vill ta bort sista indexet i en array använder man pop() men det verkar inte fungera?

Kod:
double arr[2] = {3,2,1};
arr.pop();
ERROR: expression must have class type but have double
__________________
Senast redigerad av bosscs2 2021-12-15 kl. 19:12.
Citera
2021-12-15, 19:21
  #2
Medlem
SittFints avatar
Man kan inte ta bort eller lägga till element i en array
Citera
2021-12-15, 19:30
  #3
Medlem
Dessutom deklarerar du att den ska ha 2 element men använder 3.

Du vill använda klassen för att poppa inte en vanlig array.
Citera
2021-12-15, 19:33
  #4
Medlem
SittFints avatar
Citat:
Ursprungligen postat av bambaren
Dessutom deklarerar du att den ska ha 2 element men använder 3.
Exakt. Skulle inte ens kompilera i C++. Skulle gå igenom med en varning i C.
Citera
2022-01-02, 01:51
  #5
Medlem
Citat:
Ursprungligen postat av bosscs2
Om man vill ta bort sista indexet i en array använder man pop() men det verkar inte fungera?

Kod:
double arr[2] = {3,2,1};
arr.pop();
ERROR: expression must have class type but have double

Som andra skrivit så fungerar inte en C-array på detta vis. Det fungerar inte ens om du deklarerar den som en std::array<3, double> eftersom den har precis lika konstant storlek som en traditionell C-array.

Det du kan göra är att deklarera den som en std::vector<double> som har dynamisk storlek och sedan använda metoden pop_back() för att ta bort sista element i vektorn.
Citera
2022-01-05, 23:48
  #6
Medlem
Citat:
Ursprungligen postat av bosscs2
Om man vill ta bort sista indexet i en array använder man pop() men det verkar inte fungera?

Kod:
double arr[2] = {3,2,1};
arr.pop();
ERROR: expression must have class type but have double


Nej, det man menar med push och pop är operationer på en stack.
En stack är en hög med element.
Push lägger ett element på stacken (högen).
Pop hämtar elementet som ligger högst upp.
Det är ett exempel på på sk Lifo (Last in first out) och används i
många sammanhang, tex lagerhållning mm.

Push och pop används mycket ofta i assembler, detta på grund av att vid ett
funktionsanrop så läggs bland annat returadressen och variablerna på stacken.
Gör man en pop för mycket vet inte CPUn var den ska fortsätta och det blir gallimatias
(spaghettisallad)
av hela programmet. Enligt devisen garbage in -> garbage out.
(
Garbage = sopor, skräp).

Skulle man expandera hela koden, dvs inlina varje funktionsanrop så blir resultatet en
en linjär radda av maskinkod istället.

En stack har inte så många likheter med en array.
Men stacken är en viktig datastruktur att känna igen.
__________________
Senast redigerad av DrSvenne 2022-01-06 kl. 00:02.
Citera
2022-01-06, 00:55
  #7
Medlem
Enterprises avatar
Citat:
Ursprungligen postat av DrSvenne
Nej, det man menar med push och pop är operationer på en stack. [..]
En stack har inte så många likheter med en array.
Men stacken är en viktig datastruktur att känna igen.
Det går ju att använda en array för att göra en stack-struktur.
Dock blir den begränsad till förutbestämd storlek, vilket ofta talar för en länkad lista.

Kod:
// C program for array implementation of stack
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>

// A structure to represent a stack
struct Stack {
    
int top;
    
unsigned capacity;
    
int* array;
};

// function to create a stack of given capacity. It initializes size of
// stack as 0
struct StackcreateStack(unsigned capacity)
{
    
struct Stackstack = (struct Stack*)malloc(sizeof(struct Stack));
    
stack->capacity capacity;
    
stack->top = -1;
    
stack->array = (int*)malloc(stack->capacity sizeof(int));
    return 
stack;
}

// Stack is full when top is equal to the last index
int isFull(struct Stackstack)
{
    return 
stack->top == stack->capacity 1;
}

// Stack is empty when top is equal to -1
int isEmpty(struct Stackstack)
{
    return 
stack->top == -1;
}

// Function to add an item to stack.  It increases top by 1
void push(struct Stackstackint item)
{
    if (
isFull(stack))
        return;
    
stack->array[++stack->top] = item;
    
printf("%d pushed to stack\n"item);
}

// Function to remove an item from stack.  It decreases top by 1
int pop(struct Stackstack)
{
    if (
isEmpty(stack))
        return 
INT_MIN;
    return 
stack->array[stack->top--];
}

// Function to return the top from stack without removing it
int peek(struct Stackstack)
{
    if (
isEmpty(stack))
        return 
INT_MIN;
    return 
stack->array[stack->top];
}

// Driver program to test above functions
int main()
{
    
struct Stackstack createStack(100);

    
push(stack10);
    
push(stack20);
    
push(stack30);

    
printf("%d popped from stack\n"pop(stack));

    return 
0;

Citera
2022-01-06, 02:43
  #8
Medlem
Citat:
Ursprungligen postat av Enterprise
Det går ju att använda en array för att göra en stack-struktur.
Dock blir den begränsad till förutbestämd storlek, vilket ofta talar för en länkad lista.

Kod:
// C program for array implementation of stack
#include 
#include 
#include 

// A structure to represent a stack
struct Stack {
    
int top;
    
unsigned capacity;
    
int* array;
};

// function to create a stack of given capacity. It initializes size of
// stack as 0
struct StackcreateStack(unsigned capacity)
{
    
struct Stackstack = (struct Stack*)malloc(sizeof(struct Stack));
    
stack->capacity capacity;
    
stack->top = -1;
    
stack->array = (int*)malloc(stack->capacity sizeof(int));
    return 
stack;
}

// Stack is full when top is equal to the last index
int isFull(struct Stackstack)
{
    return 
stack->top == stack->capacity 1;
}

// Stack is empty when top is equal to -1
int isEmpty(struct Stackstack)
{
    return 
stack->top == -1;
}

// Function to add an item to stack.  It increases top by 1
void push(struct Stackstackint item)
{
    if (
isFull(stack))
        return;
    
stack->array[++stack->top] = item;
    
printf("%d pushed to stack\n"item);
}

// Function to remove an item from stack.  It decreases top by 1
int pop(struct Stackstack)
{
    if (
isEmpty(stack))
        return 
INT_MIN;
    return 
stack->array[stack->top--];
}

// Function to return the top from stack without removing it
int peek(struct Stackstack)
{
    if (
isEmpty(stack))
        return 
INT_MIN;
    return 
stack->array[stack->top];
}

// Driver program to test above functions
int main()
{
    
struct Stackstack createStack(100);

    
push(stack10);
    
push(stack20);
    
push(stack30);

    
printf("%d popped from stack\n"pop(stack));

    return 
0;



Haha, se på fan och hans moster ! Den var ta mig tusan ett bra exempel.
Där ser man, allt är inte helt förlorat.
Det finns hopp om mänskligheten ännu.
Ja, kreativiteten alltså, men mänsklighetens dumhet lär bestå ändå

Hittade du den som ett exempel, eller var det något som du svängde
ihop medans jag knäppte en öl i bastun ?

Jag har dock synpunkter på att peek bör skrivas så här:

Kod:
int *peek(struct Stackstack)
{
static 
int temp 0/* Temporär kopia på stackens top medlem. */
    
if (isEmpty(stack))
        return 
NULL;
temp stack->array[stack->top];     
return (
int *) &temp;


Koden garanterar att användaren inte kan korrumpera stackens innehåll,
genom att bara lämna ut en kopia på toppmedlemmen.
Det gör i och för sig returvärdet i den andra peek också.
Annars kan användaren lockas till att med peek() förändra värdet i stackens
objektmedllemmar. Och så brukar man inte vilja att stackar ska hanteras.

Det blir så att säga en osynlig korruption av data.

Haha, det var minsann ett bra förslag. Kudos och credd för det

Mycket möjligt att de program som tilldelas ett fast stackutrymme, av kompilatorn och länkaren
faktiskt också är byggt på liknande kod.
Den vanliga programmeraren ser ju inte koden som hanterar stacken precis.

Det anses nämligen att det är dålig programmeringssed att bygga program som
bygger på väldigt djup rekursion, och så dåligt designade bör inte program vara.
För djup rekursion är den vanligaste orsaken till att stacken blir full, och programmet avslutas med en exception.
Därav programmeringsforumet stackoverflows namn.

Nu har jag ju inte provkört koden, kollade bara lite snabbt igenom den.
Men mycket intressant ändå.
Stackoverflow error var den ihärdiga 16-bits programmerarens mardröm
för det kunde bli knepigt att ta reda på var det gick snett.
Man fick vanligen inte plats med debugger också i det lilla utrymme som fanns
Och på den tiden var det vanligt med stackoverflow.
16-bits DOS och Windows miljö hade ju bara 64K segment, och det hände att
det segmentet som höll stacken blev fullt.
Då vart det ofta förkylt, och krångligt att ta reda på var det ballade ur.
Sedan så kom ju memory model large som man kunde tilldela tex
överlappande 2 segment,
men det var väl få program som trots det ballade ur.
Man tänkte på ett annat sätt då.
I 32-bit och 64-bits OS händer det nästan aldrig numera.
De som skriver program är vanligen vakna på den detaljen.

Men det finns säkert klantskallar idag också
Lätt att missa dock.

Windows och Microsoft fick oförtjänt dåligt rykte i början eftersom de var tvungna
att skohorna in ett krävande OS i en sådan ytterst trång miljö som 16-bit var.
Det var också speciella svårigheter med att skriva program för Windows/DOS.
Sedan så kom ju 32-bits miljön och då försvann många av de problemen.
En speciell grej som gav kunskap och erfarenhet maskinmässigt
med 16-bit var att man i real mode kunda anropa hårdvaran direkt.
Men när 32-bit Windows kom så fick man helst gå via Windows API.
Inte så lätt att lära sig utan exempel.
Det blev mycket förvirring hos utvecklarna med tex Overlapped ops, och tex DDE.
En mycket irriterande situation kunde uppstå genom att den begärda Overlapped
operationen aldrig slutfördes. Och man visste inte varför, typ

Programspråket Swift (Apple) verkar vilja gå tillbaks ett steg med sitt API,
och programspråk.
att funktionerna påstås bara ta ett argument, ett message,
som sedan funktionen får parsa meddelandet som den bäst vill.
Men då har man inte kompilatorn till hjälp alls att varna för fel parametrar.

Windows grundläggande fönsterhantering (tex flytta, förstora, förminska)
sker just genom att parsa WM_MESSAGES.

Skaparen av Linux, Linus Torvalds, han var nog lite lat för han gav sig på
32-bit miljön direkt.
I stort håller jag med Linus om att ett OS inte behöver skrivasobjektorienterat.
Skriver man ett OS som Linux är så kan man inte slösa CPU-cykler
bara på att anropa medlemsfunktioner för alla objekt i all oändlighet.
Alla anrop kostar nämligen cykler.

Måste ha varit ett jäkla trixande och joxande för Linus,
med tanke på att man på den tiden
hade floppys och han hade inte ens en FAT-hanterare från början.
Och inte ens att Internet fanns, måste ha kostat mycket med bara
modem-uppkopplingen, och teleavgifterna.

Läste nyss att Windows 11 presterar dåligt på vissa AMD-kärror,eftersom man kompilerat Win 11 med att inte ta hänsyn till att en del av dessa CPUer
har en större cache.

Tittar kanske imorgon mera på koden om inte några andra har
några förslag ?
Nu är det nanna kudden som gäller, typ...
__________________
Senast redigerad av DrSvenne 2022-01-06 kl. 03:14.
Citera
2022-01-06, 15:11
  #9
Medlem
Enterprises avatar
Citat:
Ursprungligen postat av DrSvenne
Hittade du den som ett exempel, eller var det något som du svängde
ihop medans jag knäppte en öl i bastun ?
Jag har i egentlig mening inte hållt på med C sedan gymnasiet vilket är ett försvarligt antal år sedan och det här var alltså 100 % kopierat.

Här är länken som också innehåller exempelkod på stack med hjälp av länkad lista samt lite datavetenskaplig teori. https://www.google.com/amp/s/www.gee...n-program/amp/
__________________
Senast redigerad av Enterprise 2022-01-06 kl. 15:18.
Citera
2022-01-06, 23:35
  #10
Medlem
kaks avatar
Citat:
Ursprungligen postat av DrSvenne
Jag har dock synpunkter på att peek bör skrivas så här:

Kod:
int *peek(struct Stackstack)
{
static 
int temp 0/* Temporär kopia på stackens top medlem. */
    
if (isEmpty(stack))
        return 
NULL;
temp stack->array[stack->top];     
return (
int *) &temp;


Nu lyckades du ju göra så att funktionen inte längre är reentrent. Känns ju onödigt.
Citera
2022-01-07, 02:07
  #11
Medlem
Citat:
Ursprungligen postat av Enterprise
Jag har i egentlig mening inte hållt på med C sedan gymnasiet vilket är ett försvarligt antal år sedan och det här var alltså 100 % kopierat.

Här är länken som också innehåller exempelkod på stack med hjälp av länkad lista samt lite datavetenskaplig teori. https://www.google.com/amp/s/www.gee...n-program/amp/


Länken fungerar inte , den ska vara:
https://www.geeksforgeeks.org/stack-...uction-program
Citat:
Ursprungligen postat av kak
Nu lyckades du ju göra så att funktionen inte längre är reentrent. Känns ju onödigt.


?? Reentrant ?? Antar att du menar threadsafe, att varje tråd, thread kan exekvera sin kopia av stack-koden.
Uatn att korrumpera datan i varsin stack, eller samma stack för den delen.

Fast det ingår ju inte i TS beskrivning av problemet, problemställningen,
ja som är felformulerat ändå från början.

Tycker personligen att man ska nöja sig med att lösa problemet och skriva koden för singlethread use.
Om man sedan vill göra tråden threadsafe så får man använda någon mutex eller semaphore.

Såg något gammalt exempel på där programmeraren skrivit en egen schudeler för sina många trådar,
type 25 trådar, som där 5 av trådarna använder samma semaforer, åt gången.
Det användes alltså 5 semaphores/mutexar.
Koden kördes på en 32-kärnig CPU
Vet ej var jag såg den men den exekverade snabbare än om de bara skulle haft en mutex/semafor

Tja det går ju säkert att göra koden threadsafe.

Men det är tyvärr rena kökkenmöddingen det där att försöka optimera mångtrådade program.
Man kan också lägga in korta delays(), lite här och var i koden,
för att taskschedulern

Tips för att skriva multitrådat. Alltså i de låsta delarna av koden:
1. Spara undan i en global/lokal variabel i varje tråd varje tråds ID, threadid alltså.
Mycket användbart vid debugging att debug-messages som skrivs ut på stdout, stderr, eller stddbg (*),
att threadid läggs med i debug-messaget.
2. Undvik FILE (stream)-operationer. Detta därför att där vet man aldrig hur lång tid dessa tar.
OSet har alltid en massa andra hyss för sig, och annat att göra i bakgrunden.
Som vi inte vet ett skit om när vi designar programmet.
3. Undvik dynamisk allokering/deallokering inne i den låsta sektionen.
4. Undvik för stora och djupa loopar i den låsta sektionen.
eftersom sådant låser mutexen för lång tid.
5. Objekt som låses i den låsta sektionen, ska låsas upp i samma ordning "utifrån och in"

Tex på punkt 5:
Låsning:
Lås objekt 1
Lås objekt 2
Lås objekt 3

/* Do something with the objects */
Upplåsning:
Lås upp objekt 3
Lås upp objekt 2
Lås upp objekt 1

Om objekten är beroende av varandra så är
Denna ordning att föredra.

Den vakne läsaren att punkt 2 motsäger punkt 1.
Hur gör man då ?
Jo man sätter samman hela debugmeddelandet till en textsträng.
Därpå låser man upp semaforen.
Nu kan man tryggt använda FILE-funktionerna som vanligt,
och skicka ut den färdigparsade textsträngen på tex debugstream.

Man ska också vara medveten om att det är inte så lätt att debugga
tidskritiska drivers, eftersom deras funktion (tex i kontakt med hårdvara)
måste slutföras inom en viss tid. Man bör därför inte sätta tex breakpoints i sådana
kritiska kodsegment.
Istället brukar man förlita sig på att printa debugmeddelanden på tex stddbg (*)
(stddbg = standard debugfil/stream)

(*) Den vakne läsaren vet förstås att stddbg inte finns,
men jag är själv inne på att den streamen
borde kunna läggas till enkelt.
På en del hemma/borta C-kompilatorer så lade man bara till den
rakt av förr i tiden.

PS Tyckte det var rätt intressant det här faktiskt. DS
Citera
2022-01-07, 07:19
  #12
Medlem
Citat:
Ursprungligen postat av DrSvenne
Länken fungerar inte , den ska vara:
https://www.geeksforgeeks.org/stack-...uction-program

?? Reentrant ?? Antar att du menar threadsafe, att varje tråd, thread kan exekvera sin kopia av stack-koden.
Uatn att korrumpera datan i varsin stack, eller samma stack för den delen.

Fast det ingår ju inte i TS beskrivning av problemet, problemställningen,
ja som är felformulerat ändå från början.

Du använder static för temp variabeln helt i onödan, det gör att den inte är reentrant.

Trådsäker är inte funktionen oavsett vilket.

—-
Edit:
För att förtydliga funktioner kan vara trådsäkra men inte reentranta och vice versa, kombinationen av de båda eller inget av dom.
__________________
Senast redigerad av JohnnyMnemonic 2022-01-07 kl. 07:31.
Citera
  • 1
  • 2

Stöd Flashback

Flashback finansieras genom donationer från våra medlemmar och besökare. Det är med hjälp av dig vi kan fortsätta erbjuda en fri samhällsdebatt. Tack för ditt stöd!

Stöd Flashback