sprintf你知道多少

sprintf你知道多少
sprintf你知道多少

在将各种类型的数据构造成字符串时,sprintf的强大功能很少会让你失望。由于sprintf跟printf 在用法上几乎一样,只是打印的目的地不同而已,前者打印到字符串中,后者则直接在命令行上输出。这也导致sprintf比printf有用得多。

sprintf是个变参函数,定义如下:

intsprintf( char *buffer, const char *format [, argument] ... );

除了前两个参数类型固定外,后面可以接任意多个参数。而它的精华,显然就在第二个参数:格式化字符串上。

printf和sprintf都使用格式化字符串来指定串的格式,在格式串内部使用一些以“%”开头的格式说明符(format specifications)来占据一个位置,在后边的变参列表中提供相应的变量,最终函数就会用相应位置的变量来替代那个说明符,产生一个调用者想要的字符串。

格式化数字字符串

sprintf最常见的应用之一莫过于把整数打印到字符串中,所以,spritnf在大多数场合可以替代itoa。

如:

//把整数123 打印成一个字符串保存在s 中。

sprintf(s, "%d", 123); //产生"123"

可以指定宽度,不足的左边补空格:

sprintf(s, "%8d%8d", 123, 4567); //产生:" 123 4567"

当然也可以左对齐:

sprintf(s, "%-8d%8d", 123, 4567); //产生:"123 4567"

也可以按照16 进制打印:

sprintf(s, "%8x", 4567); //小写16 进制,宽度占8 个位置,右对齐

sprintf(s, "%-8X", 4568); //大写16 进制,宽度占8 个位置,左对齐

这样,一个整数的16 进制字符串就很容易得到,但我们在打印16 进制内容时,通常想要一种左边补0 的等宽格式,那该怎么做呢?很简单,在表示宽度的数字前面加个0 就可以了。sprintf(s, "%08X", 4567); //产生:"000011D7"

上面以”%d”进行的10 进制打印同样也可以使用这种左边补0 的方式。

这里要注意一个符号扩展的问题:比如,假如我们想打印短整数(short)-1 的内存16 进制表示形式,在Win32 平台上,一个short 型占2 个字节,所以我们自然希望用4 个16 进制数字来打印它:

short si = -1;

sprintf(s, "%04X", si);

产生“FFFFFFFF”,怎么回事?因为spritnf是个变参函数,除了前面两个参数之外,后面的参数都不是类型安全的,函数更没有办法仅仅通过一个“%X”就能得知当初函数调用前参数压栈时被压进来的到底是个4 字节的整数还是个2 字节的短整数,所以采取了统一4 字节的处理方式,导致参数压栈时做了符号扩展,扩展成了32 位的整数-1,打印时4 个位置不够了,就把32 位整数-1 的8 位16 进制都打印出来了。

如果你想看si的本来面目,那么就应该让编译器做0 扩展而不是符号扩展(扩展时二进制左边补0 而不是补符号位):

sprintf(s, "%04X", (unsigned short)si);

就可以了。或者:

unsigned short si = -1;

sprintf(s, "%04X", si);

sprintf和printf还可以按8 进制打印整数字符串,使用”%o”。注意8 进制和16 进制都不会打印出负数,都是无符号的,实际上也就是变量的内部编码的直接的16 进制或8 进制表示。

控制浮点数打印格式

浮点数的打印和格式控制是sprintf的又一大常用功能,浮点数使用格式符”%f”控制,默认保

留小数点后6 位数字,比如:

sprintf(s, "%f", 3.1415926); //产生"3.141593"

但有时我们希望自己控制打印的宽度和小数位数,这时就应该使用:”%m.nf”格式,其中m 表示打印的宽度,n 表示小数点后的位数。比如:

sprintf(s, "%10.3f", 3.1415626); //产生:" 3.142"

sprintf(s, "%-10.3f", 3.1415626); //产生:"3.142 "

sprintf(s, "%.3f", 3.1415626); //不指定总宽度,产生:"3.142"

注意一个问题,你猜

int i = 100;

sprintf(s, "%.2f", i);

会打出什么东东来?“100.00”?对吗?自己试试就知道了,同时也试试下面这个:

sprintf(s, "%.2f", (double)i);

第一个打出来的肯定不是正确结果,原因跟前面提到的一样,参数压栈时调用者并不知道跟i相对应的格式控制符是个”%f”。而函数执行时函数本身则并不知道当年被压入栈里的是个整数,于是可怜的保存整数i 的那4 个字节就被不由分说地强行作为浮点数格式来解释了,整个乱套了。不过,如果有人有兴趣使用手工编码一个浮点数,那么倒可以使用这种方法来检验一下你手工编排的结果是否正确。

字符/Ascii码对照

我们知道,在C/C++语言中,char 也是一种普通的scalable 类型,除了字长之外,它与short,int,long 这些类型没有本质区别,只不过被大家习惯用来表示字符和字符串而已。(或许当年该把

这个类型叫做“byte”,然后现在就可以根据实际情况,使用byte 或short 来把char 通过typedef 定义出来,这样更合适些)于是,使用”%d”或者”%x”打印一个字符,便能得出它的10 进制或16 进制的ASCII 码;反过来,使用”%c”打印一个整数,便可以看到它所对应的ASCII 字符。以下程序段把所有可见字符的ASCII 码对照表打印到屏幕上(这里采用printf,注意”#”与”%X”合用时自动为16 进制数增加”0X”前缀):

for(int i = 32; i < 127; i++) {

printf("[ %c ]: %3d 0x%#04X\n", i, i, i);

}

连接字符串

sprintf的格式控制串中既然可以插入各种东西,并最终把它们“连成一串”,自然也就能够连

接字符串,从而在许多场合可以替代strcat,但sprintf能够一次连接多个字符串(自然也可以同时

在它们中间插入别的内容,总之非常灵活)。比如:

char* who = "I";

char* whom = "CSDN";

sprintf(s, "%s love %s.", who, whom); //产生:"I love CSDN. "

strcat只能连接字符串(一段以’’结尾的字符数组或叫做字符缓冲,null-terminated-string),但有时我们有两段字符缓冲区,他们并不是以’’结尾。比如许多从第三方库函数中返回的字符数组,从硬件或者网络传输中读进来的字符流,它们未必每一段字符序列后面都有个相应的’’来结尾。如果直接连接,不管是sprintf还是strcat肯定会导致非法内存操作,而strncat也至少要求第一个参数是个null-terminated-string,那该怎么办呢?我们自然会想起前面介绍打印整数和浮点数时可以指定宽度,字符串也一样的。比如:

char a1[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G'};

char a2[] = {'H', 'I', 'J', 'K', 'L', 'M', 'N'};

如果:

sprintf(s, "%s%s", a1, a2); //Don't do that!

十有八九要出问题了。是否可以改成:

sprintf(s, "%7s%7s", a1, a2);

也没好到哪儿去,正确的应该是:

sprintf(s, "%.7s%.7s", a1, a2);//产生:"ABCDEFGHIJKLMN"

这可以类比打印浮点数的”%m.nf”,在”%m.ns”中,m 表示占用宽度(字符串长度不足时补空格,超出了则按照实际宽度打印),n 才表示从相应的字符串中最多取用的字符数。通常在打印字符串时m 没什么大用,还是点号后面的n 用的多。自然,也可以前后都只取部分字符:sprintf(s, "%.6s%.5s", a1, a2);//产生:"ABCDEFHIJKL"

在许多时候,我们或许还希望这些格式控制符中用以指定长度信息的数字是动态的,而不是静态指定的,因为许多时候,程序要到运行时才会清楚到底需要取字符数组中的几个字符,这种动态的宽度/精度设置功能在sprintf的实现中也被考虑到了,sprintf采用”*”来占用一个本来需要一个指定宽度或精度的常数数字的位置,同样,而实际的宽度或精度就可以和其它被打印的变量一样被提供出来,于是,上面的例子可以变成:

sprintf(s, "%.*s%.*s", 7, a1, 7, a2);

或者:

sprintf(s, "%.*s%.*s", sizeof(a1), a1, sizeof(a2), a2);

实际上,前面介绍的打印字符、整数、浮点数等都可以动态指定那些常量值,比如:

sprintf(s, "%-*d", 4, 'A'); //产生"65 "

sprintf(s, "%#0*X", 8, 128); //产生"0X000080","#"产生0X

sprintf(s, "%*.*f", 10, 2, 3.1415926); //产生" 3.14"

打印地址信息

有时调试程序时,我们可能想查看某些变量或者成员的地址,由于地址或者指针也不过是个32 位的数,你完全可以使用打印无符号整数的”%u”把他们打印出来:

sprintf(s, "%u", &i);

不过通常人们还是喜欢使用16 进制而不是10 进制来显示一个地址:

sprintf(s, "%08X", &i);

然而,这些都是间接的方法,对于地址打印,sprintf提供了专门的”%p”:

sprintf(s, "%p", &i);

我觉得它实际上就相当于:

sprintf(s, "%0*x", 2 * sizeof(void *), &i);

利用sprintf的返回值

较少有人注意printf/sprintf函数的返回值,但有时它却是有用的,spritnf返回了本次函数调用最终打印到字符缓冲区中的字符数目。也就是说每当一次sprinf调用结束以后,你无须再调用一次

strlen便已经知道了结果字符串的长度。如:

intlen = sprintf(s, "%d", i);

对于正整数来说,len便等于整数i 的10 进制位数。

下面的是个完整的例子,产生10 个[0, 100)之间的随机数,并将他们打印到一个字符数组s 中,以逗号分隔开。

#include

#include

#include

int main() {

srand(time(0));

char s[64];

int offset = 0;

for(int i = 0; i < 10; i++) {

offset += sprintf(s + offset, "%d,", rand() % 100);

}

s[offset - 1] = '\n';//将最后一个逗号换成换行符。

printf(s);

return 0;

}

设想当你从数据库中取出一条记录,然后希望把他们的各个字段按照某种规则连接成一个字

符串时,就可以使用这种方法,从理论上讲,他应该比不断的strcat效率高,因为strcat每次调用

都需要先找到最后的那个’’的位置,而在上面给出的例子中,我们每次都利用sprintf返回值把这个位置直接记下来了。

使用sprintf的常见问题

sprintf是个变参函数,使用时经常出问题,而且只要出问题通常就是能导致程序崩溃的内存访问错误,但好在由sprintf误用导致的问题虽然严重,却很容易找出,无非就是那么几种情况,通

常用眼睛再把出错的代码多看几眼就看出来了。

?? 缓冲区溢出

第一个参数的长度太短了,没的说,给个大点的地方吧。当然也可能是后面的参数的问

题,建议变参对应一定要细心,而打印字符串时,尽量使用”%.ns”的形式指定最大字符数。

?? 忘记了第一个参数

低级得不能再低级问题,用printf用得太惯了。//偶就常犯。:。(

?? 变参对应出问题

通常是忘记了提供对应某个格式符的变参,导致以后的参数统统错位,检查检查吧。尤

其是对应”*”的那些参数,都提供了吗?不要把一个整数对应一个”%s”,编译器会觉得你

欺她太甚了(编译器是obj和exe 的妈妈,应该是个女的,:P)。

strftime

sprnitf还有个不错的表妹:strftime,专门用于格式化时间字符串的,用法跟她表哥很像,也

是一大堆格式控制符,只是毕竟小姑娘家心细,她还要调用者指定缓冲区的最大长度,可能是为了在出现问题时可以推卸责任吧。这里举个例子:

time_t t = time(0);

//产生"YYYY-MM-DD hh:mm:ss"格式的字符串。

char s[32];

strftime(s, sizeof(s), "%Y-%m-%d %H:%M:%S", localtime(&t));

sprintf在MFC 中也能找到他的知音:CString::Format,strftime在MFC 中自然也有她的同道:CTime::Format,这一对由于从面向对象哪里得到了赞助,用以写出的代码更觉优雅。

C语言函数手册(DOC)

一、字符测试函数 isupper()测试字符是否为大写英文字 ispunct()测试字符是否为标点符号或特殊符号isspace()测试字符是否为空格字符 isprint()测试字符是否为可打印字符 islower()测试字符是否为小写字母 isgraphis()测试字符是否为可打印字符 isdigit()测试字符是否为阿拉伯数字 iscntrl()测试字符是否为ASCII码的控制字符isascii()测试字符是否为ASCII码字符 isalpha()测试字符是否为英文字母 isalnum()测试字符是否为英文或数字 isxdigit()测试字符是否为16进制数字 二、字符串操作函数 strtok()字符串分割函数 strstr()字符串查找函数 strspn()字符查找函数 strrchr()定位字符串中最后出现的指定字符 strpbrk()定位字符串中第一个出现的指定字符strncpy()复制字符串 strncat()字符串连接函数 strncasecmp()字符串比较函数(忽略大小写) strlen()字符串长度计算函数 strdup()复制字符串 strcspn()查找字符串 strcpy()复制字符串 strcoll()字符串比较函数(按字符排列次序) strcmp()字符串比较函数(比较字符串) strchr()字符串查找函数(返回首次出现字符的位置) strcat()连接字符串 strcasecmp()字符串比较函数(忽略大小写比较字符串) rindex()字符串查找函数(返回最后一次出现的位置) index()字符串查找函数(返回首次出现的位置) toupper()字符串转换函数(小写转大写) tolower()字符串转换函数(大写转小写) toascii()将整数转换成合法的ASCII码字符 strtoul()将字符串转换成无符号长整型数

Sprintf函数的用法

Sprintf函数的用法: 函数简介: 函数功能:把格式化的数据写入某个字符串 头文件:stdio.h 函数原型:int sprintf( char *buffer, const char *format, [ argument] … ) ; 返回值:字符串长度(strlen) 参数说明及应用举例 sprintf格式的规格如下所示。[]中的部分是可选的。 %[指定参数][标识符][宽度][.精度]指示符 若想输出`%'本身时, 请这样`%%'处理。 1. 处理字符方向。负号时表示从后向前处理。 2. 填空字元。0 的话表示空格填0;空格是内定值,表示空格就放着。 3. 字符总宽度。为最小宽度。 4. 精确度。指在小数点后的浮点数位数。 =-=-=-=-=-=-=-=-=-=-=-=-=-=-=- 转换字符 =-=-=-=-=-=-=-=-=-=-=-=-=-=-=- %% 印出百分比符号,不转换。 %c 整数转成对应的ASCII 字元。 %d 整数转成十进位。 %f 倍精确度数字转成浮点数。 %o 整数转成八进位。 %s 整数转成字符串。 %x 整数转成小写十六进位。 %X 整数转成大写十六进位。 我们的用法: Uchar sf[20],sd[20]; d=124; a = sprintf(sf,"%.0f",d); // Long(Int)到char字符串 d=12422.422; a = sprintf(sd,"%f",d); // float 到char字符串 a = sprintf(sd,"%.6f",d); // float 到char字符串 这两句相等;即浮点型转换时,小数位不指定情况下为最大6位; 注意:以防sd缓冲区溢出,待转换数据先做判断,大于0xFFFFFFFF

C语言中可变参数的用法

C语言中可变参数的用法 文章导读:我们在C语言编程中会遇到一些参数个数可变的函数,例如printf()这个函数,它的定义是这样的: int printf( const char* format, ...); 它除了有一个参数format固定以外,后面跟的参数的个数和类型是可变的,例如我们可以有以下不同的调用方法: printf("%d",i); printf("%s",s); printf("the number is %d ,string is:%s", i, s); 究竟如何写可变参数的C函数以及这些可变参数的函数编译器是如何实现的呢?本文就这个问题进行一些探讨,希望能对大家有些帮助.会C++的网友知道这些问题在C++里不存在,因为C++具有多态性.但C++是C的一个超集,以下的技术也可以用于C++的程序中.限于本人的水平,文中如果有不当之处,请大家指正. 我们在C语言编程中会遇到一些参数个数可变的函数,例如printf()这个函数,它的定义是这样的: int printf( const char* format, ...); 它除了有一个参数format固定以外,后面跟的参数的个数和类型是可变的,例如我们可以有以下不同的调用方法: printf("%d",i); printf("%s",s); printf("the number is %d ,string is:%s", i, s); 究竟如何写可变参数的C函数以及这些可变参数的函数编译器是如何实现的呢?本文就这个问题进行一些探讨,希望能对大家有些帮助.会C++的网友知道这些问题在C++里不存在,因为C++具有多态性.但C++是C 的一个超集,以下的技术也可以用于C++的程序中.限于本人的水平,文中如果有不当之处,请大家指正. (一)写一个简单的可变参数的C函数 下面我们来探讨如何写一个简单的可变参数的C函数.写可变参数的C函数要在程序中用到以下这些宏: void va_start( va_list arg_ptr, prev_param ); type va_arg( va_list arg_ptr, type ); void va_end( va_list arg_ptr ); va在这里是variable-argument(可变参数)的意思.这些宏定义在stdarg.h中,所以用到可变参数的程序应该包含这个头文件.下面我们写一个简单的可变参数的函数,改函数至少有一个整数参数,第二个参数也是整数,是可选的.函数只是打印这两个参数的值. void simple_va_fun(int i, ...) {

华为编程大赛试题2

客观题部分,共30分,建议这部分答题用40分钟。 一、单选题(每题1分,共10题) 1、以下叙述中不正确的是______。? A) 在不同的函数中可以使用相同名字的变量 B) 函数中的形式参数是局部变量 C) 在一个函数内定义的变量只在本函数范围内有效 D).在一个函数内的复合语句中定义的变量在本函数范围内有效(复合语句指函数中的 成对括号构成的代码)? 2、下列全局变量定义中,正确的是:______。 A) char abc [] []; B) char abc [] [NUM]; C) char abc [NUM] []; D) char abc [0]; 3、关于断言,错误的说法是:______。 A) 我们可以使用断言来发现软件问题。 B) 在正式发布的软件版本中也要保留断言,以便于定位问题。 C) 断言不能用于对外部输入数据的判断,只能用于程序内部逻辑的判断。 D) 不能用断言来代替错误处理。 4、关于函数参数,正确的说法是______。 A) 防止将函数的参数作为工作变量。 B) 应该为函数功能的扩展预留尽可能多的参数接口。 C) 通常函数内部会对函数参数进行合法性检查,为了提高效率,函数调用者不需要再 次进行参数合法性检查。 D) 不要输入指针变量。 5、关于函数实现,下面不正确的说法是______。 A) 为简单功能编写函数。 B) 函数的功能应该是可以预测的,也就是只要输入数据相同就应产生同样的输出。 C) 防止把没有关联的语句放到一个函数中。 D) 为了增强函数的可用性,应尽量设计多用途面面俱到的函数。 6、关于函数,不正确的说法是______。 A) 如果多段代码重复做同一件事情,那么在函数的划分上可能存在问题。 B) 功能不明确较小的函数,特别是仅有一个上级函数调用它时,应考虑把它合并到上 级函数中,而不必单独存在。 C) 对所调用函数的错误返回码可以根据需要决定是否处理。 D) 对于提供了返回值的函数,在引用时最好使用其返回值。 7、编程中下面说法错误的是______。 A) 编程时,要防止差1错误。如:把“<=”误写成“<”或“>=”误写成“>”。 B) 系统运行之初,要初始化有关变量及运行环境,防止未经初始化的变量被引用,但 可以使用操作系统的默认初始化值。 C) 有可能的话,if语句尽量加上else分支,对没有else分支的语句要小心对待; switch语句必须有default分支。 D) 要时刻注意易混淆的操作符,如C/C++中的“=”与“==”、“|”与“||”、“&” 与“&&”等。当编完程序后,应从头至尾检查一遍这些操作符,以防止拼写错误。

c语言关键字的用法详解优选稿

c语言关键字的用法详 解 集团文件版本号:(M928-T898-M248-WU2669-I2896-DQ586-M1988)

1.Static用法 1.1static声明的变量在C语言中有两方面的特征: 1)、变量会被放在程序的全局存储区中,这样可以在下一次调用的时候还可以保持原来的赋值。这一点是它与堆栈变量和堆变量的区别。 2)、变量用static告知编译器,自己仅仅在变量的作用范围内可见。这一点是它与全局变量的区别。 1.2特点 A.若全局变量仅在单个C文件中访问,则可以将这个变量修改为静态全局变量,以降低模块间的耦合度; B.若全局变量仅由单个函数访问,则可以将这个变量改为该函数的静态局部变量,以降低模块间的耦合度; C.设计和使用访问动态全局变量、静态全局变量、静态局部变量的函数时,需要考虑重入问题; D.如果我们需要一个可重入的函数,那么,我们一定要避免函数中使用static变量(这样的函数被称为:带“内部存储器”功能的的函数) E.函数中必须要使用static变量情况:比如当某函数的返回值为指针类型时,则必须是static的局部变量的地址作为返回值,若为auto类型,则返回为错指针。 函数前加static使得函数成为静态函数。但此处“static”的含义不是指存储方式,而是指对函数的作用域仅局限于本文件(所以又称内部函

数)。使用内部函数的好处是:不同的人编写不同的函数时,不用担心自己定义的函数,是否会与其它文件中的函数同名。 扩展分析:术语static有着不寻常的历史.起初,在C中引入关键字st atic是为了表示退出一个块后仍然存在的局部变量。随后,static在C 中有了第二种含义:用来表示不能被其它文件访问的全局变量和函数。为了避免引入新的关键字,所以仍使用static关键字来表示这第二种含义。最后,C++重用了这个关键字,并赋予它与前面不同的第三种含义:表示属于一个类而不是属于此类的任何特定对象的变量和函数(与Java 中此关键字的含义相同)。 1.3关键字static的作用是什么? 1.4 这个简单的问题很少有人能回答完全。在C语言中,关键字static有三个明显的作用: 1.4.1在函数体,一个被声明为静态的变量在这一函数被调用过程中维持其值不变。 int testStatic() { int x=1; x++; return x; }

CString用法

需要强制类型转化时,C++规则容许这种选择。比如,你可以将(浮点数)定义为将某个复数(有一对浮点数)进行强制类型转换后只返回该复数的第一个浮点数(也就是其实部)。可以象下面这样:Complex c(1.2f,4.8f);float realpart=c;如果(float)操作符定义正确的话,那么实部的的值应该是1.2。这种强制转化适合所有这种情况,例如,任何带有LPCTSTR类型参数的函数都会强制执行这种转换。于是,你可能有这样一个函数(也许在某个你买来的DLL中):BOOL DoSomethingCool(LPCTSTR s);你象下面这样调用它:CString file("c:¥¥myfiles¥¥coolstuff")BOOL result=DoSomethingCool(file);它能正确运行。因为DoSomethingCool函数已经说明了需要一个LPCTSTR类型的参数,因此LPCTSTR被应用于该参数,在MFC 中就是返回的串地址。如果你要格式化字符串怎么办呢?CString graycat("GrayCat");CString s;s.Format("Mew!I love%s",graycat);注意由于在可变参数列表中的值(在函数说明中是以"..."表示的)并没有隐含一个强制类型转换操作符。你会得到什么结果呢?一个令人惊讶的结果,我们得到的实际结果串是:"Mew!I love GrayCat"。因为MFC的设计者们在设计CString数据类型时非常小心,CString类型表达式求值后指向了字符串,所以这里看不到任何象Format或sprintf中的强制类型转换,你仍然可以得到正确的行为。描述CString的附加数据实际上在CString名义地址之后。有一件事情你是不能做的,那就是修改字符串。比如,你可能会尝试用","代替"."(不要做这样的,如果你在乎国际化问题,你应该使用十进制转换的National Language Support特性,),下面是个简单的例子:CString v("1.00");//货币金额,两位小数LPCTSTR p=v;p[lstrlen(p)-3]=,;这时编译器会报错,因为你赋值了一个常量串。如果你做如下尝试,编译器也会错:strcat(p,"each");因为strcat的第一个参数应该是LPTSTR类型的数据,而你却给了一个LPCTSTR。不要试图钻这个错误消息的牛角尖,这只会使你自己陷入麻烦!原因是缓冲有一个计数,它是不可存取的(它位于CString地址之下的一个隐藏区域),如果你改变这个串,缓冲中的字符计数不会反映所做的修改。此外,如果字符串长度恰好是该字符串物理限制的长度(梢后还会讲到这个问题),那么扩展该字符串将改写缓冲以外的任何数据,那是你无权进行写操作的内存(不对吗?),你会毁换坏不属于你的内存。这是应用程序真正的死亡处方。CString转化成char*之二:使用CString对象的GetBuffer方法;如果你需要修改CString中的内容,它有一个特殊的方法可以使用,那就是GetBuffer,它的作用是返回一个可写的缓冲指针。如果你只是打算修改字符或者截短字符串,你完全可以这样做:CString s(_T("File.ext"));LPTSTR p=s.GetBuffer();LPTSTR dot=strchr(p,.);//OK, should have used s.Find...if(p!=NULL)*p=_T(¥0);s.ReleaseBuffer();这是GetBuffer的第一种用法,也是最简单的一种,不用给它传递参数,它使用默认值0,意思是:"给我这个字符串的指针,我保证不加长它"。当你调用ReleaseBuffer时,字符串的实际长度会被重新计算,然后存入CString对象中。必须强调一点,在

sprintf的用法详解

sprintf函数:sprintf函数的使用方法 疯狂代码 https://www.360docs.net/doc/ee15985739.html,/ ?:http:/https://www.360docs.net/doc/ee15985739.html,/BlogDigest/Article75531.html sprintf() 格式化输出函数(图形) 功能: 函数sprintf()用来作格式化的输出。 用法: 此函数调用方式为int sprintf(char *string,char *format,arg_list); 说明: 函数sprintf()的用法和printf()函数一样,只是sprintf()函数给出第一个参数string(一般为字符数组),然后再调用outtextxy()函数将串里的字符显示在屏幕上。arg_list为参数表,可有不定个数。通常在绘图方式下输出数字时可调用sprintf()函数将所要输出的格式送到第一个参数,然后显示输出。函数名: sprintf 功 ; 能: 送格式化输出到字符串中 用 ; 法: int sprintf(char *string, char *farmat [,argument,...]); 程序例:#include #include int main(void) { ; ; char buffer[80]; ; ; sprintf(buffer, "An approximation of Pi is %f\n", M_PI); ; ; puts(buffer); ; ; return 0; } sprintf的作用是将一个格式化的字符串输出到一个目的字符串中,而printf是将一个格式化的字符串输出到屏幕。sprintf的第一个参数应该是目的字符串,如果不指定这个参数,执行过程中出现 ; ; ; ; ;"该程序产生非法操作,即将被关闭...."的提示。 因为C语言在进行字符串操作时不检查字符串的空间是否够大,所以可能会出现数组越界而导致程序崩溃的问题。即使碰巧,程序没有出错,也不要这么用,因为早晚会出错。所以一定要在调用sprintf之前分配足够大的空间给buf。 ;由于sprintf 跟printf 在用法上几乎一样,只是打印的目的地不同而已,前者打印到字符串中, 后者则直接在命令行上输出。这也导致sprintf 比printf 有用得多。所以本文着重介绍sprintf,有时 也穿插着用用pritnf。 sprintf 是个变参函数,定义如下: int sprintf( char *buffer, const char *format [, argument] ... ); 除了前两个参数类型固定外,后面可以接任意多个参数。而它的精华,显然就在第二个参数: 格式化字符串上。 printf 和sprintf 都使用格式化字符串来指定串的格式,在格式串内部使用一些以“%”开头的 格式说明符(format specifications)来占据一个位置,在后边的变参列表中提供相应的变量,最终 函数就会用相应位置的变量来替代那个说明符,产生一个调用者想要的字符串。 格式化数字字符串 sprintf 最常见的应用之一莫过于把整数打印到字符串中,所以,spritnf 在大多数场合可以替代 itoa。如: //把整数123 打印成一个字符串保存在s 中。

Cyapi使用心得

EZ-USB FX2(68013)Cyapi使用心得(1)--USB连接 2009-11-07 19:23 用Cyapi也有一阵了,这个确实比EZusb的api好用,简单说下Cyapi的使用心得,在编程中应该注意的一些问题,毕竟,说起来,那个CYapi 的说明文档讲的实在太简单了点,好多东西都讲得不明白,只能 在使用中自己慢慢积累了。 首先说下前提,固件架构是EZ-USB FX2/FX2LP(CY7C68013),编译环境VC++ 6.0,驱动是Cyusb.sys。 上位机简单说下,建立一个MFC 单文档/对话框应用程序;在路径项目中包含头文件cyapi.h和cyapi.lib所在的路径,最好移到最上面。然后手动导入cyapi.lib,注意是CV6_7的lib,不要导入BCB的。 下面讲得是按照USB一般工作流程来讲得。 (1)USB连接 1.首先要建立一个USB设备对象 文档里有说的了,copy一下 CCyUSBDevice *USBDevice = new CCyUSBDev(Handle); 括号中的Handle是USB所关联对象的句柄,一般在MFC中直接就是m_hwnd。 2.然后就该是打开USB设备了 可以用到两个函数open();isopen() 这两个都可以用来打开USB设备,isopen()还可以判断能否获得USB设备句柄 一般来说,如果只有一个USB设备连接,可以这样打开: USBDevice->open(0) //打开0号USB设备 如果要判断,可以: if(! USBDevice->open(0)) //打开失败 {messagebox("USB未连接");} 或者 if(!USBDevice->Isopen())

c语言关键字的用法详解

1. Static用法 1.1 static声明的变量在C语言中有两方面的特征: 1)、变量会被放在程序的全局存储区中,这样可以在下一次调用的时候还可以保持原来的赋值。这一点是它与堆栈变量和堆变量的区别。 2)、变量用static告知编译器,自己仅仅在变量的作用范围内可见。这一点是它与全局变量的区别。 1.2 特点 A.若全局变量仅在单个C文件中访问,则可以将这个变量修改为静态全局变量,以降低模块间的耦合度; B.若全局变量仅由单个函数访问,则可以将这个变量改为该函数的静态局部变量,以降低模块间的耦合度; C.设计和使用访问动态全局变量、静态全局变量、静态局部变量的函数时,需要考虑重入问题; D.如果我们需要一个可重入的函数,那么,我们一定要避免函数中使用static变量(这样的函数被称为:带“内部存储器”功能的的函数) E.函数中必须要使用static变量情况:比如当某函数的返回值为指针类型时,则必须是static 的局部变量的地址作为返回值,若为auto类型,则返回为错指针。 函数前加static使得函数成为静态函数。但此处“static”的含义不是指存储方式,而是指对函数的作用域仅局限于本文件(所以又称内部函数)。使用内部函数的好处是:不同的人编写不同的函数时,不用担心自己定义的函数,是否会与其它文件中的函数同名。 扩展分析:术语static有着不寻常的历史.起初,在C中引入关键字static是为了表示退出一个块后仍然存在的局部变量。随后,static在C中有了第二种含义:用来表示不能被其它文件访问的全局变量和函数。为了避免引入新的关键字,所以仍使用static关键字来表示这第二种含义。最后,C++重用了这个关键字,并赋予它与前面不同的第三种含义:表示属于一个类而不是属于此类的任何特定对象的变量和函数(与Java中此关键字的含义相同)。 1.3 关键字static的作用是什么? 这个简单的问题很少有人能回答完全。在C语言中,关键字static有三个明显的作用:

常用转换函数汇总

1.计算CRC码(CRC16) 输入一个char数组以及数组的长度。数组长度包含CRC码。数组类似于“01 02 FA 03 A4…00 00”的格式,返回计算出的CRC码值,并存储到最后两位。次低位存储高字节,最低位存储低字节。 unsigned char* CMyCnComm::CalCRC(char buf[], int cnt) { unsigned char CRCHi=0x00,CRCLo=0x00,CRCGXHi=0x10,CRCGXLo=0x21; unsigned char ch; int j = 0; while( j < cnt-2) { ch = buf[j]; unsigned char BD; unsigned short i; bool sCF,lCF,hCF; BD=ch; sCF=false; lCF=false; hCF=false; for(i=0;i<8;i++) { if((BD&0x80)==0x80)sCF=true; if((CRCHi&0x80)==0x80)hCF=true; if((CRCLo&0x80)==0x80)lCF=true; CRCLo=CRCLo<<1; CRCHi=CRCHi<<1; if(lCF)CRCHi=CRCHi|0x01; if(sCF!=hCF) { CRCHi=CRCHi^CRCGXHi; CRCLo=CRCLo^CRCGXLo; } BD=BD<<1; sCF=false; lCF=false; hCF=false; } j++; } unsigned char *crcResult = new unsigned char[2]; crcResult[0] = CRCHi; crcResult[1] = CRCLo return crcResult; }

ComboBox组合框的基本使用

Microsoft Visual C++ 6.0中ComboBox组合框的基本使用 更多详情可以参考msdn的标准规范:[1] 1 向组合框控件添加内容ComboBox_AddString(hwndCtl,lpsz) hwndCtl为此组合框的句柄,lpsz为需要添加的字符串,组合框不能直接通过id 添加内容,所以需要得到这个控件的句柄,还得使用GetDlgItem()函数. 举例: HWND hwndCombo1 = GetDlgItem(hwnd,IDC_C1); //建立一个组合框,ID可以设置为IDC_C1,然后通过GetDlgItem获取这个组合框的句柄 //如果无法正常显示,需要调整此组合框的最大显示范围,在向下箭头上出现上下箭头时可以调整. ComboBox_AddString(hwndCombo1,TEXT("内容1")); ComboBox_AddString(hwndCombo1,TEXT("内容2")); //使用IDC_C1的句柄hwndCombo1,然后添加内容,多次调用可以设置多项文字, //添加的内容通常都放在Main_OnInitDialog()初始化函数中,也可以通过按钮或其他控件调用. 2 获取组合框控件的项目个数ComboBox_GetCount(hwndCtl) 这个函数的返回值为int,参数hwndCtl为此组合框控件句柄; 举例: HWND hwndCombo1 = GetDlgItem(hwnd,IDC_C1); int count = ComboBox_GetCount(hwndCombo1); //通过定义count拿到返回值. 3 删除给定索引号的组合框控件的内容ComboBox_DeleteString(hwndCtl, index) hwndCtl为句柄,index为项目索引号,从上至下,从0开始排列,所以0就是删除第一项. 举例: HWND hwndCombo1 = GetDlgItem(hwnd,IDC_C1); ComboBox_DeleteString(hwndCombo1,0); 4 获取当前选中项的索引号ComboBox_GetCurSel(hwndCtl) 此函数的返回值为int,返回项目索引号. 举例: HWND hwndCombo1 = GetDlgItem(hwnd,IDC_C1); int count = ComboBox_GetCurSel(hwndCombo1); //获取到索引号. TCHAR str1[256]; sprintf(str1,"当前选中的项索引号为:%d",count); //使用sprintf储存说明文字跟索引号, MessageBox(hwnd,str1,TEXT("标题"),MB_OK); ComboBox_DeleteString(hwndCombo1,count); //删除获取此索引号的项. MessageBox(hwnd,TEXT("删除当前选中的项"),TEXT("标题"),MB_OK);

C语言中常用的库函数

字符处理函数 本类别函数用于对单个字符进行处理,包括字符的类别测试和字符的大小写转换 头文件ctype.h 函数列表<> 函数类别函数用途详细说明 字符测试是否字母和数字isalnum 是否字母isalpha 是否控制字符iscntrl 是否数字isdigit 是否可显示字符(除空格外)isgraph 是否可显示字符(包括空格)isprint 是否既不是空格,又不是字母和数字的可显示字符ispunct 是否空格isspace 是否大写字母isupper 是否16进制数字(0-9,A-F)字符isxdigit 字符大小写转换函数转换为大写字母toupper 转换为小写字母tolower 地区化 本类别的函数用于处理不同国家的语言差异。 头文件local.h 函数列表 函数类别函数用途详细说明 地区控制地区设置setlocale 数字格式约定查询国家的货币、日期、时间等的格式转换localeconv 数学函数 本分类给出了各种数学计算函数,必须提醒的是ANSI C标准中的数据格式并不符合IEEE754标准,一些C语言编译器却遵循IEEE754(例如frinklin C51) 头文件math.h 函数列表 函数类别函数用途详细说明 错误条件处理定义域错误(函数的输入参数值不在规定的范围内) 值域错误(函数的返回值不在规定的范围内) 三角函数反余弦acos 反正弦asin

反正切atan 反正切2 atan2 余弦cos 正弦sin 正切tan 双曲函数双曲余弦cosh 双曲正弦sinh 双曲正切tanh 指数和对数指数函数exp 指数分解函数frexp 乘积指数函数fdexp 自然对数log 以10为底的对数log10 浮点数分解函数modf 幂函数幂函数pow 平方根函数sqrt 整数截断,绝对值和求余数函数求下限接近整数ceil 绝对值fabs 求上限接近整数floor 求余数fmod 本分类函数用于实现在不同底函数之间直接跳转代码。头文件setjmp.h io.h 函数列表 函数类别函数用途详细说明 保存调用环境setjmp 恢复调用环境longjmp 信号处理 该分类函数用于处理那些在程序执行过程中发生例外的情况。 头文件signal.h 函数列表 函数类别函数用途详细说明 指定信号处理函数signal 发送信号raise 可变参数处理 本类函数用于实现诸如printf,scanf等参数数量可变底函数。

(精华版)_stprintf_s和_stscanf_s函数与UNICODE编码

版权所有。转载请注明出处。 _stprintf_s和_stscanf_s函数与UNICODE编码 一、核心内容 ?该文档适用于微软的visual C++ 平台。 ?需要头文件: ?MSDN上对stprintf_s和_stscanf_s函数的定义: TCHAR.H routine _UNICODE & _MBCS not defined _MBCS defined _UNICODE defined _stprintf_s sprintf_s sprintf_s swprintf_s _stscanf_s sscanf_s sscanf_s swscanf_s 对应的代码为: #ifdef UNICODE #define _stprintf_s swprintf_s #else #define _stprintf_s sprintf_s ?前面的t表示编码,后面的_s表示检查内存溢出,前面的_表示非标准库函数。 ?从上我们可以看出,_stprintf_s和_stscanf_s是为适应不同编码而定义的两个宏,在不同的编码环境下他们所表示的函数是不同的。 ?_s是security的意思,具体含义参见后面的Security Remarks部分。 (1)int sprintf_s( char *buffer, size_t sizeOfBuffer, const char *format [, argument] ... ); //ANSI版本 int swprintf_s(wchar_t *buffer, size_t sizeOfBuffer, const wchar_t *format [,argument]...); //UNICODE版本

sprintf函数在LCD中使用

#include//包含sprintf函数对于LCD1602/LCD12864显示数字很有用float temperature; char displaytemp[16];//定义显示区域临时存储数组 temperature=(float)temp*0.0625; sprintf(displaytemp,"Temp % 7.3f",temperature);//打印... //sprintf函数功能:把格式化的数据写入某个字符串 //%[指定参数][标识符][宽度][.精度]指示符 //1. 处理字符方向。负号时表示从后向前处理。 //2. 填空字元。0 的话表示空格填0;空格是内定值,表示空格就放着 //3. 字符总宽度。为最小宽度。 //4. 精确度。指在小数点后的浮点数位数 // %% 印出百分比符号,不转换。 // %c 整数转成对应的 ASCII 字元。 // %d 整数转成十进位。 // %f 倍精确度数字转成浮点数。 // %o 整数转成八进位。 // %s 整数转成字符串。 // %x 整数转成小写十六进位。 // %X 整数转成大写十六进位。 LCD_Write_String(0,1,displaytemp);//显示 还有一种显示数字法:show[i]=time_buf1[j]/10+'0';//加上'0'是将数字转成字符 STC12C5A60S2 传统8051单片机执行I/O口操作,由高变低或由低变高,以及读外部状态都是12个时钟,而现在STC12系列单片机执行相应的操作是4个时钟。传统8051单片机如果对外输出为低,直接读外部状态是读不对的。必须先将I/O口置高才能够读对,而传统8051单片机由低变高的指令是12小时钟,该指令执行完成后,该I/O口也确定已变高。故可以紧跟着由低变高的指令后面,直接执行读该I/O口状态指令。而STC12系列单片机由于执行由低变高的指令是4个时钟,太快了,相应的指令执行完以后,I/0口还没有变高,要再过一个时钟之后,该I/O口才可以变高。故建议此状况下增加2个空操作延时指令再读外部品的状态。 最新STC12系列单片机I/O口的灌电流是20mA,驱动能力超强,驱动大电流时,不容易烧坏. 传统STC89Cxx系列单片机I/O口的灌电流是6mA,驱动能力不够强,不能驱动大电流,建议使用STC12系列.

【最新推荐】c语言sprintf实现原理-范文模板 (17页)

本文部分内容来自网络整理,本司不为其真实性负责,如有异议或侵权请及时联系,本司将立即删除! == 本文为word格式,下载后可方便编辑和修改! == c语言sprintf实现原理 篇一:C语言机械原理编程,连杆运动分析图线 编程大作业 基于C语言的机械原理分析图: 只有库函数包含头文件:graphics.h conio.h 才能观看该程序效果; 若已经安装VC++,可以打开文件夹里面的EasyX压缩包,并安装EasyX文件,也可以观看程序效果; 一、角度与l3与角1的关系; #include #include #include #include #define SZ 2 #define PI 3.1415926 float c[SZ][SZ]={0}; void danwei() { char s[5];

int i=0; int k=-5; while(k<=600) { sprintf(s, "%d", i); outtextxy(k, 5, s); k+=75; i+=45; } outtextxy(280,25, "θ1/度"); } void danwei2() { char s[10]; float i=-0.1; int k=-10; while(k>=-400) { sprintf(s,"%0.2f",i); outtextxy(610,k,s); k-=40; i+=0.05; } outtextxy(610,-420, "l3/m/s");

} void danwei1() { char s[10]; int i=-60; int k=-10; while(k>=-400) { sprintf(s,&q uot;%d",i); outtextxy(-30,k,s); k-=20; i+=10; } outtextxy(-85,-420, "θ2、θ3/度"); } int main() { // 创建大小为 800 * 600 的绘图窗口 initgraph(800, 600); // 设置原点 (0, 0) 为屏幕中央(Y轴默认向下为正)setorigin(100, 500); // 使用白色填充背景 setbkcolor(WHITE);

fopen,fprintf 和 sprintf在Matlab中的应用

fopen,fprintf 和sprintf在Matlab中的应用 matlab中fopen函数在指定文件打开的实例如下: *1)“fopen”打开文件,赋予文件代号。 语法1:FID= FOPEN(filename,permission) 用指定的方式打开文件 FID=+N(N是正整数):表示文件打开成功,文件代号是N. FID=-1 : 表示文件打开不成功。 FID在此次文件关闭前总是有效的。 如果以读方式打开,matlab首先搜索工作目录,其次搜索matlab的其他目录,“permission”是打开方式参数。 打开方式参数由以下字符串确定: r 读出 w 写入(文件若不存在,自动创建) a 后续写入(文件若不存在,自动创建) r+ 读出和写入(文件应已存在) w+ 重新刷新写入,(文件若不存在,自动创建) a+ 后续写入(文件若不存在,自动创建)) w 重新写入,但不自动刷新 a 后续写入,但不自动刷新 文件的存储格式:文件打开的默认方式是:二进制。以文本方式打开,可以在方式参 数“permission”中加入“t”文件将,如“rt”,“wt+” matlab中fprintf函数的具体使用方法实例如下: fprintf函数可以将数据按指定格式写入到文本文件中。其调用格式为: 数据的格式化输出:fprintf(fid, format, variables) 按指定的格式将变量的值输出到屏幕或指定文件 fid为文件句柄,若缺省,则输出到屏幕 1 for standard output (the screen) or 2 for standard error. If FID is omitted, output goes to the screen. format用来指定数据输出时采用的格式 %d 整数 %e 实数:科学计算法形式 %f 实数:小数形式 %g 由系统自动选取上述两种格式之一 %s 输出字符串 fprintf(fid,format,A) 说明:fid为文件句柄,指定要写入数据的文件,format是用来控制所写数据格式的格式符,与fscanf函数相同,A是用来存放数据的矩阵。 例6.9 创建一个字符矩阵并存入磁盘,再读出赋值给另一个矩阵。 >> a='string'; >> fid=fopen('d:\char1.txt','w'); >> fprintf(fid,'%s',a); >> fclose(fid); >> fid1=fopen('d:\char1.txt','rt'); >> b=fscanf(fid1,'%s') b = string

GPIB板的安装与使用初步

GPIB板的安装与使用初步 传统的电子电路实验,需要手动调节示波器,信号发生器,交直流电压电流表等测试仪器。完成一个电路的测量,需要人一直在旁边实时记录数据,再用手工处理分析数据,绘制图表,显然耗费时间和人力。现代较新的测量设备都带有通讯接口,可以和计算机直接连接,在计算机特定的软件环境下,通过编程对仪器进行自动控制,让信号发生器自动产生激励输入,同时将示波器放在输出端,或电路中其它支路的输出上,将示波器采集到的信号自动输入计算机,由计算机完成实验数据的处理和图表绘制。根据这种思想可以设计一个用于实验电路的自动测量装置,可以自动实现各种激励波形输入,以及扫频。然后自动采集示波器的输出,完成对频率稳定度,幅度特性曲线,相位特性曲线,谐波分量分析,功率谱密度以及分布显示等常用的实验测量指标。更一般地,凡是MATLAB信号处理工具箱能够完成的信号处理,它都可以完成,因为软件中已经将MATLAB内核嵌入。 本节将以应用实例介绍GPIB卡应用。 1.了解GPIB 1)GPIB是什么 GPIB(General Purpose Interface Bus),通用接口总线,广泛应用于仪器和计算机制造行业,其标准为IEEE-488。 2)GPIB角色 GPIB设备的角色有三种:讲者、听者、控者。讲者发送数据到一个或多个听者,听者从讲者接受数据,而控者管理总线上的信息流。GPIB设备的角色是可以随时间而变的。例如:一个由GPIB连接的示波器在接受设置命令时,其角色是听者,而在它将数据传送至计算机时,则是一个讲者。 控者在GPIB系统中的任何时刻都是必需的,它的任务是确保系统中只有一个讲者(某时刻),同时保证听者能够正确接收数据。因此,对一个特定时刻,GPIB系统中只能有一个控者。但控者可以将其控制权移交给另一设备(必须有控制能力)。GPIB板(可插入计算机扩展槽)通常被默认地设置为GPIB系统控者。 3)GPIB电缆 GPIB为8位并行传输总线,包括:8位数据线,3个握手信号线,8个控制线以及电缆保护线和地线。下表列出了GPIB中的主要信号线: 表1 GPIB电缆中引脚的定义 4)PIB连接规则 GPIB总线上最多允许15个设备,而连线的最大总长度为20米,相邻设备的长度不超

matlab 基础函数用法总结

1、Size 函数用法 例如:1,2,3;4,5,6]是一个2*3的矩阵,则: d = size(X); %返回矩阵的行数和列数,保存在d中 [m,n] = size(X)%返回矩阵的行数和列数,分别保存在m和n中 m = size(X,dim);%返回矩阵的行数或列数,dim=1返回行数,dim=2返回列数 2、Corrcoef 函数用法 corrcoef(x,y)表示序列x和序列y的相关系数,得到的结果是一个2*2矩阵,其中对角线上的元素分别表示x和y的自相关,非对角线上的元素分别表示x 与y的相关系数和y与x的相关系数,两个是相等的 3、sort函数用法 sort(X) 功能:返回对向量X中的元素按列升序排列的新向量。 [Y, I] = sort(A, dim, mode) 功能:对矩阵A的各列或各行重新排序,I记录Y中的元素在排序前A中位置,其中dim指明读A的列还是行进行排序。若dim=1,则按列排序;若dim=2,则按行排序。mode为排序的方式,取值'ascend'为升序,'descend'为降序 4、Legend 函数用法 legend(string1,string2,string3,┈) 分别将字符串1、字符串2、字符串3……标注到图中,每个字符串对应的图标为画图时的图标。 例如: plot(x,sin(x),?.b?,x,cos(x),?+r?) legend(…sin?,?cos?) //这样就可以把”.”标识为”sin”,把”+”标识为“cos” 5、find 函数用法 找到非零元素的索引和值 语法: 1. ind = find(X) 2. ind = find(X, k) 3. ind = find(X, k, 'first') 4. ind = find(X, k, 'last') 5. [row,col] = find(X, ...) 6. [row,col,v] = find(X, ...) 说明: 1. ind = find(X)

相关文档
最新文档