更新1
在之前的更新基础上,我认为我对此做了更深入的了解,但我需要这个问题的答案。在当前的for
循环中,有一个名为tstring
的变量。我需要做类似以下的事情,但它不起作用。我收到错误Collection expression type 'NSString *' may not respond to countByEnumeratingWithState:objects:count:'
如何修复此for
条款?
for (NSUInteger i = 1; i < match.numberOfRanges; ++i)
{
NSRange matchedRange = [match rangeAtIndex: i];
NSString* tstring = [string substringWithRange: matchedRange];
for (char* suit in tstring){ // error here ********
NSLog(@"char: %@",suit);}
NSLog(@"range %lu string: %@", (unsigned long)i, tstring);
}
更新1
更新0
这是另一种方法,不需要搜索,但我仍然不知道如何在for循环的上下文中完成这种方法。
我需要一个字典,如下面的示意图,它将每张卡片(2到Ace)与0到12之间的整数相关联。(我想我知道如何在C中创建字典;也许不在objective-c中。)
┌─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬──┬──┬──┐
│0│1│2│3│4│5│6│7│8│9│10│11│12│
├─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼──┼──┼──┤
│2│3│4│5│6│7│8│9│T│J│Q │K │A │
└─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴──┴──┴──┘
我需要一个带有四个名词或数组的结构,我不确定哪个长度为13,每个都是这样的。这类似于原始结构,但现在成员是卡牌套装,而不是玩家的位置。
struct board {
int num;
char spade[13]
char heart[13]
char diamond[13]
char club[13]
};
假设以下交易的第1号董事会,
Q952.652.KJT4.95 T.KQT84.A865.J73 K8763.A7.Q.KQT84 AJ4.J93.9732.A62
我在代码的for循环中需要以下过程。
spade[10] = N
spade[7] = N
spade[3] = N
spade[0] = N
heart[4] = N
heart[3] = N
etc.
问题是,“你如何在for循环中进行处理?”
更新0
以下代码对我有用,但我需要将其更改为下面描述的目的。我的控制台输出(至少是开头)也在下面提供。从输出我需要以特殊方式保留范围1和范围4到19的结果。
下面的小表包含一个4乘4阵列的范围编号,行中标有黑桃,心,钻石,俱乐部和标有北,东,南和西的列。当选择心脏时,我需要搜索行H的内容以确定该卡是否在N,E,S或W中并报告结果。请注意,在表中,每个单元格的内容是一个字符串,其中不包含任何内容(为空)或来自“23456789TJQKA”的一组字母,并且每行中包含所有13个字母。表中的数字仅指当前输出中的范围编号。
N E S W
S 4 8 12 16
H 5 9 13 17
D 6 10 14 18
C 7 11 15 19
我想学习如何将结果存储在预期的搜索任务中。我可以创建一个C结构,每个成员包含整数板号(1到36之间的数字)和4个字符串吗?例如,下面的结构是否有效?如果确实如此,那么如何在objective-c中搜索这样的结构?我也可以在循环中使用一些帮助填充结构。
struct board {
int num;
char N[13]
char E[13]
char S[13]
char W[13]
};
代码摘录如下。
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:toMatch options:NSRegularExpressionDotMatchesLineSeparators error:&error];
NSLog(@"pattern length: %lu", (unsigned long)[toMatch length]);
NSUInteger numberOfMatches = [regex numberOfMatchesInString:string options:0 range:NSMakeRange(0, [string length])];
NSLog(@"number of matches: %lu", (unsigned long)numberOfMatches);
for (NSTextCheckingResult* match in [regex matchesInString:string options:NSRegularExpressionDotMatchesLineSeparators range:NSMakeRange(0, [string length])])
{
NSLog(@"Number of ranges in match: %u", match.numberOfRanges);
for (NSUInteger i = 0; i < match.numberOfRanges; ++i)
{
NSRange matchedRange = [match rangeAtIndex: i];
NSString* tstring = [string substringWithRange: matchedRange];
NSLog(@"range %lu string: %@", (unsigned long)i, tstring);
}
}
示例输出如下。
2013-02-04 16:24:06.583 [71684:11303] string length: 22365
2013-02-04 16:24:06.591 [71684:11303] pattern length: 347
2013-02-04 16:24:06.602 [71684:11303] number of matches: 36
2013-02-04 16:24:06.613 [71684:11303] Number of ranges in match: 20
2013-02-04 16:24:06.613 [71684:11303] range 0 string:
[Board "1"]
[West ""]
[North ""]
[East ""]
[South ""]
[Dealer "N"]
[Vulnerable "None"]
[Deal "N:Q952.652.KJT4.95 T.KQT84.A865.J73 K8763.A7.Q.KQT84 AJ4.J93.9732.A62"]
2013-02-04 16:24:06.613 [71684:11303] range 1 string: 1
2013-02-04 16:24:06.613 [71684:11303] range 2 string: N
2013-02-04 16:24:06.614 [71684:11303] range 3 string: None
2013-02-04 16:24:06.614 [71684:11303] range 4 string: Q952
2013-02-04 16:24:06.614 [71684:11303] range 5 string: 652
2013-02-04 16:24:06.614 [71684:11303] range 6 string: KJT4
2013-02-04 16:24:06.614 [71684:11303] range 7 string: 95
2013-02-04 16:24:06.614 [71684:11303] range 8 string: T
2013-02-04 16:24:06.614 [71684:11303] range 9 string: KQT84
2013-02-04 16:24:06.614 [71684:11303] range 10 string: A865
2013-02-04 16:24:06.615 [71684:11303] range 11 string: J73
2013-02-04 16:24:06.615 [71684:11303] range 12 string: K8763
2013-02-04 16:24:06.615 [71684:11303] range 13 string: A7
2013-02-04 16:24:06.615 [71684:11303] range 14 string: Q
2013-02-04 16:24:06.615 [71684:11303] range 15 string: KQT84
2013-02-04 16:24:06.616 [71684:11303] range 16 string: AJ4
2013-02-04 16:24:06.616 [71684:11303] range 17 string: J93
2013-02-04 16:24:06.616 [71684:11303] range 18 string: 9732
2013-02-04 16:24:06.616 [71684:11303] range 19 string: A62
答案 0 :(得分:0)
我觉得这个问题偏离了#34;我该如何做X?&#34;并开始非常接近&#34;请为我做X.&#34;也就是说,我昨晚做了一段时间的思考,我有一些想法可以分享,这可能会对你有所帮助。
首先,是的,这可以用任意数量的C结构建模。你已经探索了其中几个。有人认为你还没有建议使用位图代表手。甲板上有52张牌;存储指针的一种方法是使用64位整数,并使52位对应于卡片中的卡片。如果设置了与特定卡对应的位,则手包含特定卡。搜索这些指针然后变成一个简单的按位AND操作。你甚至可以通过界面获得创意,并使用C union
来使底层表示为64位类型,同时允许对子集(如套装或位置)进行结构化访问,或许可以说每个套装对应16位基础类型。
也就是说,考虑到这里设置数据的大小,进入性能问题的方法相对较少,在稍微咀嚼之后,我开始觉得要努力找到最好的或者是最快速的搜索&#39;数据结构构成了前期优化。即使你使这个应用程序的数据模型成为一个完整的Objective-C对象图,包括每个卡的每个位置,每个手,甚至每个卡的对象实例的类,你仍然在解决一个问题。 &#34;恒定大小&#34;问题(有机会&#34;恒定时间&#34;表现。)IIUC,游戏中牌组中不会超过52张牌,也不会超过4个牌位,也不会超过36张牌。这是一个相当受约束的问题。如果您计划导入数以万计的这些游戏,然后查询所有这些游戏,那么您选择的数据结构可能会开始变得重要,但此时(摄取一个游戏)我觉得非常有信心当我说任何Mac或者即使使用最强力的方法,iOS设备也可以毫不费力地消化这个问题并具有足够的性能。
接下来,我建议在解析[Deal "..."]
行的内容时放弃使用正则表达式。你能用正则表达式吗?当然。但是将引用的字符串作为const char*
(参见-[NSString UTF8String]
)然后按顺序遍历字符会更简单:第一个字符是[NSEW]
并标识第一个位置(很可能需要存储在你的结构中,但到目前为止缺失了)。然后一个无用的:
要忽略。然后开始读黑桃卡。当你达到.
增量时诉讼。当你点击<space>
增加位置时。你可以使用正则表达式来提取这些部分,但简单的方法是如此简单,我建议使用它。 (我应该提一下,考虑到上下文,这种更简单的方法也非常快,但我坚持认为,仅仅为了性能而选择这种方法将是预先成熟的优化。所以,不要选择这种方法来获得性能,选择它为简单起见!)
最后,我觉得我应该提一下,虽然我的2分钟google-fu未能找到开源,C PBN阅读实施(以及模型数据结构),但是我觉得很难相信那里没有一个人。我的搜索有点复杂,因为#34; bridge&#34;是这样一个超载的英文单词。我可能会建议嗅探更多,看看你是否可以找到一个成熟的开源实现,既可以按原样使用,也可以作为灵感,而不是自己动手。
编辑:
我写了一个可能的循环来填充你建议的结构:
// Your structure, but as a typedef for clarity.
typedef struct {
int num;
char spade[13];
char heart[13];
char diamond[13];
char club[13];
} board;
// The quoted string in the [Deal "..."] line; you already know how to get this.
NSString* dealString = @"N:A8.J762.KQ742.98 KQ53.K93.A85.T52 J97.A8.J963.J743 T642.QT54.T.AKQ6";
// Set up some arrays to use as maps between ints and chars...
// ...for positions:
const char* const positionIntToCharMap = "NESW";
int positionCharToIntMap['Z'] = { 0 };
for (int i = 0, len = (int)strlen(positionIntToCharMap); i < len; ++i) positionCharToIntMap[positionIntToCharMap[i]] = i;
// and cards:
const char* const cardIntToCharMap = "23456789TJQKA";
int cardCharToIntMap['Z'] = { 0 };
for (int i = 0, len = (int)strlen(cardIntToCharMap); i < len; ++i) cardCharToIntMap[cardIntToCharMap[i]] = i;
// and suits:
const char* const suitIntToCharMap = "SHDC";
int suitCharToIntMap['Z'] = { 0 };
for (int i = 0, len = (int)strlen(suitIntToCharMap); i < len; ++i) suitCharToIntMap[suitIntToCharMap[i]] = i;
const char* dealCString = [dealString UTF8String];
const size_t dealCStringLen = strlen(dealCString);
board thisBoard = { 0 };
if (dealCStringLen)
{
char suit = 'S'; // start with spades
char pos = dealCString[0]; // first character is starting position
for (off_t i = 1; i < dealCStringLen; ++i)
{
if (dealCString[i] == ':')
{
continue;
}
else if (dealCString[i] == '.') // advance the suit
{
const int currentSuitInt = suitCharToIntMap[suit];
const int nextSuitInt = (currentSuitInt + 1) % 4;
suit = suitIntToCharMap[ nextSuitInt ];
}
else if (dealCString[i] == ' ') // advance the position and reset the suit
{
const int currentPosInt = positionCharToIntMap[pos];
const int nextPosInt = (currentPosInt + 1) % 4;
pos = positionIntToCharMap[ nextPosInt ];
suit = 'S';
}
else // read the card
{
const char charForCard = dealCString[i];
const int intForCard = cardCharToIntMap[charForCard];
// Mark the current position in the appropriate array.
if (suit == 'S')
{
thisBoard.spade[intForCard] = pos;
}
else if (suit == 'H')
{
thisBoard.heart[intForCard] = pos;
}
else if (suit == 'D')
{
thisBoard.diamond[intForCard] = pos;
}
else if (suit == 'C')
{
thisBoard.club[intForCard] = pos;
}
}
}
}
// thisBoard is now populated.
我希望这会有所帮助。