刚才发现c++的string实在太恶心了。
从今天开始,还是改用字符数组,于是学习一下cstring库的常用函数,以便于处理字符数组。
不过因为自己太弱,所以会写的很简短,一些lkb觉得无关紧要的东西就没有写上了,基本上就是记录给lkb自己看的233。
同学们如果要严谨的学习,还是看网上其他资料。
另外,下列每项操作的实现应该都不止lkb列出来的几个函数,只列了自己比较喜欢用的。
strcpy
的作用是复制整个字符数组到另一个字符数组,因此也就非常简洁,只有两个参数:
char * strcpy ( char * destination, const char * source );
读变量名就可以知道,前一个是要复制到的目标数组起始位置,后一个是被复制的源数组起始位置。
它的使用也非常简单,下面就用一个例子来说明:
int main () {
char str1[] = "Sample string";
char str2[40];
char str3[40];
strcpy (str2, str1);
strcpy (str3, "copy successful");
printf ("str1: %s\nstr2: %s\nstr3: %s\n", str1, str2, str3);
return 0;
}
程序运行后输出如下:
str1: Sample string
str2: Sample string
str3: copy successful
strncpy
与strcpy
很类似,只是可以指定复制多少个字符。它的原型是:
char * strncpy ( char * destination, const char * source, size_t num );
显然前两个参数的含义与strcpy
相同,第三个参数num
就是要复制的字符个数。理解了之后使用起来也就很容易了:
int main () {
char str1[] = "To be or not to be";
char str2[40];
char str3[40];
/* 整个字符串进行复制: */
strncpy ( str2, str1, sizeof(str2) );
/* 部分复制(这里是复制5个字符): */
strncpy ( str3, str2, 5 );
str3[5] = '\0'; /* 添加结尾符 */
puts (str1);
puts (str2);
puts (str3);
return 0;
}
从上面的例子可以看出,strncpy
因为是部分复制,所以不会帮你添加’\0’,要记得在调用完之后自己添加一个。
程序运行输出结果如下:
To be or not to be
To be or not to be
To be
strcat
的功能是把一个字符数组连接到另一个字符数组的后面(本人理解)。它的原型:
char * strcat ( char * destination, const char * source );
前一个是目标数组,后一个是要添加到后面的源数组。
举个栗子:
int main () {
char str[80];
strcpy (str, "these ");
strcat (str, "strings ");
strcat (str, "are ");
strcat (str, "concatenated.");
puts (str);
return 0;
}
输出结果是:
these strings are concatenated.
根据strcpy
和strncpy
之间的关系,应该不难猜想strca
t和strncat
之间的关系。没错,也是连接,也是可以指定字符个数。原型是:
char * strncat ( char * destination, const char * source, size_t num );
参数跟前面的套路是一样的,这里就不重复了。
还是举个例子吧:
int main () {
char str1[20];
char str2[20];
strcpy (str1, "To be ");
strcpy (str2, "or not to be");
strncat (str1, str2, 6);
puts (str1);
return 0;
}
输出结果:
To be or not
对两个字符数组我们可不能直接if (s > t)
这样比较,要知道这样比较的可是两个字符数组的指针的地址。
那么,我们就要用到strcmp
函数。它的原型是:
int strcmp ( const char * str1, const char * str2 );
两个参数是要比较大小的字符数组,返回值是它们的大小关系。
也就是说,设这两个字符串分别为 str1 和 str2 ,那么就有:
在这里的比较方式是:两个字符串自左向右逐个字符相比(按ASCII值大小相比较),直到出现不同的字符或遇’\0’为止。
一个使用的例子是:
int main () {
char key[] = "apple";
char buffer[80];
do {
printf ("Guess my favorite fruit? ");
fflush (stdout);
scanf ("%79s",buffer);
} while (strcmp (key,buffer) != 0);
puts ("Correct answer!");
return 0;
}
输出:
Guess my favourite fruit? orange
Guess my favourite fruit? apple
Correct answer!
strchr
函数可以在一个字符数组里找某个字符第一次出现的位置,它的原型是:
const char * strchr ( const char * str, int character );
显然前一个是原字符数组,后一个是要查找的字符。
给出一个使用的例子:
int main () {
char str[] = "This is a sample string";
char * pch;
printf ("Looking for the 's' character in \"%s\"...\n", str);
pch = strchr(str, 's');
while (pch ! =NULL) {
printf ("found at %d\n", pch - str + 1);
pch = strchr(pch + 1, 's');
}
return 0;
}
输出:
Looking for the ‘s’ character in “This is a sample string”…
found at 4
found at 7
found at 11
found at 18
strstr
函数可以在一个字符数组里查找另一个字符数组第一次出现的位置。它的原型是:
const char * strstr ( const char * str1, const char * str2 );
其中前一个是文本串,后一个是模式串。
给出一个使用的例子:
int main () {
char str[] = "This is a simple string";
char * pch;
pch = strstr (str, "simple");
strncpy (pch, "sample", 6);
puts (str);
return 0;
}
输出:
This is a sample string
memset
是一个非常好用的函数,不仅在字符串方面。它可以把连续一段区间的内存修改成同一个值,以字节为单位。
而一个字符正好就是一个字节,这也就让memset
可以很好的为字符串的区间修改提供服务。
memset
函数的原型是:
void * memset ( void * ptr, int value, size_t num );
ptr
指向要修改的内存块的起始地址,value
是要修改成什么值,num
是修改多少个。
给出一个使用的例子。
int main () {
char str[] = "almost every programmer should know memset!";
memset (str, '-', 6);
puts (str);
return 0;
}
输出:
—— every programmer should know memset!
strlen
用于求一个字符数组的长度,注意它是从给定的起始位置开始不断往后尝试,直到遇到’\0’为止的,因此它的时间复杂度并不是常数级别的,而是取决于字符数组的长度,在字符数组没有变动的情况下请务必不要重复调用。
该函数的原型如下:
size_t strlen ( const char * str );
那么参数毋庸置疑自然就是要求长度的字符数组了。
使用的例子如下:
int main () {
char szInput[256];
printf ("Enter a sentence: ");
gets (szInput);
printf ("The sentence entered is %u characters long.\n", (unsigned)strlen(szInput));
return 0;
}
输出的结果如下:
Enter sentence: just testing
The sentence entered is 12 characters long.
字符数组的处理函数,记得起来的暂时就先写这么多,以后等想到再补充。
之前一直没有注意,但c++的string效率实在太低了,非万不得已的情况下一定不能用。(其实,能用string实现的操作也必能通过手写实现对字符数组的相应操作。)
反正,用字符数组而不是string,用字符数组而不是string,用字符数组而不是string。
重要的事情说三遍。