C语言 字符串处理函数strtok第二次及以后的调用中第一个参数要用NULL的原因是啥? 能不能解释下原理?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C语言 字符串处理函数strtok第二次及以后的调用中第一个参数要用NULL的原因是啥? 能不能解释下原理?相关的知识,希望对你有一定的参考价值。
RT
编程中的NULL一.NULL字符
在ASCII码的第一个字符是NULL,它的数值是0,占用1字节;C语言把它作为字符串的最后一个字符,以表示字符串到此结束."\0"
二.NULL指针
在C语言的头文件stddef.h中,NULL的定义如下: #ifndef NULL #ifdef __cplusplus #define NULL 0 #else #define NULL ((void *)0) #endif #endif #interface NULL 0 可见,NULL指针是一个无类型指针,并且值为0。一个指针,拥有2个属性--地址值和指针类型。两者的作用是:1,地址值标识变量的首地址(32位系统下指针的地址值占4字节);2,指针类型告诉编译器,应该怎样进行接下来的数据访问(int型数组和float型数组是不同的;数组访问与结构体访问也是不同的;等等)。 NULL的出现是一种约定俗成,事实上它不是C语言中的关键字;把一个指针赋值为NULL,通常的说法是“将指针悬空”。这样,指针就无法再进行任何数据访问了。编程工作中有一类比较容易犯的错误--指针地址未进行正确的更新赋值就加以使用,这往往会造成很严重的后果(对内存区进行错误的涂抹)。所以一个良好的习惯是,当一个指针的工作稍事休息,先把它赋值为NULL,待到再度使用时,重新对其赋值以及进行指针类型转化。 前面说到“NULL指针无法再进行任何数据访问”,其实是视编译器功能而定的。0位置指向的是程序起始,对于不同的编译器,NULL指针的操作结果是不同的:有些是不准读写,有些是只读,甚至读写都允许。编译器是人定的。引用网友win_hate在话题“关于NULL的不严谨”中的话来说:“如果说有谁不严谨了,那必定是读取0位置的程序员,而不是C。C的设计哲学之一是:‘程序员知道自己在干什么--没有安全带’”。
三.数据库中的NULL
Null在数据库中表示 不知道的数据,主要有3种意思: 1)知道数据存在,但不知道具体值. 2)不知道数据是否存在. 3)数据不存在.
四.NULL与0的疑惑
NULL与0有着扯不断理还乱的关系,其实不那么高深。0本身有着一些原生的特性诸如:起始,没有,正负的分界线,0/1中的0还可以表示否定。NULL正需要这些特性中的一部分。 我们只需要清楚NULL的本质,并在合理的地方才加以利用而非滥用。譬如我想做一个比较某个整数i是否为0,难道写成i==NULL会比i==0更酷一点吗?
五.matlab中的函数
函数null用来求解零空间,即满足方程组A*X=0的解空间。实际上是求出解空间的一组解(基础解系)。 语法:z=null(A) %z的列向量为方程组的正交规范基,满足z‘ x z=I。 z=null(A,'r') %z的列向量是方程A*X=0的有理基。追问
您不是搞编程的就别复制了OK?谁不会用百度啊
参考技术A 源码:/***
*strtok.c - tokenize a string with given delimiters
*
* Copyright (c) 1989-1997, Microsoft Corporation. All rights reserved.
*
*Purpose:
* defines strtok() - breaks string into series of token
* via repeated calls.
*
*******************************************************************************/
#include <cruntime.h>
#include <string.h>
#ifdef _MT
#include <mtdll.h>
#endif /* _MT */
/***
*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:
*
*******************************************************************************/
char * __cdecl strtok (
char * string,
const char * control
)
unsigned char *str;
const unsigned char *ctrl = control;
unsigned char map[32];
int count;
#ifdef _MT
_ptiddata ptd = _getptd();
#else /* _MT */
static char *nextoken;
#endif /* _MT */
/* 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
#ifdef _MT
str = ptd->_token;
#else /* _MT */
str = nextoken;
#endif /* _MT */
/* 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 */
#ifdef _MT
ptd->_token = str;
#else /* _MT */
nextoken = str;
#endif /* _MT */
/* Determine if a token has been found. */
if ( string == str )
return NULL;
else
return string;
源码结束!!
/******************************************************
if (string) 这里就是为什么第二次str要赋值为NULL的原因
str = string;
else
#ifdef _MT
str = ptd->_token;
#else /* _MT */
str = nextoken;
#endif /* _MT */
××××××××××××××××××××××××××××××××××××××××/
/**************************************************************
以下是算法:
map[*ctrl >> 3] |= (1 << (*ctrl & 7))说明:
map[*ctrl >> 3] |= (1 << (*ctrl & 7));
这句是这样的意思
首先map[32]是个uchar型数组,数组每一个是8位,其中每一位可以表示一个字符,32×8=256,这样的话,map[32]中有256个bit,每个bit表示一个ASCII码,那么可以表示256个ASCII码。
*ctrl >> 3,表示将安ascii码,给其分类,*ctrl >> 3表示,除以8的意思,将ascii每八位分为一组,也就是map[32]中的一个。
1 << (*ctrl & 7),这个是这样的意思,7表示为二进制就是00000111,这样的话,相当于是一个数除以8后剩余的余数。1 << (*ctrl & 7),就是将二进制00000001,向右移动(*ctrl & 7)个位。
map[*ctrl >> 3] |= (1 << (*ctrl & 7)),就是表示将map[*ctrl >> 3]中的(*ctrl & 7)+1位设为1,表示在该位置查询到一个ascii字符。
这样做以后,就相当于简历了一个表,只要查询相应的位是否为1,就知道该字符,在strtok的字符串中是否出现过。
××××××××××××××××××××××××××××××××/追问
好吧 C++我这个初学者看不懂
追答好吧,既然是初学者,建议先会用,用好了,用的多了,再去研究函数的源码。
简单的说一下,第二次NULL主要是为了告诉函数,这是第二次用了。给你举一个简单的例子:
int myprint(char *name)
static char tmp[32];
if(name==NULL)
printf("hello %s\n",tmp);
else
strncpy(tmp,name,32);
printf("Are you %s ?\n",name);
int main()
myprint("jone");
myprint(NULL);
参考资料:http://blog.csdn.net/xtlcq/article/details/3378042
本回答被提问者采纳以上是关于C语言 字符串处理函数strtok第二次及以后的调用中第一个参数要用NULL的原因是啥? 能不能解释下原理?的主要内容,如果未能解决你的问题,请参考以下文章
C语言字符串相关函数使用示例 strtok_r strstr strtok atoi
C语言最短时间带你实现strtok,字符串分割函数,建议收藏!!!