strtok() strerror()

263 阅读5分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第28天,点击查看活动详情

🚩write in front🚩

🔎大家好,我是泽奀,希望你看完后。能对你有所帮助,不足请指正,共同学习交流🔎
🏅2021年度博客之星物联网与嵌入式开发TOP5~2021博客之星Top100~阿里云专家^星级博主~掘金⇿InfoQ创作者~周榜77»总榜1766🏅
🆔本文由 謓泽 原创 掘金/CSDN/infoQ 如需转载还请通知⚠
📝个人主页-掘金 (juejin.cn)💬
🎁欢迎各位→点赞👍 + 收藏⭐️ + 留言📝​
📣系列专栏-[C系列] 从0到1 - 泽奀的专栏 - 掘金 (juejin.cn)🎓
✉️我们并非登上我们所选择的舞台,演出并非我们所选择的剧本📩

 🎍strtok()函数代码示例🎍

题目:把字符串"Hello.Cyuyan.yyds",.之前语句进行分割最后进行打印。用strtok字符串函数实现。

使用 ****strtok() ****函数代码示例如下 👇

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

int main(void)
{
	char str[] = "Hello.Cyuyan.yyds";
	printf("yiduanhua|%s|dezifu\n", str);
	char * pch=strtok(str, ".");
	while (pch != NULL)
	{
		printf("%s\n", pch);
		pch = strtok(NULL, ".");
	}
	return 0;
}

运行结果如下 👇 

Hello.Cyuyan.yyds

Hello

Cyuyan

yyds

不知道你是否明白了( ゚д゚)つ

在这里思考下,那么它使用什么进行保存的呢?就是这个函数它能够记住地址,其实这个只需要用到一个关键字 static 静态局部变量就可以完美实现这种类似于记忆功能,把生命周期延长,出了函数的范围内不会销毁保留原来的值。

​编辑


🎍strtok()源程序实现🎍

示例代码如下:👇  

/***
*strtok.c - tokenize a string with given delimiters
*
*       Copyright (c) Microsoft Corporation. All rights reserved.
*
*Purpose:
*       defines strtok() - breaks string into series of token
*       via repeated calls.
*
*******************************************************************************/

#include <cruntime.h>
#include <string.h>
#ifdef _SECURE_VERSION
#include <internal.h>
#else  /* _SECURE_VERSION */
#include <mtdll.h>
#endif  /* _SECURE_VERSION */

/***
*char *strtok(string, control) - tokenize string with delimiter in control
*
*Purpose:
*       strtok considers the string to consist of a sequence of zero or more
*       text tokens separated by spans of one or more control chars. the first
*       call, with string specified, returns a pointer to the first char of the
*       first token, and will write a null char into string immediately
*       following the returned token. subsequent calls with zero for the first
*       argument (string) will work thru the string until no tokens remain. the
*       control string may be different from call to call. when no tokens remain
*       in string a NULL pointer is returned. remember the control chars with a
*       bit map, one bit per ascii char. the null char is always a control char.
*
*Entry:
*       char *string - string to tokenize, or NULL to get next token
*       char *control - string of characters to use as delimiters
*
*Exit:
*       returns pointer to first token in string, or if string
*       was NULL, to next token
*       returns NULL when no more tokens remain.
*
*Uses:
*
*Exceptions:
*
*******************************************************************************/

#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;
}

​编辑


🎍strerror() - 返回错误码🎍 

该函数的功能是:返回错误码,所对应的错误信息。

strerror()  函数的声明方式如下 👇 

char * strerror ( int errnum );

获取指向错误消息字符串的指针。

errnum的值,生成一个字符串,该字符串带有一条描述错误条件的消息,就像库的函数设置为errno一样。头文件是: #include <errno.h>

返回的指针指向一个静态分配的字符串,该字符串不能被程序修改。对该函数的进一步调用可能会覆盖其内容(为了避免数据竞争,不需要特定的库实现)。

strerror产生的错误字符串可能特定于每个系统和库实现。

返回值:该函数返回一个指向错误字符串的指针,该错误字符串描述了错误 errnum。

🎍strerror()函数代码示例🎍

打开文件函数是:fopen()

#include <stdio.h>
#include <string.h>
#include <errno.h>
int main(void)
{
	FILE* Pf = fopen("test.txt", "r");//打开文件如果以读的形式存在那么这个文件就会打开失败!
	//一旦打开失败那个得到的就是NULL
	if (Pf == NULL)
	{
		printf("%s\n", strerror(errno));
		return 1;//返回main函数结束
	}
	fclose(Pf);
	Pf = NULL;
	return 0;
}

运行结果如下 👇 

Error: No such file or directory 

当然如果你在安装路径新建上一个test.txt文件就不会显示如上问题。

🎍strerror()源程序实现🎍

示例代码如下:👇  

#include <cruntime.h>
#include <errmsg.h>
#include <stdlib.h>
#include <syserr.h>
#include <string.h>
#include <mtdll.h>
#include <tchar.h>
#include <malloc.h>
#include <stddef.h>
#include <dbgint.h>
#include <internal.h>

/* [NOTE: The error message buffer is shared by both strerror
   and _strerror so must be the max length of both. */
/* Max length of message = user_string(94)+system_string+2 */
#define _ERRMSGLEN_ (94+_SYS_MSGMAX+2)

#ifdef _UNICODE
#define _terrmsg    _werrmsg
#else  /* _UNICODE */
#define _terrmsg    _errmsg
#endif  /* _UNICODE */

/***
*char *strerror(errnum) - Map error number to error message string.
*
*Purpose:
*       The strerror runtime takes an error number for input and
*       returns the corresponding error message string.  This routine
*       conforms to the ANSI standard interface.
*
*Entry:
*       int errnum - Integer error number (corresponding to an errno value).
*
*Exit:
*       char * - Strerror returns a pointer to the error message string.
*       This string is internal to the strerror routine (i.e., not supplied
*       by the user).
*
*Exceptions:
*       None.
*
*******************************************************************************/

#ifdef _UNICODE
wchar_t * cdecl _wcserror(
#else  /* _UNICODE */
char * __cdecl strerror (
#endif  /* _UNICODE */
        int errnum
        )
{
        _TCHAR *errmsg;
        _ptiddata ptd = _getptd_noexit();
        if (!ptd)
                return _T("Visual C++ CRT: Not enough memory to complete call to strerror.");

        if ( (ptd->_terrmsg == NULL) && ((ptd->_terrmsg =
                        _calloc_crt(_ERRMSGLEN_, sizeof(_TCHAR)))
                        == NULL) )
                return _T("Visual C++ CRT: Not enough memory to complete call to strerror.");
        else
                errmsg = ptd->_terrmsg;

#ifdef _UNICODE
        _ERRCHECK(mbstowcs_s(NULL, errmsg, _ERRMSGLEN_, _get_sys_err_msg(errnum), _ERRMSGLEN_ - 1));
#else  /* _UNICODE */
        _ERRCHECK(strcpy_s(errmsg, _ERRMSGLEN_, _get_sys_err_msg(errnum)));
#endif  /* _UNICODE */

        return(errmsg);
}

/***
*errno_t strerror_s(buffer, sizeInTChars, errnum) - Map error number to error message string.
*
*Purpose:
*       The strerror_s runtime takes an error number for input and
*       copies the corresponding error message string in the destination
*       buffer. If the buffer is too small, the message is truncated.
*
*Entry:
*       TCHAR * buffer - Destination buffer.
*       size_t sizeInTChars - Size of the destination buffer.
*       int errnum - Integer error number (corresponding to an errno value).
*
*Exit:
*       The error code.
*
*Exceptions:
*       Input parameters are validated. Refer to the validation section of the function.
*
*******************************************************************************/

#ifdef _UNICODE
errno_t __cdecl _wcserror_s(
#else  /* _UNICODE */
errno_t __cdecl strerror_s(
#endif  /* _UNICODE */
        TCHAR* buffer,
        size_t sizeInTChars,
        int errnum
        )
{
        errno_t e = 0;

        /* validation section */
        _VALIDATE_RETURN_ERRCODE(buffer != NULL, EINVAL);
        _VALIDATE_RETURN_ERRCODE(sizeInTChars > 0, EINVAL);

        /* we use mbstowcs_s or strncpy_s because we want to truncate the error string
         * if the destination is not big enough
         */
#ifdef _UNICODE
        e = _ERRCHECK_EINVAL_ERANGE(mbstowcs_s(NULL, buffer, sizeInTChars, _get_sys_err_msg(errnum), _TRUNCATE));
        /* ignore the truncate information */
        if (e == STRUNCATE)
        {
                e = 0;
        }
#else  /* _UNICODE */
        _ERRCHECK(strncpy_s(buffer, sizeInTChars, _get_sys_err_msg(errnum), sizeInTChars - 1));
#endif  /* _UNICODE */
    return e;
}

✨最后✨

字符串函数的使用是我们必须要掌握的知识点很多面试知识点包括对于程序当中运用到字符串函数的形式还是比较多的,所以我们是必须要了解掌握这个知识点的。尽管知识点比较多,但是我们还是要好好吸收消化这个知识点的。听说长按收藏按钮会有惊喜╰(°▽°)╯