주제: C 언어의 공통 함수

목차

머리말

1.strlen 기능 

(1) strlen()의 기본 사용법

(2) strlen()의 반환값 유형

(3) my_strlen() 사용자 정의

2.strcpy 함수

(1) strcpy()의 기본 사용법

(2) my_strcpy() 사용자 정의

3. strcat 기능

(1) strcat()의 기본 사용법

(2) my_strcat() 사용자 정의

4.strcmp 기능

(1) strcmp()의 기본 사용법

(2) my_strcmp() 사용자 정의

5.str- 및 strn-

(1) 길이가 무제한인 문자열 함수

(2) 길이가 제한된 문자열 함수

6.strstr 함수

(1) strstr()의 기본 사용법

(2) my_strstr() 사용자 정의

(3) strchr 및 strrchr 함수

7.strtok 기능

(1) strtok()의 기본 사용법

8. 오류 기능

(1) strerror()의 기본 사용법

9. 기타 문자열 조작 기능

입력 및 출력 기능

대소문자 변환 기능

문자열 검색

10. 공통 캐릭터 조작 기능

입력 및 출력 기능

대소문자 변환 기능

문자 분류 기능

11.memset 기능

(1) memset()의 기본 사용법

12.memcpy 함수

(1) memcpy()의 기본 사용법

(2) my_memcpy() 사용자 정의

13.memmove 기능

(1) memmove()의 기본 사용법

(2) my_memcpy() 사용자 정의

14.memcmp 기능

(1) memcmp()의 기본 사용법

요약하다



머리말

        저자는 일부 C 언어 기능을 배운 후 문제를 해결할 때 거의 사용하지 않습니다(strlen 제외).몇몇 거물들의 영리한 문제 해결 아이디어와 방법을 관찰한 후 그는 항상 한숨을 쉬었습니다.: 코드를 모두 이해할 수 있습니다 . 나는 이것을한다? 그러다가 사장님 생각대로 다시 하려고 계획했는데, 쓸 수 없다는 걸 알게 됐어요. 이런 초보분들이 ​​적지 않은 것 같아서 여기서 다시 배우고 학습과정을 공유하려고 합니다.

참고: 이 기사에서는 주로 몇 가지 일반적인 문자(문자열) 연산 함수( string )와 메모리 관련 함수(memory ) 를 다루며 , 가장 일반적으로 사용되는 함수만 익히면 되며 필요할 때 다른 함수를 찾아볼 수도 있습니다.

학습 기능을 위한 추천 웹사이트: cplusplus.com


1.strlen 기능 

(1) strlen()의 기본 사용법

#include <stdio.h>
#include <string.h>

int main()
{
	char arr1[] = "abcdefg";
	char arr2[] = "abc\0defg";
	char arr3[20] = "abcdef";
	char arr4[] = { 'a','b','c','d','e','f','g' };
	char* arr5 = "abcde";
	printf("%d\n", strlen(arr1));
	printf("%d\n", strlen(arr2));
	printf("%d\n", strlen(arr3));
	printf("%d\n", strlen(arr4));
	printf("%d\n", strlen(arr5));
	return 0;
}

함수: strlen() 함수는 문자열에서 '\0'을 제외하고 '\0' 앞에 나타나는 문자 수를 반환합니다. 매개변수가 가리키는 문자열은 '\0'으로 끝나야 정상적인 결과를 반환할 수 있습니다.


(2) strlen()의 반환값 유형

int main()
{
	char arr1[] = "abcd";
	char arr2[] = "abcdefg";
	printf("part1:>");
	if (strlen(arr1) - strlen(arr2) < 0)
	{
		printf("arr1的长度小于arr2\n");
	}
	else
	{
		printf("arr1的长度大于等于arr2\n");
	}

	printf("part2:>");
	if ((int)strlen(arr1) - (int)strlen(arr2) < 0)
	{
		printf("arr1的长度小于arr2\n");
	}
	else
	{
		printf("arr1的长度大于等于arr2\n");
	}
	return 0;
}

참고: strlen() 함수를 사용하여 계산된 두 문자열의 길이를 빼면 항상 0보다 크거나 같습니다. strlen() 함수의 반환 값은 우리가 상상했던 int 유형이 아니지만, 부호 없는 유형 size_t

 

(3) my_strlen() 사용자 정의

自定义my_strlen()函数类型为 int 或 size_t 都可以,但它们各有优缺点
例如:如果为 int 类型,就比较方便理解 strlen(arr1) - strlen(arr2) 这样
的形式,但是如果出现意料之外的错误,就有可能导致计算的字符串长度为负数

//创建临时变量-计数器count
int my_strlen1(const char *arr)
{
	assert(arr != NULL);
	int count = 0;
	while (*arr != '\0')
	{
		count++;
		arr++;
	}
	return count;
}

//不创建临时变量-递归
int my_strlen2(const char* arr)
{
	assert(arr != NULL);
	if (*arr != '\0')
		return 1 + my_strlen2(arr + 1);
	else
		return 0;
}

int main()
{
	char arr[] = "abcdefghijk";
	int ret = my_strlen1(arr);
	printf("%d\n", ret);
	printf("%d\n", my_strlen2(arr));
	return 0;
}


2.strcpy 함수

(1) strcpy()의 기본 사용법

매개변수 1: 대상 문자열(수정 가능해야 함), 매개변수 2: 소스 문자열(수정을 방지하기 위해 const 유형으로 정의됨)

下面哪些代码可以正常运行?

	char arr1_src[] = "abcdef";
	char arr1_dest[] = { 0 };
	strcpy(arr1_dest, arr1_src);
	printf("%s\n", arr1_dest);
//arr1_dest 所占空间太小
	char arr2_src[] = { 'a','b','c','d','e','f' };
	char arr2_dest[20] = { 0 };
	strcpy(arr2_dest, arr2_src);
	printf("%s\n", arr2_dest);
//arr2_src 中没有 '\0' 
	char arr3_src[] = "abc\0def";
	char arr3_dest[20] = { 0 };
	strcpy(arr3_dest, arr3_src);
	printf("%s\n", arr3_dest);
//仅成功拷贝 \0 之前的 abc 三个字符
	char arr4_src[] = "abcdef";
	char* arr4_dest = "qwerty";
	strcpy(arr4_dest, arr4_src);
	printf("%s\n", arr4_dest);
//目标空间为 const char 类型,不可被修改
	char arr5_src[] = "abcdef";
	char arr5_dest[20] = { 0 };
	strcpy(arr5_dest, arr5_src);
	printf("%s\n", arr5_dest);
//拷贝成功

기능: 소스 문자열을 복사하여 대상 문자열에 저장합니다. 소스 문자열은 '\0'으로 끝나야 합니다. 소스 문자열의 '\0'은 대상 공간에 복사됩니다. 대상 공간은 충분히 커야 합니다. 소스 문자열을 저장할 수 있는지 확인하세요. 대상 공간은 가변적이어야 합니다.

(2) my_strcpy() 사용자 정의

char* my_strcpy(char* dest, const char* src)
{
	assert(dest && src);
	char* ret = dest;
	while (*dest++ = *src++)
	{
		;
	}
	return ret;
}

int main()
{
	char arr1[] = "Practise makes perfect!";
	char arr2[30] = { 0 };
	my_strcpy(arr2, arr1);
	printf("%s", arr2);
	return 0;
}


3. strcat 기능

(1) strcat()의 기본 사용법

매개변수 1: 기본 문자열, 매개변수 2: 추가 문자열.

int main()
{
	char arr1_dest[20] = "hello ";
	char arr1_src[] = "world!";
	strcat(arr1_dest, arr1_src);
	printf("%s\n", arr1_dest);

	char arr2_dest[20] = "hello \0xxxxxx";
	char arr2_src[] = "world!";
	strcat(arr2_dest, arr2_src);
	printf("%s\n", arr2_dest);

	char arr3_dest[20] = { 'h','e','l','l','o',' '};
	char arr3_src[] = "world!";
	strcat(arr3_dest, arr3_src);
	printf("%s\n", arr3_dest);

	char arr4_dest[20] = "hello ";
	char arr4_src[] = { 'w','o','r','l','d', '!'};
	strcat(arr4_dest, arr4_src);
	printf("%s\n", arr4_dest);
	return 0;
}

기능: 소스 문자열의 내용('\0' 포함)을 대상 문자열의 '\0' 끝에 연결하여(대상 문자열의 '\0'을 덮음) 대상 공간이 충분히 큰지 확인합니다. 그리고 수정될 수 있습니다.

(2) my_strcat() 사용자 정의

char* my_strcat(char* dest, const char* src)
{
	assert(dest && src);
	char* ret = dest;
	while (*dest != '\0')
	{
		dest++;
	}
	while (*dest++ = *src++)
	{
        ;
	}
	return ret;
}

int main()
{
	char arr1[30] = "hello ";
	char arr2[30] = "world!";
	my_strcat(arr1, arr2);
	printf("%s", arr1);
	return 0;
}

思考:
my_strcat(arr1, arr1);
可以达到如下效果吗?
arr1 = "hello hello ";


4.strcmp 기능

(1) strcmp()의 기본 사용법

char arr1[] = "compare";
char arr2[] = "compbre";
//可以这样比较字符串的大小吗?
if("compare" == "compbre")
    printf("相等\n");
//这里实际上比较的是它们的地址
//因此这种写法是不能满足我们的需要的



int main()
{
	char arr1[] = "abcde";
	char arr2[] = "abcde";
	char arr3[] = "abcdabcd";
	char arr4[] = "z";

	if (strcmp(arr1, arr2) > 0)
		printf("arr1 > arr2\n");
	else if (strcmp(arr1, arr2) == 0)
		printf("arr1 = arr2\n");
	else
		printf("arr1 < arr2\n");

	if (strcmp(arr1, arr3) > 0)
		printf("arr1 > arr3\n");
	else if (strcmp(arr1, arr3) == 0)
		printf("arr1 = arr3\n");
	else
		printf("arr1 < arr3\n");

	if (strcmp(arr1, arr4) > 0)
		printf("arr1 > arr4\n");
	else if (strcmp(arr1, arr4) == 0)
		printf("arr1 = arr4\n");
	else
		printf("arr1 < arr4\n");
	return 0;
}

기능: 문자열의 크기를 비교합니다. 먼저 두 문자열의 첫 번째 요소의 ASCII 코드 크기를 비교하고, 같으면 다음 요소를 거꾸로 비교합니다. 두 문자열의 모든 요소가 같으면 다음을 수행할 수 있습니다. 크기를 판단하십시오. 두 문자열이 동일합니다.

(2) my_strcmp() 사용자 정의

int my_strcmp(const char* arr1, const char* arr2)
{
	assert(arr1 && arr2);
	while (*arr1 == *arr2)
	{
		if (*arr1 == '\0')
			return 0;
		arr1++;
		arr2++;
	}
	return *arr1 - *arr2;
}

int main()
{
	char arr1[] = "compare";
	char arr2[] = "compbre";
	int ret = my_strcmp(arr1, arr2);

	if (my_strcmp(arr1, arr2) > 0)
		printf("arr1 > arr2\n");
	else if(my_strcmp(arr1, arr2) == 0)
		printf("arr1 = arr2\n");
	else
		printf("arr1 < arr2\n");
	return 0;
}


5.str- 및 strn-

(1) 길이가 무제한인 문자열 함수

앞서 소개한 strlen, strcpy, strcmp, strcat 함수에서 매개변수로 사용되는 문자열의 길이에는 제한이 없으므로 다음과 같은 보안 위험이 발생할 수 있습니다.

(2) 길이가 제한된 문자열 함수

길이가 제한된 문자열 함수는 상대적으로 안전할 뿐입니다. 버그를 작성하려는 사람은 누구도 막을 수 없습니다! ! !

strnlen、strncpy、strncmp、strncat

예를 들어:


6.strstr 함수

(1) strstr()의 기본 사용법

매개변수 1: 상위 문자열, 매개변수 2: 하위 문자열.

기능: str2가 str1의 하위 문자열인지 확인하고 str1에서 str2가 처음 나타나는 주소를 반환합니다.

(2) my_strstr() 사용자 정의

char* my_strstr(const char* arr1, const char* arr2)
{
	assert(arr1 && arr2);
	char* str1 = NULL;
	char* str2 = NULL;
	char* p = (char*)arr1;
	while (*p)
	{
		str1 = p;
		str2 = (char*)arr2;
		while (*str1 && *str2 && *str1++ == *str2++)
		{
			;
		}
		if (*str2 == '\0')
			return p;
		p++;
	}
	return NULL;
}

int main()
{
	char arr1[] = "qwereabcd";
	char arr2[] = "were";
	char* ret = my_strstr(arr1, arr2);
	if (ret == NULL)
	{
		printf("找不到\n");
	}
	else
	{
		printf("找到了:%s中存在字符串%s\n", ret, arr2);
	}
	return 0;
}

(3) strchr 및 strrchr 함수

int main()
{
	char arr1[] = "abcdefgbcde";
	char arr2[] = "bcde";
	char* ret1 = strchr(arr1, 'b');
	if (ret1 == NULL)
	{
		printf("找不到\n");
	}
	else
	{
		printf("%s\n", ret1);
	}
	char* ret2 = strrchr(arr1, 'b');
	if (ret2 == NULL)
	{
		printf("找不到\n");
	}
	else
	{
		printf("%s\n", ret2);
	}
	return 0;
}

요약: strchr은 대상 문자를 처음 만났을 때의 주소를 반환하고, strrchr은 대상 문자를 마지막으로 만났을 때의 주소를 반환합니다.


7.strtok 기능

(1) strtok()의 기본 사용법

매개변수 1: 분할할 문자열, 매개변수 2: 상수 문자열(분할 문자 집합)

0

기능: 분할할 문자열 세그먼트에 대한 포인터인 "마크"를 반환합니다(원래 문자열을 분할하려면 원래 문자열의 분할 문자를 '\0'으로 변경).

strtok의 첫 번째 매개변수가 NULL이 아닌 경우 함수는 첫 번째 토큰을 반환하고 해당 위치를 문자열에 저장합니다.

strtok의 첫 번째 매개변수가 NULL이면 함수는 저장된 위치에서 시작하여 다음 마크를 검색합니다.

문자열에 더 이상 토큰이 없으면 NULL을 반환합니다.

지금은 strtok 함수 사용법을 배우는 것만으로도 충분하다고 생각합니다

관심 있는 학생들은 스스로 시도해 볼 수 있으며 댓글 영역에서 자신의 my_strtok을 공유할 수 있습니다!


8. 오류 기능

(1) strerror()의 기본 사용법

매개변수: 오류 코드

기능: 오류 코드에 해당하는 오류 메시지의 첫 번째 문자 주소를 반환합니다(오류 코드를 오류 메시지로 변환).

설명: C 언어 라이브러리 함수 호출에 실패하면 errno라는 변수에 오류 코드가 저장됩니다. 어떤 오류가 발생했는지 알고 싶을 때 strerror를 사용하여 오류 코드 errno를 오류 메시지로 변환할 수 있습니다.

다음으로 예를 들어 보겠습니다.


9. 기타 문자열 조작 기능

입력 및 출력 기능

문자열을 읽습니다(공백 포함).

puts는 문자열을 출력합니다.

대소문자 변환 기능

strlwr 소문자로 변환

strupr 대문자로 변환

문자열 검색

strpbrk...

strspn ...

... ...


10. 공통 캐릭터 조작 기능

입력 및 출력 기능

getchar는 문자를 읽습니다.

putchar는 문자를 출력합니다.

대소문자 변환 기능

tolower 소문자로 변환

toupper 대문자로 변환

문자 분류 기능

조건이 충족되면 true를 반환합니다.

isalnum은 문자인지 숫자인지 판별합니다. isdigit
는 숫자인지 판별
합니다. isxdigit는 16진수인지
판별합니다. isalpha는 문자인지 여부를 판별합니다.
isupper는 대문자인지 판별합니다.
islower는 소문자인지 판별합니다. iscntrl은 문자인지
판별합니다. 제어 문자입니다
isspace 공백, 페이지 피드, 줄 바꿈, 캐리지 리턴, 탭 문자인지 확인 ispunct
구두점인지 여부
확인 isgraph 그래픽 문자인지 확인
isprint 인쇄 가능한 문자인지 확인

... ...


11.memset 기능

(1) memset()의 기본 사용법

매개변수 1: 수정해야 할 위치를 가리킴(포인터/배열 이름) 매개변수 2: 수정된 데이터 매개변수 3: 수정된 공간의 크기(단위는 바이트)

val은 int 유형입니다.

val은 char 유형입니다.

요약하다:

(1) ptr이 char 유형 주소를 가리키는 경우 value는 모든 문자 값일 수 있습니다.
(2) ptr이 int 유형 주소와 같은 char 유형이 아닌 유형을 가리키는 경우 할당이 정확하려면 값은 - 1 또는 0만 될 수 있습니다. 왜냐하면 - 1과 0이 이진수로 변환된 후에는 각 비트가 동일하므로 우리는 종종 memset을 사용하여 배열을 모두 0으로 초기화합니다.
 


12.memcpy 함수

(1) memcpy()의 기본 사용법

매개변수 1: 대상 공간에 대한 포인터(void 유형), 매개변수 2: 소스 공간에 대한 포인터(void 유형), 매개변수 3: 복사된 공간의 크기(단위는 바이트)

注意:当我们需要拷贝字符串的时候,是否可以使用memcpy呢?答案是当然可以,
但是我们为什么不直接使用更加方便的strcpy呢?

void test1()
{
	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
	int arr2[20] = { 0 };
	memcpy(arr2, arr1, 32);
	for (int i = 0; arr2[i] != 0; i++)
	{
		printf("%d ", arr2[i]);
	}
	printf("\n");
}

void test2()
{
	float arr1[] = { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0 };
	float arr2[48] = { 0.0 };
	memcpy(arr2, arr1, 32);
	for (int i = 0; arr2[i] != 0; i++)
	{
		printf("%.2f ", arr2[i]);
	}
	printf("\n");
}

int main()
{
	test1();
	test2();
	return 0;
}

(2) my_memcpy() 사용자 정의

void* my_memcpy(void* dest, const void* src, size_t num)
{
	assert(dest && src);
	void* ret = dest;
	while (num--)
	{
		//我们不知道使用者需要拷贝的类型,所以采用逐字节拷贝的方法
        *(char*)dest = *(char*)src;
		dest = (char*)dest + 1;
		src = (char*)src + 1;
	}
	return ret;
}

void test3()
{
	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
	int arr2[20] = { 0 };
	my_memcpy(arr2, arr1, 32);
	for (int i = 0; arr2[i] != 0; i++)
	{
		printf("%d ", arr2[i]);
	}
	printf("\n");
}

int main()
{
	test3();
	return 0;
}


13.memmove 기능

(1) memmove()의 기본 사용법

매개변수 1: 대상 공간에 대한 포인터(void 유형), 매개변수 2: 소스 공간에 대한 포인터(void 유형), 매개변수 3: 이동된 공간의 크기(단위는 바이트)

 

다음 코드가 우리가 기대하는 결과를 얻을 수 있습니까?

왜?

참고: 메모리가 겹칠 때 모든 컴파일러가 정상적으로 복사할 수 없는 것은 아니지만 memcpy는 메모리를 덮어쓸 위험이 있습니다! 

(2) my_memcpy() 사용자 정의

void* my_memmove(void* dest, const void* src, size_t num)
{
	assert(dest && src);
	void* ret = dest;
	if (dest < src)
	{
		while (num--)
		{
			*(char*)dest = *(char*)src;
			dest = (char*)dest + 1;
			src = (char*)src + 1;
		}
	}
	else
	{
		while (num--)
		{
			*((char*)dest + num) = *((char*)src + num);
		}
	}
	return ret;
}


14.memcmp 기능

(1) memcmp()의 기본 사용법

매개변수 1: 비교할 공간의 포인터 1(void 유형), 매개변수 2: 비교할 공간의 포인터 2(void 유형), 매개변수 3: 비교할 공간의 크기(단위는 바이트)

void test1()
{
	int arr1[] = { 1,2,3,4,5,7 };
	int arr2[] = { 1,2,3,4,6,7 };
	int ret = memcmp(arr1, arr2, 16);
	printf("%d\n", ret);//0
}

void test2()
{
	int arr1[] = { 1,2,3,4,5 };
	int arr2[] = { 1,2,3,4,6 };
	int ret = memcmp(arr1, arr2, 20);
	printf("%d\n", ret);//-1
}

void test3()
{
	int arr1[] = { 1,2,3,4,5 };
	int arr2[] = { 1,2,3,4,6 };
	int ret = memcmp(arr1, arr2, 17);
	printf("%d\n", ret);//-1
}

int main()
{
	test1();
	test2();
	test3();
	return 0;
}


요약하다

        오늘 제가 이야기하고 싶은 내용은 위와 같습니다. 사실 프로그래밍을 배우려면 질문에 답하는 것뿐만 아니라 생각하고 요약하는 것도 필요합니다. 우리는 큰 상사로부터 영감을 얻지 못하는 경우가 많습니다. 우리가 그것을 하기 전에 많은 노력을 기울여야 합니다)), 문제에 직면했을 때 더 많은 방법을 가질 수 있도록 몇 가지 문제 해결 기술과 아이디어를 기록하십시오. 이 글이 모든 분들께 도움이 되기를 바라며, 독자분들의 비판과 지적도 환영합니다^W^

추천

출처blog.csdn.net/weixin_72501602/article/details/129194248