一个关于字符串拼接的问题

antiMight 2012-12-22 10:26:42
我用strncpy和strncat来拼接字符串,第一种是直接多次调用,第二种是串接调用,应该效率高点,看起来两个结果应该是一样的才对,但是第二个输出结果有问题,我知道是tbuf的问题,把三个调用tbuf的地方换成三个就是对的,但是为什么呢?这两种方式应该是一样的吧?不一样的只是第二个cat时是直接从上一次的结尾赋值,即使我在_itoa里用了相同的tbuf,strncat后不是会直接拷贝的吗?拷贝完应该就是正确的到buf里了才对吧,谁来解释下?
	char tbuf[4] = {0};
char buf[1024] = {0};

strncpy(buf, "\n", 2);
strncat(buf, _itoa(1, tbuf, 10), 3);
strncat(buf, ":", 2);
strncat(buf, _itoa(2, tbuf, 10), 3);
strncat(buf, ":", 2);
strncat(buf, _itoa(3, tbuf, 10), 3);
strncat(buf, "\n", 2);

std::cout << buf<< std::endl; //1:2:3

strncat(strncat(strncat(strncat(strncat(strncat(
strncpy(buf, "\n", 2),
_itoa(1, tbuf, 10), 3),
":", 2),
_itoa(2, tbuf, 10), 3),
":", 2),
_itoa(3, tbuf, 10), 3),
"\n", 2);

std::cout << buf<< std::endl; //1:1:1
...全文
315 16 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
antiMight 2012-12-29
  • 打赏
  • 举报
回复
引用 12 楼 ForestDB 的回复:
第一,LZ知道_itoa返回什么? 第二,对于这种“套娃”式的函数调用,LZ能否说出它的调用顺序? 为了方便讨论,代码简化如下: C/C++ code?12345678 char tbuf[4] = {0}; char buf[1024] = {0}; strncat(buf, _itoa(1, tbuf, 10), 3); strnc……
多谢,你是对的,我对函数压参顺序完全不清楚,一直是以为从左至右,看来是我想当然了。
引用 14 楼 zhao4zhong1 的回复:
引用 12 楼 ForestDB 的回复:第一,LZ知道_itoa返回什么? 第二,对于这种“套娃”式的函数调用,LZ能否说出它的调用顺序? 为了方便讨论,代码简化如下: C/C++ code?12345678 char tbuf[4] = {0}; char buf[1024] = {0}; strncat(buf, _itoa(1, tb……
汇编还没学,看来有必要学习下了。 另外,经过我的测试发现,sprintf还是要比stringstream要快的,可能是测试的格式不够复杂的原因。
赵4老师 2012-12-26
  • 打赏
  • 举报
回复
赵4老师 2012-12-26
  • 打赏
  • 举报
回复
引用 12 楼 ForestDB 的回复:
第一,LZ知道_itoa返回什么? 第二,对于这种“套娃”式的函数调用,LZ能否说出它的调用顺序? 为了方便讨论,代码简化如下: C/C++ code?12345678 char tbuf[4] = {0}; char buf[1024] = {0}; strncat(buf, _itoa(1, tbuf, 10), 3); strnc……
支持! 对学习编程者的忠告: 眼过千遍不如手过一遍! 书看千行不如手敲一行! 手敲千行不如单步一行! 单步源代码千行不如单步对应汇编一行!
ForestDB 2012-12-25
  • 打赏
  • 举报
回复
总结下的话就是 从外向内,从右向左压参,如果参数需要演算,那么先演算参数(比如进一步的函数调用,这就导致内部函数先执行)
ForestDB 2012-12-25
  • 打赏
  • 举报
回复
第一,LZ知道_itoa返回什么? 第二,对于这种“套娃”式的函数调用,LZ能否说出它的调用顺序? 为了方便讨论,代码简化如下:

    char tbuf[4] = {0};
    char buf[1024] = {0};

    strncat(buf, _itoa(1, tbuf, 10), 3);
    strncat(buf, _itoa(2, tbuf, 10), 3);

    buf[0] = 0;
    strncat(strncat(buf, _itoa(1, tbuf, 10), 3), _itoa(2, tbuf, 10), 3);
没问题的代码就不讨论了, 单单来看strncat(strncat(buf, _itoa(1, tbuf, 10), 3), _itoa(2, tbuf, 10), 3);这句。 我没有看debugger的执行过程,但从过去看的经验,以及由此建立的对函数调用的理解,要执行这句,先是最外层的strncat压参,而且是从右向左压的,所以是: 先入3, 为了压第二个参数,先执行了_itoa(2, tbuf, 10),返回tbuf压参,同时tbuf的内容是2 为了压第一个参数,要执行strncat(buf, _itoa(1, tbuf, 10), 3),即内部的strncat, 为了执行内部的strncat,同样也是先压3, 再执行_itoa(1, tbuf, 10),这时返回tbuf,但是tbuf的内容已经是1了 压buf 此时内部strncat完成调用,返回buf,压参 然后外部strncat开始调用。 至此,可以清楚错误在哪里了。 LZ可以自行用debugger跟踪此过程,对比顺序调用的过程。 简言之,就是压参,调用,返回这样一个递归的过程(即要算什么,必须先算什么,这样一个依赖)。 最后一句话,不要过早优化
antiMight 2012-12-24
  • 打赏
  • 举报
回复
引用 10 楼 zhao4zhong1 的回复:
引用 8 楼 zhcosin 的回复:楼主的需求是否是要把三个整数用冒号串起来?如果是的话,为何不直接像下面这样直接写进去呢: C/C++ code?123int n=1, m=2, k=3;char buffer[1024];snprintf(buffer, 1024, "%d:%d:%d", n, m, k); 因为楼主不识“snprintf”
其实我原来用的就是sprintf,不过为了提高效率,所以想到这个方法,sprintf(snprintf)要每次都动态解析一次格式(很慢),而手动拼接就省去了这一步,这个差异还是很明显的,stackoverflow上一个帖子说,即使是std::stringstream也会比sprintf快很多,因为前者相当于在编译期就解析好了格式(重载),而后者每次调用都要解析一次。
赵4老师 2012-12-24
  • 打赏
  • 举报
回复
引用 8 楼 zhcosin 的回复:
楼主的需求是否是要把三个整数用冒号串起来?如果是的话,为何不直接像下面这样直接写进去呢: C/C++ code?123int n=1, m=2, k=3;char buffer[1024];snprintf(buffer, 1024, "%d:%d:%d", n, m, k);
因为楼主不识“snprintf”
antiMight 2012-12-24
  • 打赏
  • 举报
回复
引用 8 楼 zhcosin 的回复:
楼主的需求是否是要把三个整数用冒号串起来?如果是的话,为何不直接像下面这样直接写进去呢: C/C++ code?123int n=1, m=2, k=3;char buffer[1024];snprintf(buffer, 1024, "%d:%d:%d", n, m, k);
效率问题,上面的方法是动态解析的,所以效率比较低,其实我想用第二个方法也是对比下两种的效率差别的。
zhcosin 2012-12-24
  • 打赏
  • 举报
回复
楼主的需求是否是要把三个整数用冒号串起来?如果是的话,为何不直接像下面这样直接写进去呢:

int n=1, m=2, k=3;
char buffer[1024];
snprintf(buffer, 1024, "%d:%d:%d", n, m, k);
antiMight 2012-12-24
  • 打赏
  • 举报
回复
引用 4 楼 arpnet99 的回复:
感觉你的括号有问题。
第二种的应该是从内向外处理的吧,括号只是方法的括号,应该不会有歧义的吧?
引用 5 楼 h_w_m 的回复:
顺序处理无问题,高效简洁 而多重嵌套调用处理时,函数参数的入栈过程及参数的处理顺序产生了副作用,与你预期的并不一致,自以为会优处理过程,可没想到参数处理入栈嵌套多层,效果并不理想
我感觉也可能跟编译器优化有关,关键我想不通的是
char buf[1024] = {0};
		
		char tbuf[4] = {0};
		char tbuf2[4] = {0};
		char tbuf3[4] = {0};
     
    strncat(strncat(strncat(strncat(strncat(strncat(
    strncpy(buf, "\n", 2), 
    _itoa(1, tbuf, 10), 3), 
    ":", 2),
    _itoa(2, tbuf2, 10), 3),
    ":", 2), 
    _itoa(3, tbuf3, 10), 3),
    "\n", 2);
     
    std::cout << buf<< std::endl;    //1:2:3
第二种中把用于int转char*的tbuf,改成3个就可以了。。。 搞不懂究竟是怎样执行的呢?按理说应该和第一种一样的执行才对吧
引用 6 楼 xuchao1229 的回复:
你是在字符和数字之间转换然后在进行拼接的?
是这样的,我感觉问题就是出在用于转换的tbuf上了
antiMight 2012-12-22
  • 打赏
  • 举报
回复
引用 2 楼 arpnet99 的回复:
读了2遍还没明白你的意思...
主要就是看那两个代码,应该是等价的,但结果是不一样的,第二个有问题,问题在哪呢?
这不是鸭头 2012-12-22
  • 打赏
  • 举报
回复
读了2遍还没明白你的意思...
antiMight 2012-12-22
  • 打赏
  • 举报
回复
这代码是我改过的,上面的3应该是2就可以了
14号选手 2012-12-22
  • 打赏
  • 举报
回复
你是在字符和数字之间转换然后在进行拼接的?
h_w_m 2012-12-22
  • 打赏
  • 举报
回复
顺序处理无问题,高效简洁 而多重嵌套调用处理时,函数参数的入栈过程及参数的处理顺序产生了副作用,与你预期的并不一致,自以为会优处理过程,可没想到参数处理入栈嵌套多层,效果并不理想
这不是鸭头 2012-12-22
  • 打赏
  • 举报
回复
感觉你的括号有问题。

70,020

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧