如何将NSString从索引解析为索引?

时间:2012-11-07 00:00:06

标签: ios nsstring nsrange

我想解析一个这样的字符串:
NSString *str = @"firstcolumn second column text Third Column Text";

我有三列文字,每列可以是带空格的文字 我知道列有多宽,col1 = 10个字符长,col2 = 20,col3 = 30
我知道我可以使用NSRange(0,len1),(10,len2),(20,len3)。

我发现崩溃“超出范围”错误,因为长度不同,列文本的长度不必达到其最大限制。

任何想法如何做到这一点?

NSString *str = @"A000 B11 This is text description This column is a longer Text description"; 
//A000 column can be 10 chars long
//B11 can be 20 chars
//This is some text description can be 30 characters long
 NSString *code1 = [line substringWithRange:NSMakeRange(0,10)];
 NSString *code2 = [line substringWithRange:NSMakeRange(10,20)];
 NSString *shorttext = [line substringWithRange:NSMakeRange(20,20)];
 NSString *longtext = [line substringWithRange:NSMakeRange(30,30)];

我想在上面的例子中得到code1 = A000,这个长度可以是10个字符长,但不一定要如你所见。同样,其他2列,代码2和文本。 我怎么能这样做?

1 个答案:

答案 0 :(得分:1)

如果我理解正确,您有一个输入NSString str,其中包含三个连接的字符串:col1col2col3。此外,您知道以下关于问题的限制

  • col1介于0到10个字符之间
  • col2介于0到20个字符之间
  • col3介于0到30个字符之间

并希望从str恢复这些字符串。换句话说,您希望唯一确定col1col2col3,以便str等于

[NSString stringWithFormat:@"%@%@%@", col1, col2, col3];

不幸的是,正如其他人所评论的那样,如果不修改问题,这是不可能的。要了解原因,请考虑

的情况
str = @"a";

在这种情况下,您知道其中一个组件字符串(col1col2col3)等于@"a",其他两个等于@""。但是,无法确定哪个。例如,如果col1 = @"a"col2以及col3都等于@"";然后

[NSString stringWithFormat:@"%@%@%@", col1, col2, col3]

评估为

@"a"

根据需要。但是,如果col1col2等于@""col3 = @"a",则情况也是如此

[NSString stringWithFormat:@"%@%@%@", col1, col2, col3]

仍然评估为

@"a"

这里的问题不是组件字符串能够为空,而是它们能够在一定范围内变化。

如果我们约束问题以使长度准确

  • col1,长度为10个字符
  • col2,长度为20个字符
  • col3,长度为30个字符

然后可以使用以下函数恢复str

void GetColumnsFromString(NSString *str, NSString * __autoreleasing *col1, NSString * __autoreleasing *col2, NSString * __autoreleasing *col3)
{
    if (col1) {
        *col1 = [str substringWithRange:NSMakeRange(0, 10)];
    }
    if (col2) {
        *col2 = [str substringWithRange:NSMakeRange(10, 20)];
    }
    if (col3) {
        *col3 = [str substringWithRange:NSMakeRange(30, 30)];
    }
}

如评论中所提到的,另一个更好的解决方案是在str中使用“特殊”字符来划分组件字符串之间的边界。如果我们像这样构建str

str = [NSString stringWithFormat:@"%@%@%@", col1, col2, col3];

我们限制col1col2以及col3不包含字符,然后我们可以解析col1col2如下:

NSArray *cols = [str componentsSeparatedByString:@""];
col1 = cols[0];
col2 = cols[1];
col3 = cols[2];

如果使用空格字符代替字符,情况就没有区别了。

编辑:您添加了有关输入字符串和所需输出的更多信息:

而不是三个,有四个组件字符串:col1col2col3col4。我们有一些关于它们的信息:

  • col1长度介于0到10个字符之间
  • col1不包含空格字符
  • col2长度介于0到20个字符之间
  • col2不包含空格字符
  • col3长度介于0到30个字符之间
  • col3 MAY 包含空格字符
  • col4的长度不受限制
  • col4 MAY 包含空格字符

此外,四个字符串在它们的串联中用空格分隔。因此,您的目标是唯一确定col1col2col3col4,以便str等于

[NSString stringWithFormat:@"%@ %@ %@ %@", col1, col2, col3, col4];

在这种情况下,您可以使用NSScanner提取col1col2

NSScanner *scanner = [NSScanner scannerWithString:str];
NSCharacterSet *spaceCharacterSet = [NSCharacterSet characterSetWithCharactersInString:@" "];
NSString *col1 = nil, *col2 = nil;
[scanner scanUpToCharactersFromSet:spaceCharacterSet intoString:&col1];
[scanner scanUpToCharactersFromSet:spaceCharacterSet intoString:&col2];

此时,可以提取包含由空格分隔的两个最终字符串remaindercol3的字符串col4

NSCharacterSet *emptyCharacterSet = [NSCharacterSet characterSetWithCharactersInString:@""];
NSString *remainder = nil;
[scanner scanUpToCharactersFromSet:emptyCharacterSet intoString:&remainder];

此时,你又回到了我在开头所描述的那种情况。您有一个字符串(remainder),它由两个由空格分隔的组件字符串(col3col4)组成。检测这两个字符串之间边界的唯一方法就是空格。

但是,col3 可能包含空格。如果不能,那么您可以直接扫描直到到达下一个空格,并将开头和该空间之间的内容提取到col3,其余的提取到col4

此外,col4 也可能包含空格。如果不能,那么您可以从remainder的末尾扫描,直到达到结束的第一个空格,将该范围提取到col4,其余范围提取到col3