需求:需要拼接多个字符串为一整个字符串
实现:
char strName[30] = {0};
sprintf((char *)strName, "%s-%c", "hello word", '1');
// 结果:“hello word-1”
// printf("result: %s", strName)
需要注意的地方:
sprintf()会自动在字符串的尾部补充'\0',如果目标长度和原长度相等,就会导致越界。
VS验证代码:
#include <stdio.h>
#include <stdlib.h>
int main()
{
char a[7];
sprintf(a, "-%s-","hello");
printf("result:%s", a);
printf("result:%d", a[8]);
while(1);
return 0;
}
运行结果:
- a 0x0043f9d8 "-hello-" char [7]
[0] 45 '-' char
[1] 104 'h' char
[2] 101 'e' char
[3] 108 'l' char
[4] 108 'l' char
[5] 111 'o' char
[6] 45 '-' char
a[7] 0 char //越界了,此处是sprintf自己添加的\0结尾
a[8] -52 '?' char
使用strncpy时要注意保护:
char str[30];
strncpy(str, g_str_source, sizeof(str)-1);
str[19] = '\0';
strncpy的n就是拷贝的字符的个数,即 strlen 个,结尾不包含‘\0’
当拷贝二进制代码的时候,要注意,这样使用容易发生截断。因为:strncpy遇到0会结束。
#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include<string.h>
typedef unsigned char BYTE;
char srcdata[] = {'a','b',0,'c','d'};
char dstdata[10] = {};
void f()
{
strncpy(dstdata, srcdata, 10);
printf("srcdata len:%d\n", sizeof(srcdata));
printf("dstdata len:%d\n", sizeof(dstdata));
for(int i = 0; i < sizeof(dstdata);i++)
printf("i:%d, dstdata:%c\n", i,dstdata[i]);
}
int _tmain(int argc, _TCHAR* argv[])
{
f();
while(1);
return 0;
}
输出:
sizeof:可以求整个数组的长度(char A[20], 结果:20);如果数组里面的字符串没有存储满存储满,可以用strlen求字符串的实际个数(不包含‘\0’)。如果非静态数组,用指针存储字符串常量(char *p = “helloword”),用sizeof(p)只能求指针的长度(32位系统4个字节,64位系统8个字节),此时可以用strlen求字符串中字符的实际个数(不包含‘\0’)。不经结尾的字符串,sizeof时,会崩掉!
sizeof("hello") = 6; // 含 \0 ,整个常量(或变量)的长度
//对于以下语句:
char *str1 = "asdfgh";
char str2[] = "asdfgh";
char str3[8] = {'a', 's', 'd'};
char str4[] = "as\0df";
//执行结果是:
sizeof(str1) = 4; strlen(str1) = 6;
sizeof(str2) = 7; strlen(str2) = 6;
sizeof(str3) = 8; strlen(str3) = 3;
sizeof(str4) = 6; strlen(str4) = 2;
str1是字符指针变量,sizeof获得的是该指针所占的地址空间,32位操作系统对应4字节,所以结果是4;strlen返回的是该字符串的长度,遇到'\0'结束,'\0'本身不计算在内,故结果是6。
str2是字符数组,大小由字符串常量"asdfgh"确定,sizeof获得该数组所占内存空间大小,包括字符串结尾的'\0',所以结果为7;strlen同理返回6。
str3也是字符数组,但大小确定为8,故sizeof得到的结果是8;strlen统计'\0'之前所有字符的个数,即为3;
str4是常量字符数组,sizeof得到字符总数即6(包括编译器末尾加上去的'\0');strlen计算至'\0'结束,因此返回2;
总结一句就是sizeof计算的是变量的大小,而strlen计算的是字符串的长度,前者不受字符'\0'影响,后者以'\0'作为长度判定依据。
http://www.cplusplus.com/reference/cstdio/snprintf/
snprintf:
If the resulting string would be longer than n-1 characters, the remaining characters are discarded and not stored, but counted for the value returned by the function.
A terminating null character is automatically appended after the content written.
http://www.cplusplus.com/reference/cstring/strncpy/
strncpy:
Copies the first num characters of source to destination. If the end of the source C string (which is signaled by a null-character) is found before num characters have been copied, destination is padded with zeros until a total of numcharacters have been written to it.
No null-character is implicitly appended at the end of destination if source is longer than num. Thus, in this case, destination shall not be considered a null terminated C string (reading it as such would overflow).
reference:
sizeof、strlen、字符串、数组,整到一块,你还清楚吗?
https://www.cnblogs.com/zpcdbky/p/5857656.html
sprintf 的返回值 :
https://blog.csdn.net/lychee007/article/details/4217394
sprintf 会自动追加’\0’至字符串末尾
https://www.cnblogs.com/outs/p/10272239.html
C语言学习笔记之字符串拼接的2种方法——strcat、sprintf
https://blog.csdn.net/MetaphorXi/article/details/81365570
------------------------------------------------------------------------------------------------
总结:sprintf会自动在字符串末尾加null结尾,但函数返回值的字符个数(不含null)
C89
4.9.6.5 The sprintf function
Synopsis
#include <stdio.h>
int sprintf(char *s, const char *format, ...);
Description
The sprintf function is equivalent to fprintf , except that the
argument s specifies an array into which the generated output is to be
written, rather than to a stream. A null character is written at the
end of the characters written; it is not counted as part of the
returned sum. If copying takes place between objects that overlap,
the behavior is undefined.
Returns
The sprintf function returns the number of characters written in
the array, not counting the terminating null character.
------------------------------------------------------------------------------------------------
总结:strncpy 末尾不会自动加上'\0'
strncpy相对于strcpy来说, 被认为是比较安全的函数, 不会造成目标缓冲区的溢出. 但是该函数不会再目标缓冲区的结尾自动加上字串结束标志符'\0', 需要在程序中手工在结束处置'\0'.
以下为strncpy的说明:
Copies the first num characters of source to destination. If the end of the source C string (which is signaled by a null-character) is found before num characters have been copied, destination is padded with zeros until a total of num characters have been written to it.
No null-character is implicitly appended to the end of destination, so destination will only be null-terminated if the length of the C string in source is less than num.
snprintf()的用法
https://baike.baidu.com/item/snprintf%28%29/708910?fromtitle=snprintf&fromid=7320492&fr=aladdin
snprintf() 末尾会自动加 '\0'
static char ListStr[256];
char* chgListToStr(BYTE *List, BYTE num)
{
BYTE pos = 0;
for (WORD32 i=0; i<num; ++i)
{
if (pos < 256)
{
pos += snprintf(ListStr+pos, (256-pos), "%u ", *(List+i));
}
}
return ListStr;
}
sizeof的几个例子:
#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
typedef char s[99];
void f(s t)
{
printf("%d\n",sizeof(t));
printf("%d\n",sizeof(s));
printf("%d\n",sizeof(char));
printf("%d\n",sizeof("hello"));
}
int _tmain(int argc, _TCHAR* argv[])
{
s t;
f(t);
while(1);
return 0;
}
运行结果:
4
99
1
6