我正试图找到一种方法来完成这项工作:
//Returns a pointer to the nth char in a string
const char *nth_strchr(const char *s, int c, int n) {
int c_count = 0;
char *nth_ptr;
while (c_count++ != n) {
nth_ptr = strchr(s, c);
//need a line here to skip past the previous found occurrence.
}
return nth_ptr;
}
我不太清楚我是如何做到的,因此while
循环的每次迭代都可以确认在前一循环中找到的char的出现/位置。因为我有指向第一次出现的指针......我正在考虑使用内存地址递增下一个循环,以便我可以给下一个strchr()
调用从c + 1
位置开始的字符串?
这有可能吗?
答案 0 :(得分:2)
const char* nth_strchr(const char* s, int c, int n)
{
int c_count;
char* nth_ptr;
for (c_count=1,nth_ptr=strchr(s,c);
nth_ptr != NULL && c_count < n && c!=0;
c_count++)
{
nth_ptr = strchr(nth_ptr+1, c);
}
return nth_ptr;
}
此代码已经过测试。
答案 1 :(得分:1)
显而易见的(?)方式当然是使用strchr()
的返回值作为新字符串,在将已知的事件添加到步骤之后添加1,是的。
类似的东西:
const char * nth_strchr(const char *s, int c, int n)
{
for (;;)
{
if (n <= 0)
return NULL;
const char *h = strchr(s, c);
if(h == NULL)
return NULL;
if (--n == 0)
return h;
s = h + 1;
}
return NULL;
}
答案 2 :(得分:1)
假设您在n
字符串中c
s
出现,而不是评论中所说的n
字符,那么这一行
s = nth_ptr + 1;
在s
c_count
c
s
出现后,在循环结束时会将strchr
指针前移到字符处。
请记住还要检查上面评论中提到的 tabHost.setOnTabChangedListener(new TabHost.OnTabChangeListener(){
@Override
public void onTabChanged(String tabId) {
int tab = tabHost.getCurrentTab();
tabHost.getTabWidget().getChildAt(tab).setBackgroundColor(Color.parseColor("#FFFFFF"));
setTabColor(tabHost);
}
});
}
public static void setTabColor(TabHost tabhost) {
for(int i=0;i<tabhost.getTabWidget().getChildCount();i++)
{
tabhost.getTabWidget().getChildAt(i).setBackgroundColor(Color.WHITE); //unselected
}
tabhost.getTabWidget().getChildAt(tabhost.getCurrentTab()).setBackgroundColor(Color.parseColor("#FFFFFF")); // selected
}
的返回值。
答案 3 :(得分:1)
我认为代码可以像这样简单,使用带有早期转义的计数(for
)循环,如果在n
中没有出现c
个字符s
字符串const char *nth_strchr(const char *s, int c, int n)
{
const char *nth = s;
assert(c != '\0');
for (int i = 0; i < n; i++)
{
if ((nth = strchr(nth, c)) == 0)
break;
nth++;
}
return nth;
}
:
break;
return 0;
可以替换为return NULL;
或== NULL
。条件可以是== 0
而不是i
。我假设至少C99;如果你没有那个,那么你需要在循环外定义void getNextCharByteLengthAndCodePoint(const char* ch, size_t& byteLength, char32_t& codePoint)
{
unsigned char firstByte(*ch);
//Check against 1000 0000 is the first byte set?
if ((firstByte & BIT_10000000) == 0)
{
// Codepoint is everything 0111 1111
codePoint = firstByte & BIT_01111111;
byteLength = 1;
}
//Check against 1110 0000 making sure we are 1100 0000
else if ((firstByte & BIT_11100000) == BIT_11000000)
{
// Codepoint is everything 0001 1111
codePoint = firstByte & BIT_00011111;
byteLength = 2;
}
//Check against 1111 0000 making sure we are 1110 0000
else if ((firstByte & BIT_11110000) == BIT_11100000)
{
// Codepoint is everything 0000 1111
codePoint = firstByte & BIT_00001111;
byteLength = 3;
}
//Check against 1111 1000 making sure we are 1111 0000
else if ((firstByte & BIT_11111000) == BIT_11110000)
{
// Codepoint is everything 0000 0111
codePoint = firstByte & BIT_00000111;
byteLength = 4;
}
else
{
throw std::runtime_error("Invalid UTF8 encoding");
}
for (int i = 1; i < byteLength; ++i)
{
//Go through the other 'byteLength' bytes and shift everything 6
codePoint = ((codePoint << 6) | (ch[i] & BIT_00111111));
}
}
。
断言是最迂腐的。如果不详细了解代码的使用方式,并且没有使其成为理智选项的上下文,则无法将指针递增到第一个null之外。
其他答案也有类似的净影响,但IMO的代码写得不那么清楚(这就是为什么我后来添加了答案)。将循环控件分布在三行上并在设置中使用多个赋值会使其难以阅读而不是需要。在调用计数循环时使用无限循环似乎是混淆。
答案 4 :(得分:1)
在您的代码中,您始终找到c
的第一个匹配项,如果s = nth_ptr + 1;
不是nth_ptr
,则应添加NULL
,但您应该为n == 0
做出特殊情况{1}}和/或c == '\0'
。
这是一个更简单的版本:
const char *nth_strchr(const char *s, int c, int n) {
if (c == '\0' && n > 1) /* special case the null terminator */
return NULL;
if (n > 0) {
while ((s = strchr(s, c)) != NULL && --n > 0) {
s++;
}
}
return s;
}
答案 5 :(得分:-1)
//尝试使用此程序
#include<stdio.h>
#include<string.h>
int main()
{
char *q,arr[]="This is strchr i program";
int i=0;
while((q=strchr(arr+i,'i'))!=NULL){
printf("%s\n",q);
i=(char *)q-(char *)arr;
i=i+1;
}
return 0;
}