利用sprintf实现C语言字符串拼接 & strncpy 的缺点 & sprintf 的缺点

 

需求:需要拼接多个字符串为一整个字符串

 

实现:

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

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值