I would like to create a string based on the number of characters passed in. Each character passed in will be a "X". So for example, if the length passed in is 5, then the string created should be
NSString *testString=#"XXXXX";
if it is 2 then it would be
NSString *testString=#"XX";
Can anyone tell me what the most efficient way to do this would be?
Thank you!
If you know the maximum length is some reasonable number then you could do something simple like this:
- (NSString *)xString:(NSUInteger)length {
static NSString *xs = #"XXXXXXXXXXXXXXXXXXXXXXXXXXX";
return [xs substringToIndex:length];
}
NSString *str = [self xString:5]; // str will be #"XXXXX";
If you pass in too large of a length, the app will crash - add more Xs to xs.
This approach is more efficient than building up an NSMutableString but it does make an assumption about the maximum length you might need.
- (NSString *)stringOf:(NSString *)str times:(NSInteger)count
{
NSMutableString *targ = [[NSMutableString alloc] initWithCapacity:count];
for (int i=0; i < count; i++)
{
[targ appendString:str];
}
return targ;
}
and
[self stringOf:#"X" times:4];
note that initWithCapacity: (in performance manner) better than init. But I guess that's all for efficiency.
The way I would do it is
NSMutableString *xString = [[NSMutableString alloc] init];
while ( int i = 0; i < testString.length; i++ ) {
[xString appendString:#"X"];
i++;
}
NSUInteger aLength. // assume this is the argument
NSMutableString *xStr = [NSMutableString stringWithCapacity: aLength];
for ( NSUInteger i = 0; i < aLength; i++ ) {
[xStr appendFormat:#"X"];
}
The following will do what you ask in one call:
NSString *result = [#"" stringByPaddingToLength:numberOfCharsWanted
withString:characterToRepeat
startingAtIndex:0];
where numberOfCharsWanted is an NSUInteger and characterToRepeat is an NSString containing the character.
Related
In my Objective-C code I'd like to take a NSString value, iterate through the letters, sum ASCII values of the letters and return that to the user (preferably as the NSString too).
I have already written a loop, but I don't know how to get the ASCII value of an individual character. What am I missing?
- (NSString*) getAsciiSum: (NSString*) input {
NSInteger sum = 0;
for (NSInteger index=0; index<input.length; index++) {
sum = sum + (NSInteger)[input characterAtIndex:index];
}
return [NSString stringWithFormat: #"%#", sum];
}
Note: I've seen similar questions related to obtaining ASCII values, but all of them ended up displaying the value as a string. I still don't know how to get ASCII value as NSInteger.
Here is the answer:
- (NSString *) getAsciiSum: (NSString *) input
{
NSString *input = #"hi";
int sum = 0;
for (NSInteger index = 0; index < input.length; index++)
{
char c = [input characterAtIndex:index];
sum = sum + c;
}
return [NSString stringWithFormat: #"%d", sum]);
}
This is working for me.
Hope this helps!
This should work.
- (NSInteger)getAsciiSum:(NSString *)stringToSum {
int asciiSum = 0;
for (int i = 0; i < stringToSum.length; i++) {
NSString *character = [stringToSum substringWithRange:NSMakeRange(i, 1)];
int asciiValue = [character characterAtIndex:0];
asciiSum = asciiSum + asciiValue;
}
return asciiSum;
}
Thank you to How to convert a NSString to NSInteger with the sum of ASCII values? for the reference.
I am creating a word scrambler and I am having issues randomizing the letters. When the letters get randomized, it doesn't make sense.
For example, the word PARK shows as AAPA. So, as you can tell it won't make sense for the user when it is time to unscramble.
Just so you know, I am using a .plist file to hold the words.
This is the code I am using to randomize the letters:
_words = [NSMutableArray arrayWithCapacity:scramblelength];
for (int i=0;i<scramblelength;i++) {
NSString *letter = [scramble substringWithRange:[scramble rangeOfComposedCharacterSequenceAtIndex:arc4random()%[scramble length]]];
Then, I am creating UIImageViews to display the scrambled words:
if (![letter isEqualToString:#""]) {
GameView *boxes = [[GameView alloc] initWithLetter:letter andSideLength:boxSide];
boxes.center = CGPointMake(xOffset + i*(boxSide + kTileMargin), kScreenHeight/4*3);
[self.scrambleView addSubview:boxes];
[_words addObject:boxes];
What am I doing wrong here? I would like for the letters in the scrambled words to make sense.
Please help, I am stuck on this one!
Thanks!
As long as your string length will fit in 32 bits, this should be fine. If not, I would replace arc4random_uniform with a uniform random number generator in C++ and compile this as an Objective-C++ module.
The code simply iterates through the string, and swaps each composed character sequence with some random composed character sequence from the same string.
Sorry, that's what happens when you are arrogant and just type out code. Let me know if you have trouble with this one...
For much larger strings, there is a more efficient way, but this seems to do the trick.
NSMutableString category...
#interface NSMutableString (Scramble)
- (void)scramble;
#end
#implementation NSMutableString (Scramble)
static void
swapRanges(NSMutableString *string, NSRange iRange, NSRange jRange)
{
// Need to replace the "trailing" component first
if (NSEqualRanges(iRange, jRange)) return;
if (iRange.location > jRange.location) {
NSRange tmpRange = iRange;
iRange = jRange;
jRange = tmpRange;
}
NSString *iString = [self substringWithRange:iRange];
NSString *jString = [self substringWithRange:jRange];
[string replaceCharactersInRange:jRange withString:iString];
[string replaceCharactersInRange:iRange withString:jString];
}
- (void)scramble
{
for (NSUInteger i = 0; i < self.length; ++i) {
NSRange iRange = [self rangeOfComposedCharacterSequenceAtIndex:i];
NSUInteger j = arc4random_uniform(self.length);
NSRange jRange = [self rangeOfComposedCharacterSequenceAtIndex:j];
swapRanges(self, iRange, jRange);
}
}
#end
NSString category...
#interface NSString (Scramble)
- (NSString*)scrambledString;
#end
#implementation NSString (Scramble)
- (NSString *)scrambledString
{
NSMutableString *result = [self mutableCopy];
[result scramble];
return [result copy];
}
#end
Sample use...
[someMutableString scramble];
NSString *mixedUp = [someString scrambledString];
Or, if you are comfortable with C++, convert to a std::wstring, call std::random_shuffle, then convert that to a NSString. Lots less bugs when using proven, well tested code.
When you are getting a random letter, you need to do something to remove that letter from your NSMutableArray (ie the word's letters when in order). So as you iterate through the word, each time there are fewer characters remaining. Right now, from your limited code block (the first one), it appears you might not be doing that. You want something like "[_words removeObjectAtIndex:letterIndex]" and you would also want to iterate from number of letters down to zero as you remove items from the array also: for (int i=[_words count]; i > [_words count]; i--) because you need to go from 4 letters down to 0 letters left.
So, I'm sure there are more efficient ways to do this, but I go by the rule of not optimizing until you need to. With that in mind, this code appears to work correctly:
- (NSString *)scrambleWord:(NSString *)word {
NSMutableArray *letterArray = [self letterArrayFromWord:word];
NSMutableString *returnValue = [[NSMutableString alloc] init];
do {
int randomIndex = arc4random() % letterArray.count;
[returnValue appendString:letterArray[randomIndex]];
[letterArray removeObjectAtIndex:randomIndex];
if (letterArray.count == 1) {
[returnValue appendString:letterArray[0]];
break;
}
} while (YES);
if ([[returnValue copy] isEqualToString:word]) {
return [self scrambleWord:word];
} else {
return [returnValue copy];
}
}
- (NSMutableArray *)letterArrayFromWord:(NSString *)word {
NSMutableArray *array = [NSMutableArray array];
for (int i = 0; i < word.length; i = i + 1) {
[array addObject:[NSString stringWithFormat:#"%C", [word characterAtIndex:i]]];
}
return array;
}
I am trying to make a utility method for FMDB which will take an NSArray of values and return a string of placeholders for use in an IN statement based on the number of values in the array.
I can't think of an elegant way of creating this string, am I missing some NSString utility method:
// The contents of the input aren't important.
NSArray *input = #[#(55), #(33), #(12)];
// Seems clumsy way to do things:
NSInteger size = [input count];
NSMutableArray *placeholderArray = [[NSMutableArray alloc] initWithCapacity:size];
for (NSInteger i = 0; i < size; i++) {
[placeholderArray addObject:#"?"];
}
NSString *output = [placeholderArray componentsJoinedByString:#","];
// Would return #"?,?,?" to be used with input
What about this?
NSArray *input = #[#(55), #(33), #(12)];
NSUInteger count = [input count];
NSString *output = [#"" stringByPaddingToLength:(2*count-1) withString:#"?," startingAtIndex:0];
// Result: ?,?,?
stringByPaddingToLength fills the given string (the empty string in this case)
to the given length by appending characters from the pattern #"?,".
I'm gathering data to an array in string format and one item is about 30 characters. When data collection is finished I try to combine all the strings into one big string, which is then written to a file. Combining strings is done inside for-loop, and it causes device to crash when number of data items gets somewhere over 4000. What is causing it and how to fix? Here's the code I have for appending strings:
NSString *content = #"";
for (int i=0; i<self.log.count; i++)
{
content = [[content stringByAppendingString:#""] stringByAppendingString:(self.log)[i]];
}
If you are trying to turn an array into a string there is an easier way to do it:
NSString *content = [self.log componentsJoinedByString:#" "];
try this...
NSString *content = #"";
for (int i=0; i<self.log.count; i++)
{
content = [[content stringByAppendingString:#""] stringByAppendingString:[NSString stringWithFormat:#"%#",(self.log)[i]]];
}
To ensure the required amount of memory is allocated, I suggest you use a mutable string with an init for the length required.
-(NSString*)concantString:(NSArray *)incomingLog {
int calculatedLength = 0;
for (int i=0; i < [incomingLog count]; i++)
{
calculatedLength += [incomingLog[i] length];
}
NSMutableString *content = [[NSMutableString alloc] initWithCapacity:calculatedLength];
for (int i=0; i < [incomingLog count]; i++)
{
content = (NSMutableString*)[[content stringByAppendingString:#""] stringByAppendingString:incomingLog[i] ] ;
}
return content;
}
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I am writing code which should reverse a string. When I run the following code it throws an error:
- (NSString*) reversingName:(NSString *)myNameText
{
NSString *result;
int len = [myNameText length];
NSMutableString *reverseName = [[NSMutableString alloc] initWithCapacity:len];
for(int i=len;i>0;i--)
{
[reverseName appendFormat:[NSString stringWithFormat:#"%c",[myNameText characterAtIndex:i]]];
}
result = reverseName;
return result;
}
The for loop line should be as follows:
for(int i=len-1;i>=0;i--)
So your method should be
- (NSString*) reversingName:(NSString *)myNameText
{
int len = [myNameText length];
NSMutableString *reverseName = [[NSMutableString alloc] initWithCapacity:len];
for(int i=len-1;i>=0;i--)
{
[reverseName appendString:[NSString stringWithFormat:#"%c",[myNameText characterAtIndex:i]]];
}
return [reverseName autorelease];
}
I thought I'd throw another version out there in case anyone's interested.. personally, I like the cleaner approach using NSMutableString but if performance is the highest priority this one is faster:
- (NSString *)reverseString:(NSString *)input {
NSUInteger len = [input length];
unichar *buffer = malloc(len * sizeof(unichar));
if (buffer == nil) return nil; // error!
[input getCharacters:buffer];
// reverse string; only need to loop through first half
for (NSUInteger stPos=0, endPos=len-1; stPos < len/2; stPos++, endPos--) {
unichar temp = buffer[stPos];
buffer[stPos] = buffer[endPos];
buffer[endPos] = temp;
}
return [[NSString alloc] initWithCharactersNoCopy:buffer length:len freeWhenDone:YES];
}
I also wrote a quick test as well to compare this with the more traditional NSMutableString method (which I also included below):
// test reversing a really large string
NSMutableString *string = [NSMutableString new];
for (int i = 0; i < 10000000; i++) {
int digit = i % 10;
[string appendFormat:#"%d", digit];
}
NSTimeInterval startTime = [[NSDate date] timeIntervalSince1970];
NSString *reverse = [self reverseString:string];
NSTimeInterval elapsedTime = [[NSDate date] timeIntervalSince1970] - startTime;
NSLog(#"reversed in %f secs", elapsedTime);
Results were:
using NSMutableString method (below) - "reversed in 3.720631 secs"
using unichar *buffer method (above) - "reversed in 0.032604 secs"
Just for reference, here's the NSMutableString method used for this comparison:
- (NSString *)reverseString:(NSString *)input {
NSUInteger len = [input length];
NSMutableString *result = [[NSMutableString alloc] initWithCapacity:len];
for (int i = len - 1; i >= 0; i--) {
[result appendFormat:#"%c", [input characterAtIndex:i]];
}
return result;
}
(NOTE: I don't have enough reputation points yet to vote or comment on answers so I'd appreciate if anyone could vote on this answer for me. I've been a long time reader but now want to start contributing more!)
try this sample code :
NSString *name = #"abcdefghi" ;
int len = [name length];
NSMutableString *reverseName = [[NSMutableString alloc] initWithCapacity:len];
for(int i=len-1;i>=0;i--)
{
[reverseName appendFormat:[NSString stringWithFormat:#"%c",[name characterAtIndex:i]]];
}
NSLog(#"%#",reverseName);
Reverse a String in Swift 2.0:
let string = "This is a test string."
let characters = string.characters
let reversedCharacters = characters.reverse()
let reversedString = String(reversedCharacters)
The short way :
String("This is a test string.".characters.reverse())
OR
let string = "This is a test string."
let array = Array(string)
let reversedArray = array.reverse()
let reversedString = String(reversedArray)
The short way :
String(Array("This is a test string.").reverse())