1.字符
2.字符串
3.检验参数合法性(非常必要)
4.字符串相关库函数实现(面试)
字符:字符型数据;
例:‘d’、’!’、’=’、’+’、’?’…
在C语言中,字符型数据特点为:
* 字符型数据只能用单引号括起来,不能用双引号或其它括号。
* 字符型数据只能是单个字符,不能是字符串。
* 字符可以是字符集中任意字符。但数字被定义为字符型之后就不能参与数值运算。如’5’和5 是不同的。'5’是字符型数据,不能参与运算。
转义字符:转义字符是一种特殊的字符。转义字符以反斜线""开头,后跟一个或几个字符。转义字符具有特定的含义,不同于字符原有的意义,故称“转义”字符。转义字符主要用来表示那些用一般字符不便于表示的控制代码。转义字符链接
字符变量的存储:每个字符变量被分配一个字节的内存空间,因此只能存放一个字符。字符值是以ASCII码的形式存放在变量的内存单元之中的。
* C语言允许对整型变量赋以字符值,也允许对字符变量赋以整型值。在输出时,允许把字符变量按整型量输出,也允许把整型量按字符量输出。
* 整型量为2个字节单位,字符变量为单字节量,当整型量按字符型量处理时,只有低八位字节参与处理。(‘a’-(十进制整数表示为)97,‘A’=‘a’-32=65;
例:‘a’——内存中存储ASCII仍为’a’; “a”——内存中为 a \0;
#include
#include
#include //包含assert的库函数头文件
int maxNum(int a, int b) {
//assert校验参数
assert(a != 0);
assert(b != 0);
//if校验参数
if (a == 0 || b == 0) {
return 0;
}
else {
int i = 1;
int max = 0;
for (; i <= (a < b ? a : b); i++) {
if (a % i == 0 && b % i == 0) {
max = i;
}
}
return max;
}
}
int main() {
int a = 1;
int b = 2;
//不但要在函数体内检验参数合法性,函数调用时也需检验;
if (a != 0 && b != 0) {
int ret = maxNum(a, b);
printf("%d\n", ret);
}
system("pause");
return 0;
}
以上两种校验方法都可以进行参数合法性检验(校验思想很重要);
在函数内部设置校验方法是有必要的;在函数体外函数调用的时候仍需要进行参数合法性判断——因为在实际开发中,一般是多人多人协作完成开发,比如一个人写一个函数另一个人进行使用;所以不同人都对函数进行参数检验,双重保证!
#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include
#include
size_t strlen(const char* str) {
//校验参数的合法性 1.(不能校验野指针)
if (str == NULL) {
return 0;
}
//校验参数的合法性 2.(避免野指针)
assert(str != NULL);
size_t size = 0;
while (str[size] != '\0') {
size++;
}
return size;
}
int main() {
printf("字符串“abcd”的长度为:%d\n", strlen("abcd"));
char* p = "zxcv";
if (p != NULL) {
printf("p的长度为:%d\n", strlen(p));
}
system("pause");
return 0;
}
#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include
#include
typedef struct student {
int id;
char name[100];
}stu;
char* Strcpy(char* dest, const char* src) {
assert(dest != NULL);
assert(src != NULL);
int i = 0;
while (src[i] != '\0') {
dest[i] = src[i];
i++;
}
dest[i] = '\0';
return dest;
}
int main() {
char src[] = "hehe";
char dest[1024] = { 0 };
Strcpy(dest,src);
printf("%s\n", dest);
stu s = { 1,"zwr" };
//s.name = "lisa";
strcpy(s.name, "lisa");
printf("%s\n", s.name);
system("pause");
return 0;
}
<3>实现将一个字符串添加在另一个字符串后面——实现两个字符串拼接的库函数strcat
#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include
#include
char* Strcat(char* dest, const char* src) {
assert(dest != NULL);
assert(src != NULL);
int destTail = 0;
while (dest[destTail] != '\0') {
destTail++;
}
//Strcpy(dest + destTail, src);
int i = 0;
while (src[i] != '\0'){
dest[i + destTail] = src[i];
i++;
}
dest[i + destTail] = '\0';
return dest;
}
int main() {
char src[] = "heihei";
char dest[1024] = "xixi";
Strcat(dest, src);
printf("%s\n", dest);
system("pause");
return 0;
}
<4>实现比较两个字符串是否相等(大小)的库函数strcmp
#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include
#include
int Strcmp(const char* dest, const char* src) {
assert(dest!= NULL);
assert(src != NULL);
const char* p1 = dest;
const char* p2 = src;
//方法1:
while (*p1 != '\0' || *p2 != '\0') {
int diff = *p1 - *p2;
if (diff < 0 || diff>0) {
return diff;
}
else if (diff == 0) {
p1++;
p2++;
}
}
return 0;
//方法二:
//while (*p1 != '\0' && *p2 != '\0') {
// if (*p1 < *p2) {
// return -1;
// }
// else if (*p1 > *p2) {
// return 1;
// }
// p1++;
// p2++;
//}
//if (*p1 < *p2) {
// return -1;
//}
//else if (*p1 > *p2) {
// return 1;
//}
//else if(*p1==*p2){
// return 0;
//}
//return *p1 - *p2;
}
int main() {
char src[] = "hiii";
char dest[] = "hiig";
int ret = Strcmp(dest, src);
printf("%d\n", ret);
system("pause");
return 0;
}
上述程序中 int diff = *p1 - *p2——可以直接表示两个指向字符的指针相减=>两个字符在字典序中相差几位;
#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include
#include
char* Strncpy(char* dest, const char* src, size_t num) {
assert(dest != NULL);
assert(src != NULL);
assert(num != NULL);
size_t i = 0;
while (src[i] != '\0' && i < num) {
dest[i] = src[i];
i++;
}
//dest[i] = '\0';
while (i <= num) {
dest[i] = '\0';
i++;
}
return dest;
}
int main() {
char src[] = "hehe";
char dest[1024] = { 0 };
Strncpy(dest, src, 3); //size_num<=sizeof(dest)-1;
printf("%s\n", dest);
system("pause");
return 0;
}
<6>实现特定长度将源字符串拼接到目标字符串的库函数strncat
#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include
#include
char* Strncat(char* dest, const char* src, size_t num) {
assert(dest != NULL);
assert(src != NULL);
assert(num != 0);
size_t destTail = 0;
while (dest[destTail] != '\0') {
destTail++;
}
int i = 0;
while (src[i] != '\0' && i < num) {
dest[destTail + i] = src[i];
i++;
}
dest[destTail + i] = '\0';
return dest;
}
int main() {
char src[] = "hehe";
char dest[1024] = "haha";
Strncat(dest, src, 2); //size_num<=sizeof(dest)-1;
printf("%s\n", dest);
system("pause");
return 0;
}
<7>实现两个字符串比较特定长度的大小的库函数strncmp
#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include
#include
int Strncmp(const char* dest, const char* src, size_t num) {
assert(dest != NULL);
assert(src != NULL);
assert(num != 0);
size_t i = 0;
while (dest[i] != '\0' && src[i] != '\0' && i < num) {
if (dest[i] < src[i]) {
return -1;
}
else if (dest[i] > src[i]) {
return 1;
}
else {
i++;
}
}
return dest[i - 1] - src[i - 1];
}
int main() {
char src[] = "hehe";
char dest[] = "heha";
int ret = Strncmp(dest, src, 4);
printf("%d\n", ret);
system("pause");
return 0;
}
<8>实现判断两个字符串前者是否包含于后者的库函数strstr
#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include
#include
char* Strstr(const char* str1, const char* str2) {
assert(str1 != NULL);
assert(str2 != NULL);
assert(*str1 != '\0');
assert(*str2 != '\0');
const char* blank = str1;
while (*blank != '\0') {
char* red = blank; //临时比较
char* sub = str2;
while (*sub != '\0' && *red != '\0' && *red == *sub) {
red++;
sub++;
}
if (*sub == '\0') {
return blank;
}
blank++;
}
return NULL;
}
int main() {
char* str1 = "hello TiMi!";
char* str2 = "TiMi";
const char* ret = Strstr(str1, str2);
printf("%s\n", ret);
system("pause");
return 0;
}
#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include
#include
typedef struct stu {
int id;
char name[100];
}student;
void* Memcpy(void* dest, const void* src, size_t num) {
assert(src != NULL);
assert(num != 0);
char* cdest = (char*)dest;
const char* csrc = (const char*)src;
for (size_t i = 0; i < num; i++) {
cdest[i] = csrc[i];
}
return dest;
}
int main() {
int a1[] = { 3,2,1 };
int a2[100] = { 0 };
Memcpy(a2, a1, sizeof(a1)); //数组传参时,数组名可以隐式转化为首元素地址
for (int i = 0; i < 3; i++) {
printf("%d ", a2[i]);
}
student s1 = { 1,"zwr" };
student s2;
Memcpy(&s2, &s1, sizeof(s1));
printf("\n%d,%s\n", s2.id, s2.name);
system("pause");
return 0;
}
<11>实现内存空间拷贝(包括重叠的拷贝)的库函数memmove
#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include
#include
void* Memmove(void* dest, const void* src, size_t num) {
assert(src != NULL);
assert(num != 0);
char* cdest = (char*)dest;
const char* csrc = (const char*)src;
if (cdest > csrc && cdest < csrc + num) {
for (size_t i = num; i > 0; i--) {
cdest[i - 1] = csrc[i - 1];
}
}
else {
for (size_t i = 0; i < num; i++) {
cdest[i] = csrc[i];
}
}
return dest;
}
int main() {
int a1[] = { 3,2,1 };
int a2[100] = { 0 };
Memmove(a2, a1, sizeof(a1));
for (int i = 0; i < 3; i++) {
printf("%d ", a2[i]);
}
system("pause");
return 0;
}