【相干学习保举:php编程(视频)】
各人都晓得 libc 的 printf()
及其家族。本章节将具体引见 PHP 申明以及应用的许多克隆,它们的指标是甚么,为何应用它们,和什么时候应用它们。
留意
Libc 中对于
printf()
及其冤家的文档位于此处。
你晓得这些函数颇有用,但有时无奈提供足够的性能。另外,你晓得向 printf()
增加格局字符串并不是易事,不便携性以及有平安危险。
PHP 增加了本人的相似于 printf 的函数,庖代了 libc 的,而且由外部开发者应用。他们次要增加新的格局,并应用 zend_string替代 char *
等等,让咱们一同来看看。
正告
你必需把握 libc 默许
printf()
格局。请浏览它们的文档。留意
增加了这些函数以 庖代 libc 函数,象征着假如你应用了
sprintf()
,没有会应用到 libc 的sprintf()
,而是 PHP 庖代了。除了了传统的printf()
外,其余内容均被交换。
传统用处
起首,你不该该应用 sprintf()
,由于该函数没有执行任何反省,而且招致许多缓冲区溢犯错误。请防止应用它。
正告
尽可能防止应用
sprintf()
。
而后,你有一些抉择。
你晓得后果缓冲区的巨细
假如你晓得缓冲区巨细,snprintf()
或许 slprintf()
均可以应用。这些函数尽管正在前往上没有同,然而它们的性能是同样的。
这两个都是依据通报的格局来打印,而且无论发作甚么,城市经过一个NUL
字节 ‘\0’来终止你的缓冲区。 然而,snprintf()
前往能够应用的字符数,而slprintf()
前往能够无效应用的字符数,因而能够检测太小的缓冲区以及字符串截断。这个没有管帐算最初的‘\0’。
这里有个例子,以便你齐全明确:
char foo[8]; /* 8字符巨细的缓冲区 */ const char str[] = "Hello world"; /* 12个字符,蕴含 \0 */ int r; r = snprintf(foo, sizeof(foo), "%s", str); /* r = 11 ,即便这里只有7个可打印的字符可写入 foo */ /* foo 的值如今是 'H' 'e' 'l' 'l' 'o' ' ' 'w' '\0' */
snprintf()
没有是一个好用的函数,由于它没有容许反省最初的字符串截断。就像下面例子你看到的,显然“Hello world\0”没有适宜8字节的缓冲区,然而 snprintf()
依然前往11给你,这是 strlen("Hello world\0")
的值。你不方法反省字符串被截断了。
这是 slprintf()
:
char foo[8]; /* 8字符年夜的缓冲区 */ const char str[] = "Hello world"; /* 12个字符,蕴含 \0 */ int r; r = slprintf(foo, sizeof(foo), "%s", str); /* r = 7 ,由于7个可打印的字符被写入 foo */ /* foo 如今的值是 'H' 'e' 'l' 'l' 'o' ' ' 'w' '\0' */
应用 slprintf()
,后果缓冲区 foo
蕴含齐全相反的字符串,然而现在前往值为7。7少于 “Hello world” 字符串的11个字符,以是你能够反省它被截断了:
if (slprintf(foo, sizeof(foo), "%s", str) < strlen(str)) { /* 发作字符串截断 */ }
记住:
- 这两个函数老是以
NUL
终止字符串,不论能否截断。终极的字符串是平安的 C 字符串。 - 只有
slprintf()
会反省字符串截断。
这两个函数正在 main/snprintf.c 中有具体引见。
你没有晓得缓冲区巨细
如今假如你没有晓得后果缓冲区巨细,则需求静态调配一个,而且应用spprintf()
。记住,你必需本人开释缓冲区。
这是例子:
#include <time.h> char *result; int r; time_t timestamp = time(NULL); r = spprintf(&result, 0, "Here is the date: %s", asctime(localtime(×tamp))); /* 如今后果相似:"Here is the date: Thu Jun 15 19:12:51 2017\n" */ efree(result);
spprintf()
前往被打印到后果缓冲区的字符数,没有包罗最初的‘\0’, 因而,你晓得调配给你的字节数(减一)是几何。
请留意,是应用 ZendMM(申请调配)调配的,因而应作为申请的一局部应用,并应用 efree()
而没有是free()
开释。
留意
Zend 内存治理章节 (ZendMM) 具体引见若何经过 PHP 调配静态内存。
假如你想要限度缓冲区巨细,则将限度通报给第二个参数,假如你通报 0,象征着有限制:
#include <time.h> char *result; int r; time_t timestamp = time(NULL); /* 打印没有超越 10 个字节 ||调配超越 11 个字节 */ r = spprintf(&result, 10, "Here is the date: %s", asctime(localtime(×tamp))); /* r == 10,而且给后果调配 11 个字节 */ efree(result);
留意
尽可能没有要应用静态内存调配。这会影响执功能。假如有抉择,则选动态货仓旅馆调配缓冲区。
spprintf()
写正在 main/spprintf.c 中。
那末 printf() 呢?
假如你需求 printf()
,即打印格局化到输入流,则应用php_printf()
。该函数正在外部应用 spprintf()
,因而执举动态调配,以便将其发送到 SAPI 输入(正在 CLI 的状况下又称为 stdout),或输入缓冲区(CGI 缓冲区)后将其开释,用于其余 SAPI。
非凡的 PHP printf 格局
记住,PHP 经过本人设计,庖代了不少 libc 的 printf()
函数。你能够从浏览源代码中查看易于了解的参数解析 API。
这象征着解析算法的参数已齐全被重写,而且可能与你正在 libc 应用的没有同。即,正在年夜少数状况下,没有会存眷 libc 环境。
可能会应用非凡的格局,就像 “%I64” 打印64位 int,或许“%I32”。你也能够应用 “%Z” 去打印 zval(依据 PHP 规定转换为字符串),这是一个没有错的增补。
该格局化顺序也意识无量数,并打印 “INF”,或许将非数字打印为 “NAN”。
假如你谬误的申请格局化顺序打印一个 NULL
指针,libc 一定会解体,而 PHP 会将 “(null)” 作为后果字符串前往。
留意
假如正在打印中你看到神秘的 “(null)” 呈现,象征着你将 NULL 指针通报给了 PHP printf 系列函数之一。
Printf() 到 zend_strings
zend_string 作为 PHP 源代码里十分常见的构造,你可能需求 printf()
到 zend_string
,而没有是传统的 char *
。为此,请应用strpprintf()
。
该 API 是 zend_string *strpprintf(size_t max_len, const char *format, ...)
,象征着前往zend_string
给你,而没有是你希冀的可打印字符数。不外你能够限度应用第一个参数来限度该数(通报 0 示意无量年夜);而且你肯定要记住将应用 Zend 内存治理调配 zend_string
,并因而绑定以后申请。
显然,该格局 API 与下面看到的同享。
这有个例子:
zend_string *result; result = strpprintf(0, "You are using PHP %s", PHP_VERSION); /* 对后果做些甚么 */ zend_string_release(result);
对于 zend_
API 的正文
您可能会遇到 zend_spprintf()
或 zend_strpprintf()
函数。这些与下面看到的齐全相反。
这只是 Zend 引擎以及 PHP 外围之间别离的一局部,这个细节对咱们其实不首要,由于正在源码中,一切内容都是夹杂正在一同的。
想理解更多编程学习,敬请存眷php培训栏目!
以上就是PHP自界说的 printf 函数新用处的具体内容,更多请存眷资源魔其它相干文章!
标签: php php开发教程 php开发资料 php开发自学 printf
抱歉,评论功能暂时关闭!