alle Zeichen (außer die Buchstaben von a-z) in NSSTRING ersetzen

mzi2003

Aktives Mitglied
Thread Starter
Dabei seit
20.07.2003
Beiträge
384
Reaktionspunkte
2
Hallo
ich komme nicht weiter, mir fehlt einfach die syntax.

Ich möchte alle Zeichen die nicht a-zA-Z oder @ sind durch eine 0 ersetzen (null).

Nun habe ich folgendes gebastelt

Code:
	for (charIndex = 0; charIndex < [str length]; charIndex++)
	{
		unichar testChar = [str characterAtIndex:charIndex];
		
		//..und hier verlassen sie mich
	}


in str ist der String in dem die ersetzung am ende drin sein sollte nun weiß ich nur nicht wie ich hier am besten vorgehe :(
 
Hallo
ich komme nicht weiter, mir fehlt einfach die syntax.

Ich möchte alle Zeichen die nicht a-zA-Z oder @ sind durch eine 0 ersetzen (null).

Nun habe ich folgendes gebastelt

Code:
	for (charIndex = 0; charIndex < [str length]; charIndex++)
	{
		unichar testChar = [str characterAtIndex:charIndex];
		
		//..und hier verlassen sie mich
	}


in str ist der String in dem die ersetzung am ende drin sein sollte nun weiß ich nur nicht wie ich hier am besten vorgehe :(

NSCharacterSet ist Dein Freund.

Alex
 
NSCharacterSet ist Dein Freund.

Alex

Hallo,
ok, nun bin ich einen Absturz weiter :) Das mit dem char prüfen klappt ja nur das ändern nicht. Nun dachte ich ok nimmste einen neuen String und baust den zeichen für zeichen neu zusammen aber genau da schmiert mir das ding ab, weiß einer nen rat?

Code:
NSString* validoriginstring( NSString *str )
{
	int charIndex;
	
	NSCharacterSet *chrSet = [NSCharacterSet alphanumericCharacterSet] ;
	NSString *result= [[[NSString alloc] init] autorelease];
	result=@"";
	for (charIndex = 0; charIndex < [str length]; charIndex++)
	{

		if ([chrSet characterIsMember: [str characterAtIndex:charIndex]]) {
			result=[NSString stringWithFormat:@"%@%@", 	result, [str characterAtIndex:charIndex]];
		} else {
			result=[NSString stringWithFormat:@"%@%@", 	result, @"X"];
		}
	}
	
	return result;
}
 
Eine Art, es zu tun:

Code:
#import <Foundation/Foundation.h>

int main (int argc, const char * argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

     NSString *inputString =@"dlkjgl902304oulnvmlo<jaoº@º{e3ansdfow64587ºª∆º";
     NSLog (@"Input: %@", inputString);

     NSCharacterSet *specialCharSet = [NSCharacterSet characterSetWithCharactersInString:@"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ@"];
	
     NSMutableString * outputString = [[inputString mutableCopy] autorelease];
     NSUInteger i;
     for (i = 0; i < [inputString length]; i++) {
          if (![specialCharSet characterIsMember:[outputString characterAtIndex:i]]) {
            [outputString replaceCharactersInRange:NSMakeRange(i, 1) withString:@"0"];
         }
      }
     NSLog (@"Output: %@", outputString);
    [pool drain];
    return 0;
}

Alex
 
Danke Alex, genau sowas schwebte mir mit meinem Post vor (NSString->NSMutableString->replaceCharactersInRange).

Nachtrag/Frage: Gibt es eigentlich einen Design-Grund, wieso NSString Immutable ist? Wann immer man in ObjC einen String manipulieren will, muss er erst in einen NSMutableString gewandelt werden. ^^
 
Zuletzt bearbeitet:
Nach meinem Wissensstand sind NextStep Hilfsobjekte (NSArray, NSString,..) grundsätzlich immutable aus zwei Gründen:
  1. Leistung: Ein immutable Objekt wird angelegt und bleibt auch da, während ein mutable Größe und Inhalt ändern kann.
  2. Sicherheit: z.B. bei Threads. Im Prinzip überall da, wo man auf einen definierten Zustand angewiesen ist. Ein anderes Beispiel: Leg mal ein mutable Objekt als Key in eine Hashmap. Dann ändere das Objekt. Der Hashwert ändert sich und das Objekt geht verloren.

Interessanterweise empfiehlt Apple auf dem iPhone mutable Objekte zu verwenden, da Objekterzeugung relativ teuer ist. Zumindest auf dem iPhone.
Am Mac habe ich mir angewöhnt, wann immer es geht, immutable Objekte zu verwenden, da man an weniger denken muss... Und meine veränderbaren Objekte nach der Befüllung, Veränderung, usw. in immutable Objekte zu kopieren. Wie gesagt, kann viel Ärger und Leistung sparen.
 
Nach meinem Wissensstand sind NextStep Hilfsobjekte (NSArray, NSString,..) grundsätzlich immutable aus zwei Gründen:
  1. Leistung: Ein immutable Objekt wird angelegt und bleibt auch da, während ein mutable Größe und Inhalt ändern kann.
  2. Sicherheit: z.B. bei Threads. Im Prinzip überall da, wo man auf einen definierten Zustand angewiesen ist. Ein anderes Beispiel: Leg mal ein mutable Objekt als Key in eine Hashmap. Dann ändere das Objekt. Der Hashwert ändert sich und das Objekt geht verloren.

Interessanterweise empfiehlt Apple auf dem iPhone mutable Objekte zu verwenden, da Objekterzeugung relativ teuer ist. Zumindest auf dem iPhone.
Am Mac habe ich mir angewöhnt, wann immer es geht, immutable Objekte zu verwenden, da man an weniger denken muss... Und meine veränderbaren Objekte nach der Befüllung, Veränderung, usw. in immutable Objekte zu kopieren. Wie gesagt, kann viel Ärger und Leistung sparen.

Danke Max!

Genau aus dem Grund, dass Objekterzeugung eine teure Operation ist (Speicher ausfassen, Konstruktor durchlaufen), wunderte ich mich ja über diese Vorgehensweise. Es ist also eher eine disziplinarische Maßnahme, um den Programmierer vor Fehlern zu schützen. Muable Objects können ja schließlich auch durch den Programmierstil des Entwicklers unveränderlich sein. Danke, akzeptiert.
 
Wann immer man in ObjC einen String manipulieren will, muss er erst in einen NSMutableString gewandelt werden. ^^
Musst du nicht unbedingt, du kannst stattdessen auch einfach stringByReplacingCharactersInRange:withString: nehmen.

Genau aus dem Grund, dass Objekterzeugung eine teure Operation ist (Speicher ausfassen, Konstruktor durchlaufen), wunderte ich mich ja über diese Vorgehensweise.
Wenn du von Anfang an veränderbare Zeichenketten verwendest, musst du auch nie umwandeln.

Ein anderes Beispiel: Leg mal ein mutable Objekt als Key in eine Hashmap. Dann ändere das Objekt. Der Hashwert ändert sich und das Objekt geht verloren.
Das sollte ja eher ein Implementierungsdetail der Hashmap sein.
 
Zuletzt bearbeitet:
Musst du nicht unbedingt, du kannst stattdessen auch einfach stringByReplacingCharactersInRange:withString: nehmen.

Ah man merkt, dass ich kein ObjC-Fachman bin ;)

Wenn du von Anfang an veränderbare Zeichenketten verwendest, musst du auch nie umwandeln.
.

Dann verlierst du aber eben die "Unverletzlichkeit" der Objekte! Ich denke, da muss man dann abwägen, was in welchem Fall besser ist.
 
Das sollte ja eher ein Implementierungsdetail der Hashmap sein.

In Java bin ich da mal drübergestolpert.
Habs gerade in Objective-C/Cocoa ausprobiert. Es lässt sich gar kein mutable Object als Key ablegen.

Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '*** -[NSCFDictionary setObject:forKey:]: mutating method sent to immutable object'
 
Sorry, aber den genauen Text finde ich nicht mehr. Es hat sich viel geändert, seit ich die Texte auf developer.apple.com durchgelesen habe. Er steht jedenfalls irgendwo in den Einführungen zur iPhone-Programmierung. Den Beweis muss ich wohl schuldig bleiben.

PS: Dafür hab ich einen Beleg zu meiner Hashmap-Aussage gefunden:
Mutable Objects in Collections
Storing mutable objects in collection objects can cause problems. Certain collections can become invalid or even corrupt if objects they contain mutate because, by mutating, these objects can affect the way they are placed in the collection. In the first case, the properties of objects that are keys in hashing collections such as NSDictionary objects or NSSet objects will, if changed, corrupt the collection if the changed properties affect the results of the object’s hash or isEqual: methods. (If the hash method of the objects in the collection does not depend on their internal state, corruption is less of a likelihood.) Second, if an object in an ordered collection such as a sorted array has its properties changed, this might affect how the object compares to other objects in the array, thus rendering the ordering invalid.
aus http://developer.apple.com/iPhone/library/documentation/Cocoa/Conceptual/CocoaFundamentals/CocoaObjects/CocoaObjects.html#//apple_ref/doc/uid/TP40002974-CH4-SW69
 
Sorry, aber den genauen Text finde ich nicht mehr. Es hat sich viel geändert, seit ich die Texte auf developer.apple.com durchgelesen habe. Er steht jedenfalls irgendwo in den Einführungen zur iPhone-Programmierung. Den Beweis muss ich wohl schuldig bleiben.

Das war gar nicht böse gemeint, aber für solche Dinge sehe ich immer gerne die Quelle. Schade, ich schau auch noch mal

Alex
 
Ah man merkt, dass ich kein ObjC-Fachman bin ;)
Mit ObjC hat das nichts zu tun, das ist Cocoa. ;)
Dann verlierst du aber eben die "Unverletzlichkeit" der Objekte! Ich denke, da muss man dann abwägen, was in welchem Fall besser ist.
Welche Unverletzlichkeit? Ich verstehe nicht, was jetzt dein Problem ist.

In Java bin ich da mal drübergestolpert.
Habs gerade in Objective-C/Cocoa ausprobiert. Es lässt sich gar kein mutable Object als Key ablegen.
Wie schon gesagt, das ist ein Implementierungsdetail der Hashmap, bzw. hängt davon ab, wie der Hashwert berechnet wird, das ist aber keine generelle Einschränkung an Hashmaps. Wenn man den Hash über die Objektidentität bestimmt, sind veränderbare Objekte in Hashmaps unproblematisch.
 
Mit ObjC hat das nichts zu tun, das ist Cocoa. ;)

Einverstanden, wie gesagt, bin kein Fachmann, weder ObjC noch und erst recht nicht für Cocoa/Carbon/...

Welche Unverletzlichkeit? Ich verstehe nicht, was jetzt dein Problem ist.


Das Problem ist, dass du selbst aufpassen musst, ob du möglicherweise in zwei Threads ein Mutable Object manipulierst. Das kann dir bei Immutable Objekten nicht passieren (dafür läufst du mglw. in andere Probleme).
 
Das "Verbot" von Mutables hat nichts mit Threads zu tun, sondern mit der Kapselung. Es wäre möglich, Eigenschaften einer Instanz zu ändern, ohn dass die Instanz dies bemerkt. Das ist schon fr berechnete Eigenschaften, Konsistenzgewährleistung usw. eine Katastrophe.
Code:
Account : NSObject {
   NSMutableArray* bookings;
   NSDecimalNumber* saldo;
}
Code:
anAccount = …
NSLog( @"%@s", [anAccoutn saldo] );
[[anAccount bookings] addObject:newBooking];
NSLog( @"%@s", [anAccoutn saldo] );
Dieser Code wäre "legal" und eine Katastrophe. Dafür braucht es keinen Thread.

Wer wirklich ändern muss, nimmt dafür -mutableArrayValueForKey:
Code:
[[[anAccount bookings] mutablArrayValueForKey:@"ookings"] addObject:newBooking];
oder die erqweiterten KVC-Mothoden
Code:
NSLog( @"%@s", [anAccoutn saldo] );
[[anAccount bookings] addBookingObject:newBooking];
NSLog( @"%@s", [anAccoutn saldo] );
oder einen Setter:
Code:
NSLog( @"%@s", [anAccoutn saldo] );
NSMutableArray* bookings = [NSMutableArray arrayWithArray:[anAccount bookings]];
[bookings addObject:newBooking];
[anAccount setBookings:bookings];
NSLog( @"%@s", [anAccoutn saldo] );


Hinzukommt, dass auch KVO die Änderung nicht mitbekommt. Eine Eigenschaft sollte daher nie Mutable sein, jedenfalls dann, wenn Sie nach außen bekannt ist. (Ansonsten ist es für mich keine Eigenschaft, was aber ein anderes Thema ist.)

Für Mutable-Collections bietet KVC ein eigens Interface an (Negm-Awad, Band I, S. 426 ff.)

Für Attribute nimmt man eine copy-Eigenschaft.
 
Zuletzt bearbeitet:
Nur am Rande und nicht wirklich wichtig: Die Schleife kann man sich sparen:
Code:
NSArray* components = [inputString componentsSepetratedByCharactersInset:specialCharSet];
outputString = [compoenents jointByString:@"YOURREPLACESTRINGHERE"];
 
Die Schleife kann man sich sparen:
Code:
NSArray* components = [inputString componentsSepetratedByCharactersInset:specialCharSet];
outputString = [compoenents jointByString:@"YOURREPLACESTRINGHERE"];

Hab ich auch zuerst gedacht aber: Nein, kann man sich nicht. Anforderung nicht gelesen ;)

Er will JEDEN Buchstaben, der nicht im Set ist, durch eine '0' ersetzen. Dazu kann ich keinen statischen @"YOURREPLACESTRINGHERE" String nehmen, sondern muss für jede Ersetzung zumindest die Länge kennen.

Die Schleife erschien mir da als die eingängigste Variante, auch wenn man das anders lösen kann.
 
_ebm_ schrieb:
Einverstanden, wie gesagt, bin kein Fachmann, weder ObjC noch und erst recht nicht für Cocoa/Carbon/...

Das gibt es auch in allen anderen OO-Sprachen. Grundsätzlich gilt soviele Eigenschaften wie möglich immutable zu machen. Bei Java heißt dieses Pattern functional approach und birgt zahlreiche Vorteile.
Bisher habe ich es nur bei Cocoa gesehen das explizit mutable/imutable Varianten angeboten werden und dieser Ansatz damit forciert wird was sehr zu begrüßen ist. Grundsätzlich ist das ein Pattern das es auch bei komplexeren Objekten ermöglicht sauberen und sicheren Code zu schreiben.
 
Zurück
Oben Unten