Каков самый маленький код, который я могу использовать для подсчета числа вхождений символа новой строки в файле с привязкой object-c/cocoa?Подсчитайте количество строк новой строки в файле
Спасибо!
Каков самый маленький код, который я могу использовать для подсчета числа вхождений символа новой строки в файле с привязкой object-c/cocoa?Подсчитайте количество строк новой строки в файле
Спасибо!
Оба других ответа верны, но с предостережением, что они требуют загрузки всего файла в память для работы.
Способ загрузки файлов с помощью NSFileHandle
. Что-то вроде этого:
NSFileHandle * file = [NSFileHandle fileHandleForReadingAtPath:pathToFile];
NSUInteger chunkSize = 1024;
NSData * chunk = [file readDataOfLength:chunkSize];
NSUInteger numberOfNewlines = 0;
while ([chunk length] > 0) {
const unichar * bytes = (const unichar *)[chunk bytes];
for (int index = 0; index < [chunk length]; ++index) {
unichar character = (unichar)bytes[index];
if ([[NSCharacterSet newlineCharacterSet] characterIsMember:character]) {
numberOfNewlines++;
}
}
chunk = [file readDataOfLength:chunkSize];
}
Это должно вас происходит:
NSString *fileContents = [NSString stringWithContentsOfFile:file encoding:encoding error:&error];
NSUInteger newlineCount = [fileContents numberOfOccurrencesOfString:@"\n"];
@interface NSString()
- (NSUInteger)numberOfOccurrencesOfString:(NSString *)aString;
- (NSUInteger)numberOfOccurrencesOfChar:(char)aChar;
@end
@implementation NSString()
- (NSUInteger)numberOfOccurrencesOfString:(NSString *)aString {
NSRange range = [self rangeOfString:aString];
NSUInteger length = [self length];
NSUInteger count = 0;
while (range.location != NSNotFound) {
range = [self rangeOfString:aString options:0 range:NSMakeRange(range.location + range.length, length - range.location - range.length)];
count++;
}
return count;
}
- (NSUInteger)numberOfOccurrencesOfChar:(char)aChar {
const char *cString = [self cStringUsingEncoding:NSUTF8StringEncoding];
NSUInteger stringLength = strlen(cString);
NSUInteger count = 0;
for (int i = 0; i < stringLength; i++) {
if (cString[i] == aChar) {
count++;
}
}
return count;
}
@end
В то время как «numberOfOccurrencesOfString:» не выделяет никакой дополнительной памяти и поддерживает строковые иглы, «numberOfOccurrencesOfChar:» выделяет autoreleased с-струнный копию NSString и ищет одиночный знак. ""
Как вы просили подсчет новых строк (отсюда и одиночные символы), я решил, что быстрый результат может быть хорошим для этой конкретной цели: Итак, я взял тестовую строку длиной 2486813, содержащую всего 78312 '\ n ». (Я в основном взял вариацию файла слов OSX) и ... ... ran [testString numberOfOccurrencesOfString: @ "\ n"] 100 раз: 19.35s ... ran [testString numberOfOccurrencesOfChar: '\ n'] 100 раз: 6.91s (Настройка: 2,2 ГГц Core 2 Duo MacBook Pro, работающий на одной нити)
[Изменить: исправлена небольшая ошибка; . Сделал второй фрагмент кода в метод категории строки]
За исключением ..... Откуда берется «testRange»? –
Упс, исправлено. Релиз из версии до того, как я затянул код;) – Regexident
Вы можете сканировать через строку, используя SubstringWithRange:
Подсчитайте число раз \ п появляется.
Вы имеете в виду [string substringWithRange: NSMakeRange (i, 1)] для i = 0 ... n? с "isEqualToString: \ n"? Это создало бы автореализованную подстроку с одним символом для каждого отдельного символа. Нехорошо и сравнительно медленно. Но я думаю, вы, вероятно, имели в виду «rangeOfString:»;) См. Мой ответ, используя его. – Regexident
Правда. Я не считал память подстрокиWithRange:. rangeOfString: будет иметь такой же эффект. Но я пытался избежать выполнения домашнего задания OPs. Извините, если это не так, но чтение между строками похоже на это. –
Истинный момент. Я просто подумал, что в любом случае мне понадобится его в собственном проекте, и, таким образом, он не слишком беспокоился: P – Regexident
наименьший вы говорите? Это автоматически превращает этот вопрос в код гольф
FILE*f=fopen(path,"r");
int i,c;
while(1+c)i+=(c=fgetc(f))==10;
printf("%i",i);
(пожалуйста, не когда-либо фактически использовать этот код)
Если Вы хотите остановиться в Cocoa/CocoaTouch, вы можете использовать NSRegularExpression для этого:
NSString *theString = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:&error];
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"\\n" options:NSRegularExpressionCaseInsensitive error:&error];
NSUInteger numLines = [regex numberOfMatchesInString:theString options:0 range:NSMakeRange(0, [theString length])] + 1;
Хороший! На самом деле я просто упустил из виду, откуда Фред получал струну. Шахта универсальна для подсчета подстроки, но, как ответ на самый вопрос о Фреде, ваш выбор - лучший выбор.Компилятор выдает ошибку на «(unichar) байтах [index];» для меня, хотя (ошибка: «Значение Void не игнорируется, как должно быть»), и по какой-то неизвестной и жуткой причине количество чисел меняется для меня при каждом прогоне и слишком низкое (по величине). O_o – Regexident
Btw, поскольку [fileHandle readDataOfLength: length] должен возвращать автореализованные NSData (документы не содержат исключения, поэтому я должен предположить, что это происходит, по соглашению об именах), вы в конечном итоге получите столько же данных в памяти, учитывая, что в вашем коде на данный момент нет NSAutoreleasePool внутри цикла while. поправьте меня если я ошибаюсь. – Regexident
@Regexident WRT ошибка: индексирование в 'void *' приводит к 'void', поэтому ответ будет заключаться в использовании другого типа массива (отредактированный ответ). Память WRT: да, вероятно, вы должны создавать и сливать пулы автозапуска, чтобы сохранить использование памяти. –