XPCOM中的字符串类可以用操作做宽字节(16bit)和窄字节字符串。
宽字节和窄字节字符串基类是分开的,但是它们提供的接口是一致的。而对于每一个宽字节的实现类,都有一个类似的窄字节实现类。
Naming convention for wide and narrow string classes
Wide |
Narrow |
nsAString |
nsACString |
nsString |
nsCString |
nsAutoString |
nsCAutoString |
etc... |
抽象基类
所有的字符串类都是从nsAString
/nsACString这两个抽象基类派生。
nsAString
/nsACString提供了一些访问和操作字符串的基本方法。这两个类的命名模仿了Mozilla对于接口的命名,(Mozilla的接口命名中使用I来表示接口,如nsISupports),A表示“Abstract”。
下面是对字符串体系中主要类的总体描述:
nsAString
/nsACString: 所有字符串类的基类,定义了xpcom中字符串的基本操作,如赋值、字符存取、基本的字符操作,比较等。nsAString 可以不必是以null(\0)结尾的。
(nsAString is not necessarily null-terminated.)
nsString
/nsCString: 从以上两个基类继承而来,可以保证字符串是以null结尾。这两个类允许通过get()方法获取c风格的字符串(以'\0'结尾的字符数组)。
以为所有的字符串类都是从两个基类继承而来的,因为它们共享一些基本的API接口,如一些简单的只读函数:
.Length()
- 字符串字符数目 (对于窄字符串类字符是char对于宽字节来说是PRUnichar
)。
.IsEmpty()
- 最快的可以判断字符串为空的方法. 用这个方法来代替 string.Length
== 0
.Equals(string)
- 判定两个字符串内容相同.
一些简单的改变字符串的方法:
-
.Assign(string)
- 用string的值给字符串赋值.
-
.Append(string)
- 追加string到字符串.
-
.Insert(string, position)
- 在给定位置(position
)的字符前插入string.
-
.Truncate(length)
- 将字符串缩短到length指定的长度.
只读字符串
c++的const修饰符可以指定一个字符串类是否可写。 如果一个字符串被指定为const,并且视图调用一个non-const的方法,编译器将会给出一个错误。
For example:
void nsFoo::ReverseCharacters(nsAString& str) {
...
str.Assign(reversedStr); // modifies the string
}
而下面的代码将不能通过编译, 因为你为一个静态的对象进行赋值了:
void nsFoo::ReverseCharacters(const nsAString& str) {
...
str.Assign(reversedStr);
}
xpcom字符串类继承结构

-
nsString / nsCString
- 一个以null结尾的字符串,数据在堆(heap)上分配,在对象析构的时候会把数据也给干掉。
-
nsAutoString / nsCAutoString
- 拥有一个64个字符的缓冲区,缓冲区和字符串类本身位于同一存储空间。如果为之类字符串赋一个小于64个字符的值,它会使用它本身的缓冲区,如果超过64字符,它会在对上分配一个新的缓冲区。
-
nsXPIDLString / nsXPIDLCString
- 这类字符串支持通过getter_Copies()
方法获取wstring / string。
这类字符串同样支持空缓冲区( nsString的
buffer永远不会为null)。
-
nsDependentString
- 这个字符串永远都不会有自己的buffer。 当把一个原生的字符串转化成(const PRUnichar*
or const char*
) nsAString类型的时候特别有用。注意你的字符串必须是以null结尾的
,如果不是使用 nsDependentSubstring。
-
nsPrintfCString
- 类似于 nsCAutoString。
它的构造函数可以接受 printf
-style的参数来格式化一个字符串。
-
NS_LITERAL_STRING/NS_NAMED_LITERAL_STRING
- 它们可以把常量字符串(such as "abc") 转化成一个nsString或者
nsString的子类型。
在支持双字节的平台上 (e.g., MSVC++ or GCC with the -fshort-wchar option), 它们是一些类似nsDependentString使用方式的简单的宏。
但是很显然宏比包装成nsDependentString要快很多。
Iterators
因为Mozilla中的字符串是一个单一的buffer,所以可以利用原生指针来完成迭代:
/**
* Find whether there is a tab character in `data`
*/
bool HasTab(const nsAString& data)
{
const PRUnichar* cur = data.BeginReading();
const PRUnichar* end = data.EndReading();
for (; cur < end; ++cur) {
if (PRUnichar('\t') == *cur)
return true;
}
return false;
}
注意end指向字符串结束字符的下一个位置,因为永远不要“提领”end指针.
向一个可变的字符串中写入也很容易:
/**
* Replace every tab character in `data` with a space.
*/
void ReplaceTabs(nsAString& data)
{
PRUnichar* cur = data.BeginWriting();
PRUnichar* end = data.EndWriting();
for (; cur < end; ++cur) {
if (PRUnichar('\t') == *cur)
*cur = PRUnichar(' ');
}
}
可以通过SetLength()来改变字符串的长度。
需要注意的是如果要增加一个字符串长度的话可能会失败 (如没有足够的内存), 如果调用失败的话,字符串会简单的保持它的缓冲区和长度不变; 因此需要调用Length()方法看SetLength()是否成功. 同样要注意的是SetLength()成功以后迭代器指针将会失效:
/**
* Replace every tab character in `data` with four spaces.
*/
void ReplaceTabs2(nsAString& data)
{
int len = data.Length();
PRUnichar *cur = data.BeginWriting();
PRUnichar *end = data.EndWriting();
// Because `cur` may change during the loop, track the position
// within the string.
int pos = 0;
while (cur < end) {
if (PRUnichar('\t') != *cur) {
++pos;
++cur;
} else {
len += 3;
data.SetLength(len);
if (data.Length() != len)
// error handling goes here!
// After SetLength, read `cur` and `end` again
cur = data.BeginWriting() + pos;
end = data.EndWriting();
// move the remaining data over
if (pos < len - 1)
memmove(cur + 4, cur + 1, (len - 1 - pos) * sizeof(PRUnichar));
// fill the tab with spaces
*cur = PRUnichar(' ');
*(cur + 1) = PRUnichar(' ');
*(cur + 2) = PRUnichar(' ');
*(cur + 3) = PRUnichar(' ');
pos += 4;
cur += 4;
}
}
}
如果在写入一个字符串的时候字符串的buffer变小了,用SetLength来通知你的对象:
/**
* Remove every tab character from `data`
*/
void RemoveTabs(nsAString& data)
{
int len = data.Length();
PRUnichar* cur = data.BeginWriting();
PRUnichar* end = data.EndWriting();
while (cur < end) {
if (PRUnichar('\t') == *cur) {
len -= 1;
end -= 1;
if (cur < end)
memmove(cur, cur + 1, (end - cur) * sizeof(PRUnichar));
} else {
cur += 1;
}
}
data.SetLength(len);
}
帮助类和函数
搜索一个字符串
FindInReadable()
用来替代老的string.Find(..)函数:
PRBool FindInReadable(const nsAString& pattern,
nsAString::const_iterator start, nsAString::const_iterator end,
nsStringComparator& aComparator = nsDefaultStringComparator());
start
和end指向搜索的起点和终点。
如果搜索成功, start和
end将会指向找到的字串的起点和终点。
函数返回PR_TRUE或PR_FALSE来指示搜索是否成功。
An example:
const nsAString& str = GetSomeString();
nsAString::const_iterator start, end;
str.BeginReading(start);
str.EndReading(end);
NS_NAMED_LITERAL_STRING(valuePrefix, "value=");
if (FindInReadable(valuePrefix, start, end)) {
// end now points to the character after the pattern
valueStart = end;
}
内存分配
从一个已经存在的字符串类分配一个新的字符buffer(意思是你得到一个新的c-style字符指针或数组,这个c-style的字符指针或数组里面字符的值和字符串类相等,当然如果这样的话意味着您得自己去释放这部分内存)的首选方法如下:
-
PRUnichar* ToNewUnicode(nsAString&)
- 从nsAString分配PRUnichar*
buffer 。
-
char *ToNewCString(nsACString&)
- 从nsACString分配char*
buffer。需要注意的是这个函数也可以接受nsAString参数,但是这个时候会进行有损失的转化,所以最好在知道所转化的字符串是ASCII编码的情况下使用此函数。
-
char* ToNewUTF8String(nsAString&)
- 从一个 UTF-8编码的nsAString上分配char*
buffer。
这些函数返回的buffer是通过XPCOM的allocator分配空间的(不使用malloc等)。所以必须使用NS_Free来释放其内存。
子串(string fragments)
如果不需要重新分配空间并拷贝字符到新空间的话,或者一个字符串的字串是很容易的。 Substring()方法是完成这一工作的首选:
void ProcessString(const nsAString& str) {
const nsAString& firstFive = Substring(str, 0, 5); // from index 0, length 5
// firstFive is now a string representing the first 5 characters
}
分享到:
相关推荐
- **string**: 专门处理字符串的库,提供高效和灵活的字符串操作函数,支持Unicode编码。 - **pref**: 用于处理用户偏好设置的库。XPCOM组件可以通过这个库读取和修改用户设置,实现个性化功能。 - **xpcom**: ...
契约ID则是用于标识组件的唯一字符串,它是查找和加载组件的关键。 3. **XPCOM服务**:在XPCOM中,服务是一种特殊的组件,它们是单例的,即在应用程序的整个生命周期中只存在一个实例。通过XPCOM服务,开发者可以...
- 实现该功能的一个简单方法是遍历字符串,将不匹配的字符复制到一个新的缓冲区,然后用新的字符串替换原字符串。 - 示例代码: ```c #include #include void delete_char(char *str, char ch) { int i, j...
10. **题目**: 给定一个字符串 "ABCDE",求其所有可能的排列组合。 - A. EDCBA - B. DECA - C. DCBA - D. CDEA - E. ABCDE **知识点**: - 字符串的排列组合可以通过递归算法实现。 - 对于长度为 n 的字符...
**解析**:字符串ABCDE的逆序结果应该是EDCBA。 以上是根据给定的文件摘要整理的C语言笔试题知识点解析。这些题目涵盖了C语言的基础语法、数据类型、内存管理、函数、算法、网络协议等多个方面,旨在全面考察应试者...
// 加1是为了存储字符串结束符 if(errstr == NULL) // 修复错误的条件判断 return -1; strncpy(errstr, __err[index], len+1); // 使用len+1防止溢出 } else errstr = __err + index; } ``` 通过这些题目,...
5. **nprt.rc**: 资源脚本文件,用于定义插件的资源,如图标、字符串等,这些资源可以在程序运行时使用。 6. **__history**: 这可能是文本编辑器的版本历史记录,通常不直接参与编译过程,但可能包含有关代码修改的...
6. **正则表达式理解**:正则表达式用来匹配特定格式的字符串,考察对正则语法的理解。 7. **C语言代码分析**:这通常涉及程序错误检测,如空指针、数组越界、资源泄漏等问题。 8. **算法题**:通常这类题目会给出...