Archief - JAVA - strings controleren mbv regular expressions

Het archief is een bevroren moment uit een vorige versie van dit forum, met andere regels en andere bazen. Deze posts weerspiegelen op geen enkele manier onze huidige ideeën, waarden of wereldbeelden en zijn op sommige plaatsen gecensureerd wegens ontoelaatbaar. Veel zijn in een andere tijdsgeest gemaakt, al dan niet ironisch - zoals in het ironische subforum Off-Topic - en zouden op dit moment niet meer gepost (mogen) worden. Toch bieden we dit archief nog graag aan als informatiedatabank en naslagwerk. Lees er hier meer over of start een gesprek met anderen.

wolfway

Legacy Member
hallo,

we moeten als project een klasse "Hero" maken. Deze held (het wordt een computerspelletje) krijgt een naam mee. Aan deze naam hangen echter restricties. Zo mogen er (momenteel) maximum 2 ' tekens in, en voor de rest enkel spaties en letters. En de eerste letter moet een hoofdletter zijn.

Ik weet dat het opgelost kan(/moet) worden met behulp van regular expressions, en de methode .matches() van de klasse String.

Het zou dus zo simpel moeten zijn dat je gewoon letters{ .. , ..} en '{ .. , ..} en spaties{..,..} schrijft , met ..,.. = min, max aantal.

Later mogen er bijvoorbeeld andere tekens wel bij, en dan moet je gewoon dat teken en {min,max} erbijzetten, erg handig dus.


Het lukt ons wel om te controleren of een string tussen de min of max aantal ' is, maar dan mag hij enkel uit ' tekentjes bestaan... Een naam "test 'o' test" zou dus ook moeten juist worden genomen, met dus de ' tekentjes op verschillende plaatsen en ook letters en spaties erbij.


Ik weet (en heb al opgevangen hier en daar) dat het echt maar een 6 tal regeltjes code is ofzo, en ik en men partner hebben al uren op het internet naar een voorbeeldje gezocht dat dit implementeert, maar zonder succes.


Jullie hulp wordt erg gewaardeerd!:help:


Grtz,
Maarten

Cycloon

Legacy Member
Met reguliere expressies ga je dit nooit oplossen. Wil je het toch geavanceerd oplossen dan kan je eventueel een context-vrije grammatica gebruiken maar dat is hier ook overkill. Een simpel lusje die de karakters overloopt en een frequentietabel opstelt is veruit het makkelijkst.

wolfway

Legacy Member
ik zoek dus gewoon een boolean terug te krijgen of de naam voldoet aan de eisen of niet

onze assistenten gaven ons nogtans de tip om reguliere expressies te bekijken en ik denk dat andere teams het ook zo al opgelost hebben, dus het zou moeten mogelijk zijn?

Een lusje, maar dan moet je ook zeggen dat het niet gelijk mag zijn aan 0 1 2 3 4 5 6 7 8 9 & é " { [ en ga zo maar door... terwijl je met die reguliere expressies en matches() precies wel kan controleren dat het énkel de toegelaten tekens toelaat [a-zA-Z] voor de letters enz

Je kan de string opsplitsen en elk karakter in een array zwieren. Is het dan mogelijk om dit wel makkelijk te testen?

Cycloon

Legacy Member
En je denkt dat die match functie met reguliere expressies niet elk teken zal overlopen?

De verzameling karakters die je wil overhouden is vrij beperkt dus makkelijk te controlleren.

Code:
while(i < aantal tekens EN (a < teken < z OF A < teken < Z OF teken == ') EN tel < 2) {
   if(teken == ')
      tel++;
   i++;
}
if (i == aantal tekens) => match!

Dit stukje pseudocode doet alles wat jij verlangt.

EDIT:

Het kan eigenlijk wel met RegExp, net ff wat verder gedacht:
Code:
^([a-zA-Z\s]*'?){0,2}[a-zA-Z\s]*$

Anyway, in dit geval zou ik zelf regexp afraden. Zo'n lusje is een mooie programmeeroefening en zal nog steeds efficiënter zijn.

Messias.

Legacy Member
Zoals hierboven gezegd: een frequentietabel. String overlopen en karakter-frequentieparen opslaan in een hash map.

forloRn_

Legacy Member
Het wiel en zo. Ik zou het net wel met regex proberen op te lossen, omdat je daar meer mee leert dan met zo'n lus. Efficiëntie is geen argument tenzij je zinnens bent die check vele malen na elkaar uit te voeren, maar dat zal niet het geval zijn.

Gurdt

Legacy Member
Ik ben zelf ook gene reguliere expressieman. Ik heb hier snel even een functieje geschreven dat ongeveer wel zou moeten doen wat jij wil bereiken :)
Let op: ik beweer niet dat dit de meest efficiënte of duidelijke code is, ik heb hem zelfs niet gecompileerd, het gaat het algoritme.

Code:
bool check(std::string naam)
{
	int aantalLetters = 0;
	int aantalSpaties = 0;
	int aantalQuotes = 0;

	bool foutieveNaam = false;

	// voor elke letter bepalen wat voor karakter het is
	for(int i = 0; i < naam.length() && !foutieveNaam; ++i)
	{
		char current = naam[i];
		
		if((a < current < z) || (A < current < Z))
			++aantalLetters;
		else if(current == ' ')
			++aantalSpaties;
		else if(current == "'")
			++aantalQuotes;
		else
			foutieveNaam = true;
	}
	
	// controleren of je naam wel voldoet aan de eisen
	foutieveNaam = foutieveNaam || (aantalLetters < MIN_AANTAL_LETTERS) || (aantalLetters > MAX_AANTAL_LETTERS);
	foutieveNaam = foutieveNaam || (aantalSpaties < MIN_AANTAL_SPATIES) || (aantalSpaties > MAX_AANTAL_SPATIES);
	foutieveNaam = foutieveNaam || (aantalQuotes < MIN_AANTAL_QUOTES) || (aantalQuotes > MAX_AANTAL_QUOTES);
	
	return foutieveNaam;

}

wolfway

Legacy Member
er staat in de opgave dat het aantal tekens uitgebreid kan worden, dus stel dat plots ; en . en " ... toegelaten worden, dan zal ik snel aan een heel erg lange methode zitten...

gurdt, bedankt! ik ga dat sebiet eens implementeren en testen

(a < current < z) , mag je dit zo ingeven dan, en zorgt dit dat current een letter van het alfabet moet zijn? (moet je dan ook niet met <= werken?)


bedankt!

Messias.

Legacy Member
wolfway zei:
er staat in de opgave dat het aantal tekens uitgebreid kan worden, dus stel dat plots ; en . en " ... toegelaten worden, dan zal ik snel aan een heel erg lange methode zitten...

Per mijn eerdere suggestie: gebruik een hash map om een frequentietabel op te stellen van karakter-frequentieparen. Learn to love your data structures.

Tyfius

Legacy Member
Volgens mij moet dit toch met een regex gaan. Het is vrij lang geleden dat ik er nog eentje geschreven heb en mijn Java kennis is ook niet bepaald up to date, maar ik dacht aan hetvolgende:
Code:
boolean isMatch = false;
try {
	Pattern regex = Pattern.compile("\\A[A-Z][a-zA-Z\t ]*'?[a-zA-Z\t ]*'?[a-zA-Z\t ]+\\Z");
	Matcher matcher = regex.matcher(input);
	isMatch = matcher.matches();
} catch (PatternSyntaxException ex) {
	// @todo: handle error
}

En ergens lijkt mij die performantie nog al mee te vallen. 't Is niet dat hij één of ander critical space shuttle component aan het maken is.

wolfway

Legacy Member
tyfius, bedankt! dat werkt perfect. Daar ga ik nu eens proberen mee spelen (en uitdokteren hoe je aan die code komt, want ik snap dus praktisch niets van die regex spijtig genoeg)

de andere codes heb ik proberen implementeren maar die werkten niet. En spijtig genoeg is mijn kennis van java ook wat beperkt om er heel erg veel mee te prullen.

(in de code van cycloon zei hij bvb dat \s niet mocht, dat er slechts een aantal gedefinieerd waren, bvb \f ofzo)

wolfway

Legacy Member
moest er trouwens iemand weten hoe je er de {min,max} in kan implementeren, laat maar weten

als we zouden 5 ' tekens mogen gebruiken, of @ tekens bvb plots mogen gebruiken, zou het enorm lastig implementeren worden.

Tyfius

Legacy Member
Het is niet de meest propere regex waarschijnlijk, maar het doet iets als 1ste karakter uppercase, dan 0-unlimited a-zA-Z of whitespace (spatie en tab), dan 0 of 1 ', dan terug gewone karakters, dan terug ' en dan terug gewone karakters.

Als er dan later meerdere speciale karakters moeten komen wordt het wel ingewikkelder, dan kan je misschien toch beter een soort van count doen op het aantal speciale tekens. Iets als
if (input contains ' 0-5 times) {
if (input starts with capital) {
enzoverder.

Cycloon

Legacy Member
wolfway zei:
(in de code van cycloon zei hij bvb dat \s niet mocht, dat er slechts een aantal gedefinieerd waren, bvb \f ofzo)

In je code moet je natuurlijk je \s extra escapen => \\s
Het archief is een bevroren moment uit een vorige versie van dit forum, met andere regels en andere bazen. Deze posts weerspiegelen op geen enkele manier onze huidige ideeën, waarden of wereldbeelden en zijn op sommige plaatsen gecensureerd wegens ontoelaatbaar. Veel zijn in een andere tijdsgeest gemaakt, al dan niet ironisch - zoals in het ironische subforum Off-Topic - en zouden op dit moment niet meer gepost (mogen) worden. Toch bieden we dit archief nog graag aan als informatiedatabank en naslagwerk. Lees er hier meer over of start een gesprek met anderen.
Terug
Bovenaan