Gå til innhold

Anbefalte innlegg

  • 9 måneder senere...
Videoannonse
Annonse
Mange lurer på hvordan du sorterer strenger med norske regler (aa etter z osv.) Her er en enkel sak som bruker std::locale som et funksjonsobjekt til å sortere en std::vector bestående av strenger.

 

#include <string>
#include <locale>
#include <vector>
#include <algorithm>

int main(int argc, char *argv[])
{
// vi bruker en vector med strenger
std::vector<std::string> v;

// legger til strenger i vectoren
v.push_back("Aabel, Per");
v.push_back("Zappa, Frank");
v.push_back("Young, Neil");
v.push_back("A Perfect Circle");
v.push_back("Mazzy Star");
v.push_back("Harvey, PJ");
v.push_back("Portishead");
v.push_back("Aaliyah");
v.push_back("Amos, Tori");
v.push_back("Aarset, Eivind");
v.push_back("Tool");

// bruker std::sort i algorithm for å sortere
std::sort(v.begin(), v.end(), std::locale("") );
}

 

Merk at std::locale c'toren vi bruker tar en streng som argument. Det er forskjell på å skrive std::locale() og std::locale("")! Den første varianten bruker "C" locale, mens den andre velger brukerens ønskede locale (i Windows vil det som regel si brukerens regioninstilling).

 

Fordelen med dette er at koden også vil fungere for brukere med andre regioninstillinger (f.eks. svensker, tyskere....). Hvis du ønsker å hardkode strengen til å bruke norske regler, kan du prøve å skrive inn "no" istedenfor en blank streng, slik:

 

std::sort(v.begin(), v.end(), std::locale("no") );

 

locale strengene er forøvrig ikke spesifisert i C++ standarden og kan være implementasjonsavhengig. Men jeg vil tro at "no" vil fungere de fleste steder :)

 

 

Jeg trodde kanskje dette kune ordne til at lister ble sortert korrekt med tanke på æøå, men det gjorde det ikke med mingw i alle fall. æøå fungerte til min store overraskelse mellom kildekode og konsollvinduet, men ikke til sorteringa altså.

Det er dog litt mistenkelig at programmet krasjer hvis jeg hadkoder locale 'nb-NO' eller 'no', eller 'french' for den saks skyld

Lenke til kommentar
  • 2 måneder senere...

Edit at ID3Tagger (taggene: album, artist og navn+++ i MP3)

 

Kanskje litt silly, men jeg synes kanskje tutorial til id3lib var litt avskrekkende. Så om du er newb men har lyst til å fikle med id3 taggene i feks en mp3 fil så legger jeg ved følgende kode som gir deg en god kickstart!

 

LINK: id3lib

 

#include <id3/tag.h>

 

ID3_Tag myTag;

myTag.Link(url_til_mp3_fil);

ID3_Frame* albumFrame = myTag.Find(ID3FID_ALBUM);

albumField = albumFrame->GetField(ID3FN_TEXT);

albumField->Set("navn_som_settes_inn_i_album_på_gjeldene_mp3fil");

myTag.Update();

Lenke til kommentar
  • 3 uker senere...

Trimming av C string

Trimmer av whitespace i starten og slutten av en C string.

#include <string.h>
#include <ctype.h>

char *strtrm(char *str)
{
int from, to, i;

from = 0;
while (str[from] && isspace(str[from])) from++;
to = strlen(str)-1;
while (to >= 0 && isspace(str[to])) to--;
i = 0;
while (from <= to)
	str[i++] = str[from++];
str[i] = 0;
return str;
}

Endret av LostOblivion
Lenke til kommentar
  • 1 år senere...

Her er en kode-snutt som kan brukes til finne ut hvor mange sekunder det har gått fra en tid til en annen. Programmet funker bare i Windows fordi jeg bruker get-ticks funksjonen, men kan lett implementeres til Linux eller Mac. Ideen fikk jeg av Lazy Foo, men jeg har skrevet min egen lignende kode. Jeg var tretten år gammel når jeg lagde denne koden.

Jeg bruker den mest til spill, som å regulere fps(framespersecond).

Her er header filen:

 

/*
Made by Emil Sandstø 2009
*/
#ifndef TIME
#define TIME
#include "Windows.h"

class Timer
{
private: 
DWORD startTicks;	

int pausedTicks;

bool paused;
bool started;

public:
Timer();

void start();//Starter klokken.
void stop();//Stopper klokken.
void pause();//Pauser klokken.
void unpause();//Fortsetter fra klokken pauset.

DWORD get_ticks();//Sender deg tiden som klokken har tikket fra den startet i millisekunder.

bool is_started();
bool is_paused();
};

#endif 

 

Her er cpp filen:

 

/*
Made by Emil Sandstø 2009
*/

#include "Windows.h"
#include "Time.h"

Timer::Timer()
{
startTicks = 0;
pausedTicks = 0;
paused = false;
started = false;
}

void Timer::start()
{
started = true;

paused = false;

startTicks = GetTickCount();
}

void Timer::stop()
{
started = false;

paused = false;
}

DWORD Timer::get_ticks()
{
if ( started == true )
{
	if ( paused == true )
	{
		return pausedTicks;
	}
	else
	{
		return GetTickCount() - startTicks;
	}
}
return 0;
}

void Timer::pause()
{
if (( started == true ) && ( paused == false ))
{
	paused = true;

	pausedTicks = GetTickCount() - startTicks;
}
}

void Timer::unpause()
{
if ( paused == true )
{
	paused = false;

	startTicks = GetTickCount() - pausedTicks;

	pausedTicks = 0;
}
}

bool Timer::is_started()
{
return started;
}

bool Timer::is_paused()
{
return paused;
}

Lenke til kommentar

Jeg bare tenker, i Accellerated C++ boka er aldri "using namespace std" med, så han kjører på med string:: og cout:: og alle mulige andre kommandoer med :: foran, istedet for å bare definere hvilken namespace kommandoene er i fra starten av og slipper å skrive std:: foran alt 30 ganger nedover..hvorfor gjør han det?

 

Når jeg skriver inn eksempelprogrammene slenger jeg bare inn using namespace std og using namespace string istedet for å skrive masse ekstra hele tiden. Det funker jo likevel. Den boka er glimrende forresten, man lærer litt "kule ting" helt i starten istedet for å bli druknet i OO teori.

 

F.eks. er en av de første programsnuttene hvordan man lager en *********** border rundt en tekst, der programmeret genererer borderen etter hvor mange bokstaver man har. Så den blir alltid riktig uansett hvor lang setning man skriver inn :)

Endret av Bytex
Lenke til kommentar
Jeg bare tenker, i Accellerated C++ boka er aldri "using namespace std" med, så han kjører på med string:: og cout:: og alle mulige andre kommandoer med :: foran, istedet for å bare definere hvilken namespace kommandoene er i fra starten av og slipper å skrive std:: foran alt 30 ganger nedover..hvorfor gjør han det?

Det er en god idé at lærebøker er eksplisitte. I C++ er ikke namespaces så utbredt som det kunne vært, men noen prosjekter bruker det mye, og da kan det føre til forvirring dersom eksempelkode for eksempel utelatter hvilket namespace som er i bruk.

Dette er noe som ofte irriterer meg i .NET sin dokumentasjon, altså at eksempelforfatteren har brukt noen using uten å fortelle hvilke.

Lenke til kommentar

Så det er egentlig en dårlig vane jeg legger meg til? Jeg bare gidder ikke skrive std:: 10 ganger nedover når det er et lite program som bare skriver ut ting i et console vindu. Her er snutten som lager ************** border rundt tekst du inputter, forresten. Syns det var et kult triks, og ikke så komplisert heller.

 

#include <iostream>
#include <string>

int main()
{
 std::cout << "Skriv fornavnet ditt her: ";
 std::string name;
 std::cin >> name;

// bygge meldingen vi outputter

 const std::string greeting =  "Hallo, " + name + "!";

// bygge 2. og 4. linje av border
 const std::string spaces(greeting.size(), ' ');
 const std::string second = "* " + spaces + " *";

// bygge 1. og 5. linje av border
 const std::string first(second.size(), '*');

// skrive ut alt sammen
 std::cout << std::endl;
 std::cout << first << std::endl;
 std::cout << second << std::endl;
 std::cout << "* " << greeting << " *" << std::endl;
 std::cout << second << std::endl;
 std::cout << first << std::endl:
		 std::cin.get();

 return 0;
}

 

 

Nå vil du få en perfekt * border rundt det du skriver som input. Som du ser blir det endel std:: istedet for å bruke using namespace std i starten :p

Endret av Bytex
Lenke til kommentar
Hvis du først skal gjøre det Windows spesifikt burde du bruke QueryPerformanceFrequency og QueryPerformanceCounter. Disse teller antall instruksjoner prosesoren har utført og er så presise du får det.

 

Det er sant at QueryPerformanceFrequency er mer nøyaktig enn Get-TickCount, men

hvis du bruker dette for å kontrollere fps er det veldig lett å gjøre en speedhack som for eksempel overklokke cpu, og da går jo fps'en opp å det er ikke en bra når det gjelder spill. I tillegg funker ikke QueryPerformanceFrequency nøyaktig på alle CPU'er.

Lenke til kommentar
Hvis du først skal gjøre det Windows spesifikt burde du bruke QueryPerformanceFrequency og QueryPerformanceCounter. Disse teller antall instruksjoner prosesoren har utført og er så presise du får det.

 

Det er sant at QueryPerformanceFrequency er mer nøyaktig enn Get-TickCount, men

hvis du bruker dette for å kontrollere fps er det veldig lett å gjøre en speedhack som for eksempel overklokke cpu, og da går jo fps'en opp å det er ikke en bra når det gjelder spill. I tillegg funker ikke QueryPerformanceFrequency nøyaktig på alle CPU'er.

Hvis du leser dokumentasjonen, ser du at dette ikke er tilfellet ^^

edit: at klokka i PC-en ikke er nøyaktig uansett, men du har helt rett, men High resolution timer er mer presis enn GetTickCount som kan ha en oppløsning på mellom 10 og 16 ms.

Endret av GeirGrusom
Lenke til kommentar
  • 4 uker senere...

Jeg har laget min egen slags Vector class. Den er ganske fiffig å ha i programmet sitt. Den kan brukes som arrays bare at du har mulighet til å resize arrayen.

 

Jeg er 14 år gammel. Og har programmert i to år nå. Jeg lagde denne greia som en egen øvelse for templates og fordi jeg trenger det i spillene jeg lager.

 

De smarte triksene har jeg fått av eksempler fra andre.

 

Du burde lagre denne greia som en header fil og inkludere den i prosjektet ditt.

#ifndef LINKEDLIST_H
#define LINKEDLIST_H

#include <stdlib.h>
#include <stdio.h>
#include <time.h>

#define SAFE_DELETE( p )		{ if ( p ) { delete ( p ); ( p ) = 0; } }

//---------------------------------------------------------------------------
//Linked List Class
//---------------------------------------------------------------------------
template< class Type > class LinkedList
{
public:
//---------------------------------------------------------------------------
//Element Struct
//---------------------------------------------------------------------------
struct Element 
{
	Type * data;
	Element * next;
	Element * prev;

	Element( Type * Element )
	{
		data = Element;
		next = prev = NULL;
	}
	~Element()
	{
		SAFE_DELETE( data );
		if ( next )
			next->prev = prev;
		if ( prev )
			prev->next = next;
	}
};

//---------------------------------------------------------------------------
//Linked List Constructor and Destructor
//---------------------------------------------------------------------------
LinkedList()
{
	m_first = m_last = m_iterate = m_temp = NULL;
	m_totalElements = 0;
}

~LinkedList()
{
	Empty();
}

//---------------------------------------------------------------------------
//Add a new element to list
//---------------------------------------------------------------------------
Type * Add( Type * element )
{
	if ( element == NULL )
		return NULL;

	if ( m_first == NULL )
	{
		m_first = new Element( element );
		m_last = m_first;
	}
	else 
	{
		m_last->next = new Element( element );
		m_last->next->prev = m_last;
		m_last = m_last->next;
	}

	++m_totalElements;

	return m_last->data;
}

//---------------------------------------------------------------------------
//Insert a element before the next element
//---------------------------------------------------------------------------
Type * InsertBefore( Type * element, Element * nextElement )
{
	m_temp = nextElement->prev;

	++m_totalElements;

	if ( m_temp = NULL )
	{
		m_first = new Element( element );
		m_first->next = nextElement;
		nextElement->prev = m_first;

		return m_first->data;
	}
	else
	{
		nextElement->prev = new Element( element );
		m_temp->next = nextElement->prev;
		nextElement->prev->next = nextElement;
		nextElement->prev->prev = m_temp;

		return m_temp->next->data;
	}
}
//---------------------------------------------------------------------------
//Removing a element
//---------------------------------------------------------------------------
Type * Remove( Type * *element )
{
	m_temp = m_first;

	while ( m_temp != NULL )
	{
		if ( m_temp->data == element )
		{
			if ( m_temp = m_first )
			{
				m_first = m_first->next;
				if ( m_first )
					m_first->prev = NULL;
			}

			if ( m_temp = m_last )
			{
				m_last = m_last->prev;
				if ( m_last )
					m_last->next = NULL;
			}

			SAFE_DELETE( m_temp );

			*element = NULL;

			--m_totalElements;

			return;
		}

		m_temp = m_temp->next;
	}
}

//---------------------------------------------------------------------------
//Destroys every element in the list and deleting the data
//---------------------------------------------------------------------------
void Empty()
{
	while ( m_last != NULL )
	{
		m_temp = m_last;
		m_last = m_last->prev;
		SAFE_DELETE( m_temp );
	}
	m_first = m_last = m_temp = m_iterate = NULL;
	m_totalElements = 0;
}

//-------------------------------------------------------------------------
// Removes all the elements and clears their data pointers.
//-------------------------------------------------------------------------
void ClearPointers()
{
	while( m_last != NULL )
	{
		m_temp = m_last;
		m_temp->data = NULL;
		m_last = m_last->prev;
		SAFE_DELETE( m_temp );
	}
	m_first = m_last = m_iterate = m_temp = NULL;
	m_totalElements = 0;
}

//-------------------------------------------------------------------------
// Removes the given element and clears its data pointer.
//-------------------------------------------------------------------------
void ClearPointer( Type **element )
{
	m_temp = m_first;
	while( m_temp != NULL )
	{
		if( m_temp->data == *element )
		{
			if( m_temp == m_first )
			{
				m_first = m_first->next;
				if( m_first )
					m_first->prev = NULL;
			}
			if( m_temp == m_last )
			{
				m_last = m_last->prev;
				if( m_last )
					m_last->next = NULL;
			}

			m_temp->data = NULL;

			SAFE_DELETE( m_temp );

			*element = NULL;

			m_totalElements--;

			return;
		}

		m_temp = m_temp->next;
	}
}

//-------------------------------------------------------------------------
// Iterates through the elements in the linked list.
//-------------------------------------------------------------------------
Type *Iterate( bool restart = false )
{
	if( restart )
		m_iterate = NULL;
	else
	{
		if( m_iterate == NULL )
			m_iterate = m_first;
		else
			m_iterate = m_iterate->next;
	}

	if( m_iterate == NULL )
		return NULL;
	else
		return m_iterate->data;
}

//-------------------------------------------------------------------------
// Returns the currently iterated element in the linked list.
//-------------------------------------------------------------------------
Type *GetCurrent()
{
	if( m_iterate )
		return m_iterate->data;
	else
		return NULL;
}

//-------------------------------------------------------------------------
// Returns the first element in the linked list.
//-------------------------------------------------------------------------
Type *GetFirst()
{
	if( m_first )
		return m_first->data;
	else
		return NULL;
}

//-------------------------------------------------------------------------
// Returns the last element in the linked list.
//-------------------------------------------------------------------------
Type *GetLast()
{
	if( m_last )
		return m_last->data;
	else
		return NULL;
}

//-------------------------------------------------------------------------
// Returns the next element in the linked list from the given element.
//-------------------------------------------------------------------------
Type *GetNext( Type *element )
{
	m_temp = m_first;
	while( m_temp != NULL )
	{
		if( m_temp->data == element )
		{
			if( m_temp->next == NULL )
				return NULL;
			else
				return m_temp->next->data;
		}

		m_temp = m_temp->next;
	}

	return NULL;
}

//-------------------------------------------------------------------------
// Returns a random element from the linked list.
//-------------------------------------------------------------------------
Type *GetRandom()
{
	if( m_totalElements == 0 )
		return NULL;
	else if( m_totalElements == 1 )
		return m_first->data;

	unsigned long element = rand() * m_totalElements / RAND_MAX;

	m_temp = m_first;
	for( unsigned long e = 0; e < element; e++ )
		m_temp = m_temp->next;

	return m_temp->data;
}

//-------------------------------------------------------------------------
// Returns the complete element (including its next and previous pointers).
//-------------------------------------------------------------------------
Element *GetCompleteElement( Type *element )
{
	m_temp = m_first;
	while( m_temp != NULL )
	{
		if( m_temp->data == element )
				return m_temp;

		m_temp = m_temp->next;
	}

	return NULL;
}

//-------------------------------------------------------------------------
// Returns the total number of elements in the linked list.
//-------------------------------------------------------------------------
unsigned long GetTotalElements()
{
	return m_totalElements;
}

private:
Element * m_last;
Element * m_first;
Element * m_iterate;
Element * m_temp;

unsigned long m_totalElements;
};
#endif 

 

Her er et eksempel på hvordan du bruker den. Jeg kaller header filen som inneholder LinkedList classen for "LinkedList.h"

#include <LinkedList.h>
#include <iostream>


int main()
{
int a = 0;
int b = 0;
int *pC = 0; //Lager en pointer som peker til NULL
int d = 0;

pC = (int*)200; //Pointer mot 200

LinkedList<int> tall; // Lager en liste <int> liste	
tall.Add( (int*) 50 ); // Setter inn en pointer til 50 i listen
tall.Add( pC ); // Setter inn pointer i listen
tall.Add( (int*) 80 ); //Setter inn en pointer til 80 i listen


std::cout << "Iterater gjennom listen\n";

tall.Iterate( true );
while( tall.Iterate() )
{		
	std::cout <<(int)tall.GetCurrent() << " " << std::endl; // Får tallet som 
                                                                       //blir iterated
}

a = (int)tall.GetFirst(); // Får første tallet i listen
b = (int)tall.GetLast(); // Får siste tallet i listen

std::cout << "Får første og siste tall i listen.\n";
std::cout << a << " " << b;

d = (int)tall.GetNext( pC );

std::cout << "\nFår neste etter andre elementet i listen som er 200\n";
std::cout << d;
std::cin.get();

return 0;
}

Endret av Tapped
Lenke til kommentar
  • 3 måneder senere...

Jeg har laget min egen slags Vector class .. snip ..

 

hvor nyttig er egentlig dette når vi har stl? Dette er helt basic stuff som man lærer 1 året i en programmeringsklasse.

 

i tilegg mangler den standard ting som

* iteratorer

LinkedList<int> liste;
sort(liste.begin(), liste.end() ); // dette vil ikke fungere.

* er ikke const correct

const Linkedlist<int> liste;
liste.GetTotalElements()();  /// compiler error. burde ikke gi det, da dette kallet ikke modifiserer lista i det hele tatt.

* må caste for å insette pod types.

Linkedlist<int> liste:
liste.Add(10); // funker ikke, må caste.. Dette er jo bare rot, jeg har jo allerede definert at typen jeg skal bruke er en int, ikke en int*!

 

Du skriver også at den ligner på et array, men du har ikke laget [] operatorer til den.

 

ta en titt på std::vector (som array - men kan resizes), std::list (vanlig linka liste), std::set (sortert), std::map (key, value oppslag)

eneste som kunne vært nyttig her er en rask og minneeffektiv version av std::vector.

 

de vanlige containerne som finnes i stl, har mer funksjonalitet og er bedere enn det du har laget her. Sorry, men skal det være kodesnutter her, bør det være noe folk har bruk for.

Endret av [kami]
Lenke til kommentar
  • 2 måneder senere...

Opprett en konto eller logg inn for å kommentere

Du må være et medlem for å kunne skrive en kommentar

Opprett konto

Det er enkelt å melde seg inn for å starte en ny konto!

Start en konto

Logg inn

Har du allerede en konto? Logg inn her.

Logg inn nå
  • Hvem er aktive   0 medlemmer

    • Ingen innloggede medlemmer aktive
×
×
  • Opprett ny...