3.文字列関連の関数

strlen

strcpy

strcat

strcmp

strncpy

strncat

strncmp

strstr

strtok

ストラー


size_t strlen(const char * str)

#include <string.h>

・文字列は「\ 0」で終わり、strlen関数は文字列の「\ 0」の前に表示される文字数を返します(「\ 0」は含まれません)。
・パラメータが指す文字列は「\ 0」で終わる必要があります。
・関数の戻り値はsize_tであり、符号なし(エラーが発生しやすい)であることに注意してください。
・strlen関数のアナログ実装

例:
/* strlen example1 */
#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;
}

/* strlen example2 */
#include <stdio.h>
#include <string.h>

int main ()
{
   char str[50];
   int len;

   strcpy(str, "This is runoob.com");

   len = strlen(str);
   printf("|%s| 的长度是 |%d|\n", str, len);
   
   return(0);
}

カウンターシミュレーションの実装:
/* simulation of strlen function with counter */
#include <stdio.h>
//计数器实现
size_t Strlen(const char* str)
{
	size_t count = 0;
	while (*str != '\0')
	{
		++str;
		++count;
	}
	return count;
}
int main()
{
	char str[] = "This is runoob.com";
	size_t len;

	len = strlen(str);
	printf("|%s| 的长度是 |%u|\n", str, len);
	return 0;
}

再帰的シミュレーションで実現:
/* simulation of strlen function with recursion */
#include <stdio.h>
//递归实现
size_t Strlen(const char* str)
{
	if (*str != '\0')
	{
		return Strlen(str + 1) + 1;
	}
	else
		return 0;
}
int main()
{
	char str[] = "This is runoob.com";
	size_t len;

	len = Strlen(str);
	printf("|%s| 的长度是 |%u|\n", str, len);
	return 0;
}


ポインタアドレス差分法を使用して、以下をシミュレートおよび実現します。
/* simulation of strlen function with indicator */
#include <stdio.h>
//指针地址差实现
size_t strlen(const char* str)
{
	const char* eos = str;
	while (*eos++);
		return (eos - str - 1);
}
int main()
{
	char str[] = "This is runoob.com";
	size_t len;

	len = strlen(str);
	printf("|%s| 的长度是 |%u|\n", str, len);
	return 0;
}
ライブラリでの実装:
/*strlen in lib*/


size_t __cdecl strlen (
        const char * str
        )
{
        const char *eos = str;

        while( *eos++ ) ;

        return( eos - str - 1 );
}


char * strcpy(char * dest、const char * src)

#include <string.h>

dest-コピーされたコンテンツを格納するために使用されるターゲット配列を指します。
src-コピーする文字列。

例:
/* strcpy example1 */
#include <stdio.h>
#include <string.h>
 
int main()
{
   char src[40];
   char dest[100];
  
   memset(dest, '\0', sizeof(dest));
   strcpy(src, "This is runoob.com");
   strcpy(dest, src);
 
   printf("最终的目标字符串: %s\n", dest);
   
   return(0);
}

/* strcpy example2 */
#include <stdio.h>
#include <string.h>
 
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;
}

シミュレーションの実装:
/* simulation of strcpy1*/
#include <stdio.h>
#include <string.h>
char* Strcpy(char* dest, const char* src)
{
    char * cp = dest;
	while (*src)
	{
		*cp++ = *src++;
	}
	*cp = *src;
	return dest;
}
int main()
{
	char src[40];
	char dest[100];

	memset(dest, '\0', sizeof(dest));
	Strcpy(src, "This is runoob.com");
	Strcpy(dest, src);

	printf("最终的目标字符串: %s\n", dest);

	return(0);
}


/* simulation of strcpy2*/
#include <stdio.h>
#include <string.h>
#include <assert.h>
char* Strcpy(char* dest, const char* src)
{
    char * cp = dest;
	assert(src != NULL);
	while (*cp++ = *src++);
	return dest;
}
int main()
{
	char src[40];
	char dest[100];

	memset(dest, '\0', sizeof(dest));
	Strcpy(src, "This is runoob.com");
	Strcpy(dest, src);

	printf("最终的目标字符串: %s\n", dest);

	return(0);
}

ライブラリでの実装:
/*strcpy in lib*/


char * __cdecl strcpy(char * dst, const char * src)
{
	char * cp = dst;
 
	while (*cp++ = *src++)
		;               /* Copy src over dst */
 
	return(dst);

}


char * strcat(char * dest、const char * src)

#include <string.h>

dest-C文字列を含み、追加された文字列を保持するのに十分な大きさのターゲット配列を指します。
src-追加する文字列を指します。ターゲット文字列は上書きされません。

例:
/* strcat example */
#include <stdio.h>
#include <string.h>
 
int main ()
{
   char src[50], dest[50];
 
   strcpy(src,  "This is source");
   strcpy(dest, "This is destination");
 
   strcat(dest, src);
 
   printf("最终的目标字符串: |%s|", dest);
   
   return(0);
}

シミュレーションの実装:
/* simulation of strcat*/
#include <stdio.h>
#include <string.h>
#include <assert.h>
char* Strcat(char* dest, const char* src)
{
    char * cp = dest;
	/*while (*cp) 
		++cp;*/
	if (*cp)
		while (*(++cp));
	assert(src != NULL);
	while (*cp++ = *src++);
	return dest;
}
int main()
{
	char src[50], dest[50];

	strcpy(src, "This is source");
	strcpy(dest, "This is destination");

	Strcat(dest, src);

	printf("最终的目标字符串: |%s|", dest);

	return(0);
}


ライブラリでの実装:
/*strcat in lib*/  
char * __cdecl strcat (
        char * dst,
        const char * src
        )
{
        char * cp = dst;

        while( *cp )
                cp++;                   /* find end of dst */

        while( *cp++ = *src++ ) ;       /* Copy src to end of dst */

        return( dst );                  /* return dst */

}

int strcmp(const char * str1、const char * str2)

#include <string.h>

str1-比較される最初の文字列。
str2-比較する2番目の文字列。
戻り値が0未満の場合、str1がstr2よりも小さいことを意味します。
戻り値> 0の場合、str2がstr1より小さいことを意味します。
戻り値= 0の場合、str1がstr2と等しいことを意味します。

例:
/* strcmp example */
#include <stdio.h>
#include <string.h>
 
int main ()
{
   char str1[15];
   char str2[15];
   int ret;
 
 
   strcpy(str1, "abcdef");
   strcpy(str2, "ABCDEF");
 
   ret = strcmp(str1, str2);
 
   if(ret < 0)
   {
      printf("str1 小于 str2");
   }
   else if(ret > 0) 
   {
      printf("str2 小于 str1");
   }
   else 
   {
      printf("str1 等于 str2");
   }
   
   return(0);
}

シミュレーションの実装:
/* simulation of strcmp*/
#include <stdio.h>
#include <string.h>

int Strcmp(const char* src, const char* dst)
{
	while ( (*src && *dst) && *src++ == *dst++);  //*src != '\0'&& *dst != '\0'  --> *src && *dst
	if (!*src && !*dst)	return 0;
	else if (!*src) return -1;
	else if (!*dst) return 1;
	else
		return *src - *dst;
}

int main()
{
	char str1[15];
	char str2[15];
	int ret;

	strcpy(str1, "abcdef");
	strcpy(str2, "ABCDEF");

	ret = Strcmp(str1, str2);

	if (ret < 0)
	{
		printf("str1 小于 str2");
	}
	else if (ret > 0)
	{
		printf("str2 小于 str1");
	}
	else
	{
		printf("str1 等于 str2");
	}

	return(0);
}
ライブラリでの実装:
/*strcmp in lib*/
int __cdecl strcmp (
        const char * src,
        const char * dst
        )
{
        int ret = 0 ;

        while( ! (ret = *(unsigned char *)src - *(unsigned char *)dst) && *dst)
                ++src, ++dst;

        if ( ret < 0 )
                ret = -1 ;
        else if ( ret > 0 )
                ret = 1 ;

        return( ret );
}

char * strncpy(char * dest、const char * src、size_t n)

#include <string.h>

dest-コピーされたコンテンツを格納するために使用されるターゲット配列を指します。
src-コピーする文字列。
n-ソースからコピーされる文字数。
この関数は、最終的にコピーされた文字列を返します。

例:
/* strncpy example */  //不追加'\0'
#include <stdio.h>
#include <string.h>

int main()
{
   char src[40];
   char dest[12];
  
   memset(dest, '\0', sizeof(dest));
   strcpy(src, "This is runoob.com");
   strncpy(dest, src, 10);

   printf("最终的目标字符串: %s\n", dest);
   
   return(0);
}
シミュレーションの実装
/* simulation of strncpy*/  //不追加'\0'
#include <stdio.h>
#include <string.h>

char* Strncpy(char* dest, const char* src, size_t n)
{
	char* cp = dest;
	while (n--)
	{
		*cp++ = *src++;
	}
	return dest;
}

int main()
{
	char src[40];
	char dest[12];

	memset(dest, '\0', sizeof(dest));
	strcpy(src, "This is runoob.com");
	Strncpy(dest, src, 10);

	printf("最终的目标字符串: %s\n", dest);

	return(0);
}

ライブラリでの実装:
/*Strncpy in lib*/
char * __cdecl strncpy (
        char * dest,
        const char * source,
        size_t count
        )
{
        char *start = dest;

        while (count && (*dest++ = *source++))    /* copy string */
                count--;

        if (count)                              /* pad out with zeroes */
                while (--count)
                        *dest++ = '\0';

        return(start);
}

char * strncat(char * dest、const char * src、size_t n)

#include <string.h>

dest-C文字列を含み、追加のnull文字を含む追加された文字列を保持するのに十分な大きさのターゲット配列を指します。
src-追加する文字列。
n-追加する最大文字数。
戻り値:
この関数は、最終的なターゲット文字列destへのポインタを返します

例:
/* strncat example */  //追加'\0'
#include <stdio.h>
#include <string.h>

int main ()
{
   char src[50], dest[50];

   strcpy(src,  "This is source");
   strcpy(dest, "This is destination");

   strncat(dest, src, 15);

   printf("最终的目标字符串: |%s|", dest);
   
   return(0);
}
シミュレーションの実装:
/* simulation of strncat*/
#include <stdio.h>
#include <string.h>
char* Strncat(char* dest, const char* src, size_t n)
{
	char* cp = dest;
	if(*cp)
		while (*(++cp));  //如果dest第一个是\0元素,防止从从它后面开始复制
	while (n--)
	{
		if(!(*cp++ = *src++))    //防止越界写
		return dest;
	}
	*cp = '\0';
	return dest;
}

int main()
{
	char src[50], dest[50] = {0};

	strcpy(src, "This is source");
	//strcpy(dest, "This is destination");


	Strncat(dest, src, 15);

	printf("最终的目标字符串: |%s|", dest);

	return(0);
}
ライブラリでの実装:
/*Strncat in lib*/  //追加'\0'
char * __cdecl strncat (
        char * front,
        const char * back,
        size_t count
        )
{
        char *start = front;

        while (*front++)
                ;
        front--;

        while (count--)
                if (!(*front++ = *back++))
                        return(start);

        *front = '\0';  //追加'\0'
        return(start);
}

int strncmp(const char * str1、const char * str2、size_t n)

#include <string.h>

str1-比較される最初の文字列。
str2-比較する2番目の文字列。
n-比較する最大文字数。
戻り値
この関数の戻り値は次のとおりです。
戻り値<0の場合、str1がstr2よりも小さいことを意味します。
戻り値> 0の場合、str2がstr1より小さいことを意味します。
戻り値= 0の場合、str1がstr2と等しいことを意味します。

例:
/* strncmp example */
#include <stdio.h>
#include <string.h>

int main ()
{
   char str1[15];
   char str2[15];
   int ret;


   strcpy(str1, "abcdef");
   strcpy(str2, "ABCDEF");

   ret = strncmp(str1, str2, 4);

   if(ret < 0)
   {
      printf("str1 小于 str2");
   }
   else if(ret > 0) 
   {
      printf("str2 小于 str1");
   }
   else 
   {
      printf("str1 等于 str2");
   }
   
   return(0);
}
シミュレーションの実装:
/* simulation of strncmp1*/
#include <stdio.h>
#include <string.h>
int Strncmp(const char* str1, const char* str2, size_t n)
{
	while (n && (*str1 && *str2) && (*str1++ == *str2++)) n--;
	if (!*str1 && !*str2) return 0;
	else if (!*str1) return -1;
	else if (!*str2) return 1;
	else return *str1 - *str2;
}

int main()
{
	char str1[15];
	char str2[15];
	int ret;


	strcpy(str1, "abcdef");
	strcpy(str2, "ABCDEF");

	ret = strncmp(str1, str2, 4);

	if (ret < 0)
	{
		printf("str1 小于 str2");
	}
	else if (ret > 0)
	{
		printf("str2 小于 str1");
	}
	else
	{
		printf("str1 等于 str2");
	}

	return(0);
}
/* simulation of strncmp2*/
#include <stdio.h>
#include <string.h>
int Strncmp(const char* str1, const char* str2, size_t n)
{
	int res = 0;
	while (n && (*str1 && *str2) && !(res = *str1++ - *str2++)) n--;
	if (!n) return 0;
	if (res < 0) return -1;
	else return 1;
}

int main()
{
	char str1[15];
	char str2[15];
	int ret;


	strcpy(str1, "ABCdef");
	strcpy(str2, "ABCDEF");

	ret = strncmp(str1, str2, 3);

	if (ret < 0)
	{
		printf("str1 小于 str2");
	}
	else if (ret > 0)
	{
		printf("str2 小于 str1");
	}
	else
	{
		printf("str1 等于 str2");
	}

	return(0);
}

/* simulation of strncmp3 鲍*/
#include <stdio.h>
#include <string.h>

int Strncmp(
	const char* first,
	const char* last,
	size_t     count)
{
	assert(first != NULL);
	assert(last  != NULL);

	while (count && *first == *last)
	{
		first++,last++;
		count--;
	}
	return (int)(*first - *last);
}

int main()
{
	char str1[15];
	char str2[15];
	int ret;


	strcpy(str1, "ABCdef");
	strcpy(str2, "ABCDEF");

	ret = strncmp(str1, str2, 3);

	if (ret < 0)
	{
		printf("str1 小于 str2");
	}
	else if (ret > 0)
	{
		printf("str2 小于 str1");
	}
	else
	{
		printf("str1 等于 str2");
	}

	return(0);
}

ライブラリでの実装:
/*Strncmp in lib*/
int __cdecl strncmp
(
    const char *first,
    const char *last,
    size_t      count
)
{
    size_t x = 0;

    if (!count)
    {
        return 0;
    }

    /*
     * This explicit guard needed to deal correctly with boundary
     * cases: strings shorter than 4 bytes and strings longer than
     * UINT_MAX-4 bytes .
     */
    if( count >= 4 )
    {
        /* unroll by four */
        for (; x < count-4; x+=4)
        {
            first+=4;
            last +=4;

            if (*(first-4) == 0 || *(first-4) != *(last-4))
            {
                return(*(unsigned char *)(first-4) - *(unsigned char *)(last-4));
            }

            if (*(first-3) == 0 || *(first-3) != *(last-3))
            {
                return(*(unsigned char *)(first-3) - *(unsigned char *)(last-3));
            }

            if (*(first-2) == 0 || *(first-2) != *(last-2))
            {
                return(*(unsigned char *)(first-2) - *(unsigned char *)(last-2));
            }

            if (*(first-1) == 0 || *(first-1) != *(last-1))
            {
                return(*(unsigned char *)(first-1) - *(unsigned char *)(last-1));
            }
        }
    }

    /* residual loop */
    for (; x < count; x++)
    {
        if (*first == 0 || *first != *last)
        {
            return(*(unsigned char *)first - *(unsigned char *)last);
        }
        first+=1;
        last+=1;
    }

    return 0;
}


char * strstr(const char * haystack、const char * needle)

#include <string.h>

haystack-取得するC文字列。
針-干し草の山の文字列で検索される小さな文字列。
戻り値:
この関数は、干し草の山に針のひもが最初に現れる位置を返します。見つからない場合はnullを返します。

例:
/* strstr example */
#include <stdio.h>
#include <string.h>
int main()
{
	const char haystack[20] = "RUNOOB";
	const char needle[10] = "NOOB";
	const char* ret = NULL;

	ret = strstr(haystack, needle);

	printf("子字符串是: %s\n", ret);

	return(0);
}
関数strstrのプロトタイプはchar * strstr(char * str1、char * str2)です。その関数は、str1で指定された文字列str2が最初に出現する位置を返すことです。 シミュレーションの実装:
/*simulation of strstr1*/
#include <stdio.h>
#include <string.h>

char* Strstr(const char* str1, const char* str2)
{
	const char* p1 = str1;
	while (*p1++);  //p指向'\0'后面
	int length1 = p1 - str1 - 1;

	const char* p2 = str2;
	while (*p2++);  //p指向'\0'后面
	int length2 = p2 - str2 - 1;

	//while(*p2)  p2++;  //p指向'\0'
	//int length2 = p2 - str2; 

	int nums = length1 - length2 + 1;

	for (int i = 0; i < nums; ++i)
	{
		if (!strncmp(str1 + i, str2, length2))
			return (char*)(str1 + i);
	}
	return nullptr;
}

int main()
{
	char haystack[20] = "RUNOOB";
	char needle[10] = "NOOB";
	char* ret = NULL;

	ret = Strstr(haystack, needle);

	printf("子字符串是:%s\n", ret);

	return(0);
}

/*simulation of strstr2*/
#include <stdio.h>
#include <string.h>

char* Strstr(const char* str1, const char* str2)
{
	const char* p1 = str1;
	while (*p1++);  //p指向'\0'后面
	int length1 = p1 - str1 - 1;

	const char* p2 = str2;
	while (*p2++);  //p指向'\0'后面
	int length2 = p2 - str2 - 1;

	//while(*p2)  p2++;  //p指向'\0'
	//int length2 = p2 - str2; 

	int nums = length1 - length2 + 1;
	for (int i = 0; i < nums; ++i)
	{
		//if (!strncmp(str1 + i, str2, length2))
		int flag = 0;
		for (int j = 0; j < length2; ++j)
		{
			if (*(str1 + i + j) == *(str2 + j))
				flag = 1;
			else
				flag = 0;
		}
		if(flag)
			return (char*)(str1 + i);
	}
	return nullptr;
}

int main()
{
	char haystack[20] = "RUNOOB";
	char needle[10] = "NOOB";
	char* ret = nullptr;

	ret = Strstr(haystack, needle);

	printf("子字符串是:%s\n", ret);

	return(0);
}

/*strstr in lib*/



char * strtok(char * str、const char *区切り文字);

#include <string.h>

Cライブラリ関数char * strtok(char *> str、const char * delim)は、文字列strを文字列のセットとして区切り、delimを区切り文字として区切ります。

例:
/* strtok example1 */
#include <stdio.h>
#include <string.h>

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;
}
/* strtok example2 */
#include <string.h>
#include <stdio.h>
 
int main () {
   char str[80] = "This is - www.runoob.com - website";
   const char s[2] = "-";
   char *token;
   
   /* 获取第一个子字符串 */
   token = strtok(str, s);
   
   /* 继续获取其他的子字符串 */
   while( token != NULL ) {
      printf( "%s\n", token );
    
      token = strtok(NULL, s);
   }
   
   return(0);
}
シミュレーションが実行されます。
/*simulation of strtok*/


ライブラリでの実装:
/*strtok in lib  1*/
/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */
#include <string.h>

char* strtok(char *s, const char *delim)
{
  const char *spanp;
  int c, sc;
  char *tok;
  static char *last;

  if (s == NULL && (s = last) == NULL)
    return (NULL);
  /*
   * Skip (span) leading delimiters (s += strspn(s, delim), sort of).
   * 跳过字符串首部的分隔符
   */
 cont:
  c = *s++;
  for (spanp = delim; (sc = *spanp++) != 0;) {
    if (c == sc)
      goto cont;
  }
  
  /*
   *分割符后面没有字符串了
   */
  if (c == 0) {                 /* no non-delimiter characters */
    last = NULL;
    return (NULL);
  }
  tok = s - 1;    /*分割符后面还有字符串,将tok指向字符串首部(不包括分隔符)*/

  /*
   * Scan token (scan for delimiters: s += strcspn(s, delim), sort of).
   * Note that delim must have one NUL; we stop if we see that, too.
   * 循环字符串中的字符,直到找到分隔符或者结束符,并替换成结束符
   */
  for (;;) {
    c = *s++;
    spanp = delim;
    /*
     *判断字符串中的某字符是否是分割符中的字符
     *如果是,将分隔符替换成结束符并返回tok;
     *如果不是,继续判断下一个字符
     */
    do {
      if ((sc = *spanp++) == c) {
        if (c == 0)
          s = NULL;
        else
          s[-1] = 0;
        last = s;
        return (tok);
      }
    } while (sc != 0);
  }
  /* NOTREACHED */
}
/*strtok in lib  2*/
#ifdef _SECURE_VERSION
#define _TOKEN *context
#else  /* _SECURE_VERSION */
#define _TOKEN ptd->_token
#endif  /* _SECURE_VERSION */
 
#ifdef _SECURE_VERSION
char * __cdecl strtok_s (
        char * string,
        const char * control,
        char ** context
        )
#else  /* _SECURE_VERSION */
char * __cdecl strtok (
        char * string,
        const char * control
        )
#endif  /* _SECURE_VERSION */
{
        unsigned char *str;
        const unsigned char *ctrl = control;
 
        unsigned char map[32];
        int count;
 
#ifdef _SECURE_VERSION
 
        /* validation section */
        _VALIDATE_RETURN(context != NULL, EINVAL, NULL);
        _VALIDATE_RETURN(string != NULL || *context != NULL, EINVAL, NULL);
        _VALIDATE_RETURN(control != NULL, EINVAL, NULL);
 
        /* no static storage is needed for the secure version */
 
#else  /* _SECURE_VERSION */
 
        _ptiddata ptd = _getptd();
 
#endif  /* _SECURE_VERSION */
 
        /* Clear control map */
        for (count = 0; count < 32; count++)
                map[count] = 0;
 
        /* Set bits in delimiter table */
        do {
                map[*ctrl >> 3] |= (1 << (*ctrl & 7));
        } while (*ctrl++);
 
        /* Initialize str */
 
        /* If string is NULL, set str to the saved
         * pointer (i.e., continue breaking tokens out of the string
         * from the last strtok call) */
        if (string)
                str = string;
        else
                str = _TOKEN;
 
        /* Find beginning of token (skip over leading delimiters). Note that
         * there is no token iff this loop sets str to point to the terminal
         * null (*str == '\0') */
        while ( (map[*str >> 3] & (1 << (*str & 7))) && *str )
                str++;
 
        string = str;
 
        /* Find the end of the token. If it is not the end of the string,
         * put a null there. */
        for ( ; *str ; str++ )
                if ( map[*str >> 3] & (1 << (*str & 7)) ) {
                        *str++ = '\0';
                        break;
                }
 
        /* Update nextoken (or the corresponding field in the per-thread data
         * structure */
        _TOKEN = str;
 
        /* Determine if a token has been found. */
        if ( string == str )
                return NULL;
        else
                return string;
}


ストラー

#include <string.h>

Cライブラリ関数char * strerror(int errnum)は、内部配列からエラー番号errnumを検索し、エラーメッセージ文字列へのポインタを返します。strerrorによって生成されるエラー文字列は、開発プラットフォームとコンパイラによって異なります。
宣言
以下は、strerror()関数の宣言です。
char * strerror(int errnum)
パラメーター
errnum-エラー番号、通常はerrno。
戻り値
この関数は、エラーerrnumを説明するエラー文字列へのポインタを返します。

例:
/* strerror example */
#include <stdio.h>
#include <string.h>
#include <errno.h>

int main ()
{
   FILE *fp;

   fp = fopen("file.txt","r");
   if( fp == NULL ) 
   {
      printf("Error: %s\n", strerror(errno));
   }
   
  return(0);
}

おすすめ

転載: blog.csdn.net/qq_43808700/article/details/112706562