C复习-字符串+字符+字节

参考: 里科《C和指针》


长度strlen

库函数strlen返回的是size_t(stddef.h中定义,是一个无符号整数)。如果需要跟int做比较、加减,需要加类型转换,否则结果可能是错的

if( strlen(x) >= strlen(y) )
if( strlen(x) - strlen(y) >= 0 ) // size_t是无符号数,相减结果也是size_t,肯定是永远非负
if( strlen(x) - 10 >= 0 ) // 这个也会永远true

#include <string.h>
#include <typeinfo>

		char s[] = "test";
    cout << typeid(strlen(s) - 10).name() << endl; // unsigned __int64
    cout << strlen(s) - 10 << endl; // 18446744073709551610
    cout << typeid(strlen(s)).name() << endl; // unsigned __int64

字符串复制strcpy

复制字符串使用的strcpy,要求目标字符数组的空间必须足够容纳待复制的字符串。strcpy不会检查目标字符数组的长度,所以复制过长的字符串时,会越界改写,报错。

char *strcpy(char *dst, char const *src);

字符串连接strcat

就是将src拷贝到dst末尾。同样需要程序员保证空间充足

char *strcat(char *dst, char const *src);

strcpy/strcat返回的是第一个参数的拷贝,即指向目标字符数组的指针。不过返回值一般都被忽略。

字符串比较strcmp

逐个字符比较,直到发现不匹配,此时如果那个字符比较小(字符集中的序数),则认为那个字符串比较小。使用strcmp,如果s1<s2,返回负值,大于返回正值,等于返回0。

int strcmp(char const *s1, char const *s2);

限定复制、连接和比较的长度strnXXX

strncpy、strncat和strncmp多加一个形参size_t len,用来限定操作范围。

strncpy:如果src的长度小于len,dst会用NUL填充到len长度;否则只复制len个,此时需要手动加\0,因为不会自动以NUL结尾

strncat:添加完后自动添加NUL

字符串查找单个字符

// 以下两个函数区分大小写
// 查找第一次出现的位置,找到后返回指针;找不到返回NULL
// char *ans = strchr(string, 'h');
char *strchr(char const *str, int ch);
// 从右边开始查找
char *strrchr(char const *str, int ch);

查找一组字符

只要其中一个字符出现即返回指针。区分大小写

char *strpbrk(char const *str, char const *group);

char string[20] = "Hello there";
char *ans = strpbrk(string, "aeiou");
// ans = string + 1,因为e出现了

查找一个子串

返回指针,指向s2在s1中第一次出现的位置。如果没有返回NULL。如果s2是空串,返回s1

char *strstr(char const *s1, char const *s2);

查找一个字符串前缀

size_t strspn(char const *str, char const *group);
// 这个c指的complement,指遇到匹配group的就停止
size_t strcspn(char const *str, char const *group); 

int len1, len2;
char buffer[] = "25,142,330,Smith,J,239-4123";
len1 = strspn(buffer, "0123456789"); // 2,因为buffer[2]=',',不匹配了
len2 = strspn(buffer, ",0123456789"); // 11,因为buffer[11]='S',不再匹配

查找标记token

// 会修改原字符串,因为找到下一个标记时会给它以NUL结尾,再返回指向这个标记的指针
// 如果str是NULL, 就从上一次查找位置之后继续查找
char *strtok(char *str, char const *sep);

void
print_tokens(char* line) 
{
    static char whitespace[] = " \t\f\r\v\n";
    char* token;
    for (token = strtok(line, whitespace); token != NULL;
        token = strtok(NULL, whitespace))
        printf("Next is %s\n", token);
}

int main()
{
    char s[] = " tes\tt"; 
    print_tokens(s);
    // Next is tes
    // Next is t
    return 0;
}

如果vs报错:‘strtok’: This function or variable may be unsafe. Consider using strtok_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS

去调试器的属性页-C/C+±预处理器-预处理器定义,编辑,增加_CRT_SECURE_NO_WARNINGS

同时,因为strtok保存了局部状态信息,所以不能同时解析两个字符串,因此,如果for循环的循环体中调用了一个在内部调用strtok的函数,上面的代码会失效

字符分类

iscntrl // 任何控制字符
isspace // 空格 换页\f 换行\n 回车\r 制表\t 垂直制表\v
isdigit // 0-9,十进制
isxdigit // 0-9+a-f+A-F十六进制
islower //
isupper // 最好不要用if(ch >='A' && ch <='Z')判断大小写,因为有的字符集不正确
isalpha // a~z+A~Z
isalnum // 字母+数字
ispunct //标点符号,任何不属于数字和字母的图形字符(可打印符号)
isgraph // 任何图形字符
isprint // 任何可打印字符,包括图形字符和空白字符

字符转换

int tolower(int ch);
int toupper(int ch);

内存操作

因为字符串函数处理不了内部有NUL的情况,但是下面可以。其中Length指的是字节,所以如果不是单字节的数据,需要使用sizeof

// 复制,但是dst和src重叠的结果未知
void *memcpy(void *dst, void const *src, size_t length);
// 如果是复制整型数组,可以把length写成sizeof(src)
// 如果只是复制部分,length=count * sizeof(src[0])

// 复制,dst和src可以重叠,比memcpy慢
void *memmove(void *dst, void const *src, size_t length);
void *memcmp(void const *a, void const *b, size_t length);

// 查找ch第一次出现的位置,共查找length个字节
void *memchr(void const *a, int ch, size_t length);

// 从a开始的length个字节设置为ch
void *memset(void *a, int ch, size_t length);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值