爆肝一个假期的笔记补档。
这个月可能会发十几二十几篇吧。
这个是目录)
什么是字符串
"hello world.\n"
- 这种由双引号引起来的一串字符称为字符串字面值,或者简称字符串。
C语言中对字符和字符串的处理很是频繁,但是C语言本身是没有字符串类型的,字符串通常放在常量字符串中或者字符数组中。
字符串常量 适用于那些对它不做修改的字符串函数。
注:字符串的结束标志是一个 \0 的转义字符。在计算字符串长度的时候 \0 是结束标志,不算作字符串内容。
没有结束标志会出现奇妙的事件
关于‘\0’的认识
- ‘\0’不属于字符串的内容,属于字符串的结束分隔符。
- 字面值就是0,占一个字节。
‘\0’和‘0’是有区别的,‘0’是字符0,ASCII码值是48。
strlen
size_t strlen ( const char * str );
strlen的标准引用
-
字符串的末尾已经含有’\0’了strlen返回的是’\0’前的字符数
-
参数指向的字符串必须要以’\0’结束
-
注意函数的返回值为size_t是无符号的包括计算也是无符号的(易错)
#include<stdio.h> #include<string.h> int main() { const char*str1 = "abcdef"; const char*str2 = "bbb"; if(strlen(str2)-strlen(str1)>0) { printf("str2>str1\n"); } else { printf("srt1>str2\n"); } return 0; } //答案是str2>str1因为计算值也是无符号的
模拟实现:
//模拟实现strlen,普通计数器法 size_t my_strlen(char* arr) { size_t count = 0; while (*arr) { count++; arr++; } return count; } //递归实现 size_t my_strlen(char* arr) { if (!(*arr)) { return 0; } else { return 1 + my_strlen(arr + 1); } } //指针相减 size_t my_strlen(char* arr) { char* ret = arr; while (*ret++) { ; } return (ret - arr-1); }
strcpy
char* strcpy(char * destination, const char * source );
-
源字符串必须以 ‘\0’ 结束。
-
Copies the C string pointed by source into the array pointed by destination, including the terminating null character (and stopping at that point).
-
会将源字符串中的 ‘\0’ 拷贝到目标空间。 目标空间必须足够大,以确保能存放源字符串。
-
目标空间必须可变。
模拟实现:
char *my_strcpy(char *dest, const char*src)
{
char *ret = dest;
assert(dest && src );
while((*dest++ = *src++))
{
;
}
return ret;
}
strcat
char * strcat ( char * destination, const char * source );
-
Appends a copy of the source string to the destination string. The terminating null character in destination is overwritten by the first character of source, and a null-character is included at the end of the new string formed by the concatenation of both in destination.
-
源字符串必须以 ‘\0’ 结束。 目标空间必须有足够的大,能容纳下源字符串的内容。
-
目标空间必须可修改。
-
字符串自己给自己追加,如何?会死循环。
模拟实现:
char* my_strcat(char* Dis, char* Sor)
{
char* ret = Dis;
assert(Dis && Sor);
while (*Dis)
{
Dis++;
}
while (*Dis++ = *Sor++)
{
;
}
return ret;
}
strcmp
int strcmp ( const char * str1, const char * str2 );
-
This function starts comparing the first character of each string. If they are equal to each other, it continues with the following pairs until the characters differ or until a terminating null-character is reached.
-
标准规定
- 第一个字符串大于第二个字符串,则返回大于0的数字
- 第一个字符串等于第二个字符串,则返回0
- 第一个字符串小于第二个字符串,则返回小于0的数字
模拟实现:
int my_strcmp(const char* arr1, const char* arr2) { assert(arr1 && arr2) while (*arr1 && *arr2 && *arr1 == *arr2) { arr1++; arr2++; } return *arr1-*arr2; }
strncpy
char * strncpy ( char * destination, const char * source, size_t num );
-
Copies the first num characters of source to destination. If the end of the source C string (which is signaled by a null-character) is found before num characters have been copied, destination is padded with zeros until a total of num characters have been written to it.
-
拷贝num个字符从源字符串到目标空间。
-
如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加0,直到num个。
strncat
- Appends the first num characters of source to destination, plus a terminating null-character.
- If the length of the C string in source is less than num, only the content up to the terminating null-character is copied
就是在字符串1后追加num个字符串2的字符
- 如果n的长度要大于第二个字符串就追加到\0就不追加了
- 会在最后多追加一个\0
char * mystrncat(char * dst, const char * src, size_t n)
{
char * tmp = dst;
while (*dst)
{
dst++;
}
int i;
for (i = 0; src[i] && i < n; i++)
{
dst[i] = src[i];
}
dst[i] = 0;
return tmp;
}
strstr
char * strstr ( const char *str1, const char * str2);
- Returns a pointer to the first occurrence of str2 in str1, or a null pointer if str2 is not part of str1
在字符串1中寻找字符串2并返回找到后字符串1中的开头的地址
如果没找到就返回NULL
如果str2是空字符串就直接返回str1的首地址.
strtok
char * strtok ( char * str, const char * sep );
- sep参数是个字符串,定义了用作分隔符的字符集合 如"@."就是以’@‘和’.'寻找并分割
- 第一个参数指定一个字符串,它包含了0个或者多个由sep字符串中一个或者多个分隔符分割的标 记
- strtok函数找到str中的下一个标记,并将其用 \0 结尾,返回一个指向这个标记的指针。(注: strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容 并且可修改。)
- strtok函数的第一个参数不为 NULL ,函数将找到str中第一个标记,strtok函数将保存它在字符串中的位置。
- strtok函数的第一个参数为 NULL ,函数将在同一个字符串中被保存的位置开始,查找下一个标 记。
- 如果字符串中不存在更多的标记,则返回 NULL 指针
int main()
{
char str[] ="- This, a sample string.";
char * pch;
printf ("Splitting string \"%s\" into tokens:\n",str);
pch = strtok (str," ,.-");
while (pch != NULL)
{
printf ("%s\n",pch);
pch = strtok (NULL, " ,.-");
}
return 0;
}
strerror
char * strerror ( int errnum );
打印错误信息(现阶段几乎用不到)
使用
printf("%s\n",strerror(errno));
//或者直接使用
perror("fopen");
memset
void *memset( void *dest, int c, size_t count );
- dest 是要更改的变量
- c是要更改的数值
- count是要更改的字节数
memcpy
void * memcpy ( void * destination, const void * source, size_t num );
- 函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置。
- 这个函数在遇到 ‘\0’ 的时候并不会停下来。
- 如果source和destination有任何的重叠,复制的结果都是未定义的。
模拟实现:
void * memcpy ( void * dst, const void * src, size_t count)
{
void * ret = dst;
assert(dst&&src);
while (count--) {
*(char *)dst = *(char *)src;
dst = (char *)dst + 1;
src = (char *)src + 1;
}
return(ret);
}
memmove
void* memove(void* destination, const void* source, size_t num)
- 和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的。
- 如果源空间和目标空间出现重叠,就得使用memmove函数处理。
模拟实现:
void * memmove ( void * dst, const void * src, size_t count)
{
void * ret = dst;
//前->后
if (dst < src) {
while (count--) {
*(char *)dst = *(char *)src;
dst = (char *)dst + 1;
src = (char *)src + 1;
}
}
//后->前
else {
while (count--) {
*(*(char *)dst+count-1) = *((*(char *)src+count-1);
}
}
return ret;
}
memcmp
int memcmp ( const void * ptr1,
const void * ptr2,
size_t num );
-
比较从ptr1 和ptr2指针开始的num个字节
-
返回值如下
perror
会自动的帮你吧错误信息打到屏幕上
你也可以给他传递一个字符串他会把字符串打印到错误信息前并在中间加上。