接收各种输出 printf 和 cout-C++
我有一个我想要打印的字符串。 当我使用时
, 它很棒,但使用
让他褪色。
这是代码:
给我 "rawname: file"
给我 "rawname:", 然后是一堆抹布
</filename>
cout
, 它很棒,但使用
printf
让他褪色。
这是代码:
int main / int argc, char *argv[] /
{
// Check to make sure there is a single argument
if / argc != 2 /
{
cout<<"usage: "<< argv[0] <<" <filename>\n";
return 1;
}
// Grab the filename and remove the extension
std::string filename/argv[1]/;
int lastindex = filename.find_last_of/"."/;
std::string rawname = filename.substr/0, lastindex/;
cout << "rawname:" << rawname << endl;
printf/"rawname: %s", rawname/;
}
cout
给我 "rawname: file"
printf
给我 "rawname:", 然后是一堆抹布
</filename>
没有找到相关结果
已邀请:
5 个回复
快网
赞同来自:
原因是 printf 从 %s 预计 null 完成的线路 C 心里。 虽然字符串 std::string stl 不是完全生原料 - 她最终 null 结束您的情况,不确定它甚至是一种保证,因为长度是由容器类内部控制的 stl.
编辑
:
如在内部的评论中所示,它将被保证 null 停了下来。 所以你看到了什么 'squiggly lines', 是所有选定但未使用的输出 /或初始化/ 内存在此排中到终结器符号 null.
小明明
赞同来自:
那不是那么概要
简短的插图 /假设稍后解释/:
您无法传输除此之外的数据 POD, 这样的功能
, 其中采取任意数量的参数使用
. /参数 " ... " - 此功能 C++, 继承自 C, 它本质上不适合与复杂对象一起使用。 C++/.
你甚至可以编译它吗?
我的编译器 GCC 不喜欢:
GCC 4.5.2 错误:
GCC 4.1.2 一个警告 + 执行期间的行为:
它们不会编译它,因为没有标准的方法来传输对象
. 编译器无法从简单计算
, 它们是价值还是依值 reference/pointer,, 因此,它不知道要生成哪个代码。
但你的勇敢的编译器做了一些事情。 让我们花一点时间,对象看起来像什么 std::string, 然后返回您的编译器如何获得并访问它。
胃对象 std::string
内部元素 std::string 未指定,但通常包含其中任何一个:
当前成员 OR 指向超出线的结尾 /ala
/
其中任何一个允许您简单地计算另一个,而是一对我检查的标准库实现是针对成员进行了优化的。 pointer/
并计算
- 它与迭代器的惯例周期更好。
在堆中的字符缓冲区上的路标 /在实践中,它最有可能存储 NUL 完成I.
直接返回它,但此指针可通过该功能访问 - 成员
, 标准允许向文本吸引未完成的文本 NUL, 所以
理论上
他可以有一个终结者 NUL, 仅在呼叫时添加
, 或者
可以将文本复制到另一个位置,然后添加 NUL 并将指针返回到此新缓冲区/
数据缓冲区 "short string optimisation", 因此,所有几个字符的行都不应该使用一堆
和/或者
指向其他地方的某些对象的指针 /其中有上述要素 + 参考电表 a mutex,...?/
示例:简单的String Store Store
它们可以按任何顺序。 所以,最简单的可能性 - 这是什么 - 那似乎是:
现在,
"this and that"-这是
字符串字面量
, 说,at. "A"; 该数据被复制到
;
不是
记得他在哪里拿走他们
- 这是实际对象
, 说,at. "B"; 让我们想象一下,这是最容易的:
/将包含值 13, 平等的
/
将指示一些新分配的堆积内存,在地址 "C" - 其中复制了 "这是我 that\0"
重要的是要注意地址 "A", 地址 "B" 和地址 "C" 不同的!
如何 printf// 看 std::string
如果我们有一个糟糕的编译器,可以尝试传输我们的对象
在
, 也就是说,这两件事
可以得到
, 哪一个
说要期待:
1/ 指向对象的指针
, 即。地址 "B"
2/
复制字节数据
从
地址 "A" 一些地址堆栈 "B" 和 / 或注册在哪里
如果它可以应对这些东西,我会期待这个; - P
然后
开始从此地址打印字节,就像它们是符号,直到字节发现 0/NUL:
对于脚本 1 上面它在对象中打印字节,例如:
让我们说
- 这是 4 字节和对象的开头; 尺寸 13 可能是 be 13, 0, 0, 0 或者 0, 0, 0, 13 根据机器是否使用存储协议 big-endian 或者 little-endian... 考虑到他第一次停止 NUL, 它将打印一个符号 13 /结果是一个值 ASCII carriage-return/CR, 将光标返回到行的开头/, 然后停下来,或者他可以绝对打印。 在你自己的情况下,你的行的内容是不同的,所以它会打印一些其他垃圾,但是进入之前只有一个或两个字符 0/NUL.
让我们说
在突出显示的桩缓冲区中 "C" 位于对象的开头,然后将打印此地址中的各个字符:对于32位指针,这可能是 4 垃圾符号 /假设他们都不会 0/NUL/, 为了 64-bit 这将是 8, 然后他将继续与下一个领域合作
/可能跟踪指针
, 但如果这是一个领域
, 然后具有更大的概率 0/NUL/./.
可以解释对象数据的前四个字节
作为进一步文本数据的指针......它与之不同 1/: 让我们说一个会员
是第一个,价值是 13,
可能错误地将其解释为
对于地址 13, 然后尝试从那里读取字符。 它实际上保证无法密封一些东西 /现代 OSes/, 因此,这种行为真的很不可能让我们留下 "1".
石油百科
赞同来自:
八刀丁二
赞同来自:
rawname - 这不是一个字符数组,而是一个类实例 std::string. 要获取实际的字符数组,必须调用函数 c_str//
帅驴
赞同来自: