Удалите все кроме чисел от NSString

Как альтернатива вложенной IFS, существует способ использовать do / while(false) для вспыхивания где угодно:

    function()
    {
        HRESULT error = S_OK;

        do
        {
            if(!SUCCEEDED(Operation1()))
            {
                error = OPERATION1FAILED;
                break;
            }

            if(!SUCCEEDED(Operation2()))
            {
                error = OPERATION2FAILED;
                break;
            }

            if(!SUCCEEDED(Operation3()))
            {
                error = OPERATION3FAILED;
                break;
            }
            if(!SUCCEEDED(Operation4()))
            {
                error = OPERATION4FAILED;
                break;
            }
        } while (false);

        return error;
    }

, Который получает Вас одна точка выхода, позволяет Вам иметь другое вложение операций, но все еще реальную глубинную структуру. Если Вам не нравится! СЛЕДОВАВШИЙ Вы могли всегда делать, ПЕРЕСТАЛ РАБОТАТЬ что. Такого рода вещь также позволяет Вам добавить другой код между любыми двумя другими проверками, не имея необходимость повторно располагать что-либо с отступом.

, Если Вы были действительно сумасшедшими, что целый if блок мог быть macroized также.: D

    #define BREAKIFFAILED(x,y) if (!SUCCEEDED((x))) { error = (Y); break; }

    do
    {
        BREAKIFFAILED(Operation1(), OPERATION1FAILED)
        BREAKIFFAILED(Operation2(), OPERATION2FAILED)
        BREAKIFFAILED(Operation3(), OPERATION3FAILED)
        BREAKIFFAILED(Operation4(), OPERATION4FAILED)
    } while (false);
157
задан Anh Pham 8 September 2017 в 08:52
поделиться

7 ответов

Старый вопрос, но как насчет:

  NSString *newString = [[origString componentsSeparatedByCharactersInSet:
                [[NSCharacterSet decimalDigitCharacterSet] invertedSet]] 
                componentsJoinedByString:@""];

Он разбивает исходную строку на набор нецифровых символов, а затем повторно собирает их, используя пустой разделитель строк. Не так эффективно, как выбор символов, но гораздо более компактный код.

374
ответ дан 23 November 2019 в 21:42
поделиться

There's no need to use a regular expressions library as the other answers suggest -- the class you're after is called NSScanner. It's used as follows:

NSString *originalString = @"(123) 123123 abc";
NSMutableString *strippedString = [NSMutableString 
        stringWithCapacity:originalString.length];

NSScanner *scanner = [NSScanner scannerWithString:originalString];
NSCharacterSet *numbers = [NSCharacterSet 
        characterSetWithCharactersInString:@"0123456789"];

while ([scanner isAtEnd] == NO) {
  NSString *buffer;
  if ([scanner scanCharactersFromSet:numbers intoString:&buffer]) {
    [strippedString appendString:buffer];

  } else {
    [scanner setScanLocation:([scanner scanLocation] + 1)];
  }
}

NSLog(@"%@", strippedString); // "123123123"

EDIT: I've updated the code because the original was written off the top of my head and I figured it would be enough to point the people in the right direction. It seems that people are after code they can just copy-paste straight into their application.

I also agree that Michael Pelz-Sherman's solution is more appropriate than using NSScanner, so you might want to take a look at that.

75
ответ дан 23 November 2019 в 21:42
поделиться

Если вы просто смотрите чтобы получить числа из строки, вы наверняка можете использовать регулярные выражения для их анализа. Для выполнения регулярных выражений в Objective-C ознакомьтесь с RegexKit . Изменить: Как указывает @Nathan, использование NSScanner - гораздо более простой способ синтаксического анализа всех чисел из строки. Я совершенно не знал об этом варианте, так что поддерживаю его за предложение. (Мне даже не нравится использовать регулярные выражения, поэтому я предпочитаю подходы, которые не требуют их.)

Если вы хотите отформатировать телефонные номера для отображения, стоит взглянуть на NSNumberFormatter . Я предлагаю вам прочитать этот связанный вопрос SO , чтобы узнать, как это сделать. Помните, что номера телефонов форматируются по-разному в зависимости от местоположения и / или региона.

0
ответ дан 23 November 2019 в 21:42
поделиться

Это здорово, но код не работает для меня в iPhone 3.0 SDK.

Если я определю strippedString, как вы здесь показываете, я получаю ошибку ПЛОХОЙ ДОСТУП при попытке распечатать его после вызова scanCharactersFromSet: intoString .

Если я сделаю это так:

NSMutableString *strippedString = [NSMutableString stringWithCapacity:10];

Я получаю пустую строку, но код не падает.

Вместо этого мне пришлось прибегнуть к старому доброму C:

for (int i=0; i<[phoneNumber length]; i++) {
    if (isdigit([phoneNumber characterAtIndex:i])) {
        [strippedString appendFormat:@"%c",[phoneNumber characterAtIndex:i]];
    }
}
30
ответ дан 23 November 2019 в 21:42
поделиться

Гм. Первый ответ мне кажется совершенно неправильным. NSScanner действительно предназначен для парсинга. В отличие от регулярного выражения, в нем вы анализируете строку по одному крошечному фрагменту за раз. Вы инициализируете его строкой, и он поддерживает индекс того, как далеко продвинулся по строке; Этот индекс всегда является его точкой отсчета, и любые команды, которые вы ему даете, относятся к этой точке. Вы говорите ему: «Хорошо, дайте мне следующий кусок символов в этом наборе» или «дайте мне целое число, которое вы найдете в строке», и они начинаются с текущего индекса и продвигаются вперед, пока не найдут что-то, что не соответствие. Если самый первый символ уже не совпадает, тогда метод возвращает NO, и индекс не увеличивается.

Код в первом примере сканирует «(123) 456-7890» на предмет десятичных символов, который уже не работает с самого первого символа, поэтому вызов scanCharactersFromSet: intoString: оставляет переданную строку strippedString в покое и возвращает NO; Код полностью игнорирует проверку возвращаемого значения, оставляя strippedString неназначенным. Даже если бы первым символом была цифра, этот код не сработал бы, так как он вернул бы только цифры, которые он находил, до первого тире, парного знака или чего-то еще.

Если вы действительно хотите использовать NSScanner, вы можете поместить что-то подобное в цикле и продолжайте проверять, нет ли возвращаемого значения, и если вы получите это, вы можете увеличить scanLocation и сканировать снова; и вы также должны проверить isAtEnd и yada yada yada. Короче говоря, инструмент неподходящий для работы. Решение Майкла лучше.

оставляет переданную строку strippedString и возвращает NO; Код полностью игнорирует проверку возвращаемого значения, оставляя strippedString неназначенным. Даже если бы первым символом была цифра, этот код не сработал бы, так как он вернул бы только цифры, которые он находил, до первого тире, парного знака или чего-то еще.

Если вы действительно хотите использовать NSScanner, вы можете поместить что-то подобное в цикле и продолжайте проверять, нет ли возвращаемого значения, и если вы получите это, вы можете увеличить scanLocation и сканировать снова; и вы также должны проверить isAtEnd и yada yada yada. Короче говоря, инструмент неподходящий для работы. Решение Майкла лучше.

оставляет переданную строку strippedString и возвращает NO; Код полностью игнорирует проверку возвращаемого значения, оставляя strippedString неназначенным. Даже если бы первым символом была цифра, этот код не сработал бы, так как он вернул бы только цифры, которые он находил, до первого тире, парного знака или чего-то еще.

Если вы действительно хотите использовать NSScanner, вы можете поместить что-то подобное в цикле и продолжайте проверять, нет ли возвращаемого значения, и если вы получите это, вы можете увеличить scanLocation и сканировать снова; и вы также должны проверить isAtEnd и yada yada yada. Короче говоря, инструмент неподходящий для работы. Решение Майкла лучше.

поскольку он будет возвращать только цифры, которые он находит, до первого дефиса, парного знака или чего-то еще.

Если вы действительно хотите использовать NSScanner, вы можете поместить что-то подобное в цикл и продолжать проверять, нет ли возвращаемого значения, и если вы получите это, вы можете увеличить scanLocation и сканировать снова; и вы также должны проверить isAtEnd и yada yada yada. Короче говоря, инструмент неподходящий для работы. Решение Майкла лучше.

поскольку он будет возвращать только цифры, которые он находит, до первого дефиса, парного знака или чего-то еще.

Если вы действительно хотите использовать NSScanner, вы можете поместить что-то подобное в цикл и продолжать проверять, нет ли возвращаемого значения, и если вы получите это, вы можете увеличить scanLocation и сканировать снова; и вы также должны проверить isAtEnd и yada yada yada. Короче говоря, инструмент неподходящий для работы. Решение Майкла лучше.

0
ответ дан 23 November 2019 в 21:42
поделиться

Спасибо за пример. В нем отсутствует только одно приращение scanLocation на случай, если один из символов в originalString не найден внутри объекта NumberSettings. Я добавил оператор else {}, чтобы исправить это.

NSString *originalString = @"(123) 123123 abc";
NSMutableString *strippedString = [NSMutableString 
        stringWithCapacity:originalString.length];

NSScanner *scanner = [NSScanner scannerWithString:originalString];
NSCharacterSet *numbers = [NSCharacterSet 
        characterSetWithCharactersInString:@"0123456789"];

while ([scanner isAtEnd] == NO) {
  NSString *buffer;
  if ([scanner scanCharactersFromSet:numbers intoString:&buffer]) {
    [strippedString appendString:buffer];
  }
  // --------- Add the following to get out of endless loop
  else {
     [scanner setScanLocation:([scanner scanLocation] + 1)];
  }    
  // --------- End of addition
}

NSLog(@"%@", strippedString); // "123123123"
5
ответ дан 23 November 2019 в 21:42
поделиться
NSString *originalPhoneNumber = @"(123) 123-456 abc";
NSCharacterSet *numbers = [[NSCharacterSet characterSetWithCharactersInString:@"0123456789"] invertedSet];
NSString *trimmedPhoneNumber = [originalPhoneNumber stringByTrimmingCharactersInSet:numbers];

];

Будь проще!

-4
ответ дан 23 November 2019 в 21:42
поделиться
Другие вопросы по тегам:

Похожие вопросы: