接收各种输出 printf 和 cout-C++

我有一个我想要打印的字符串。 当我使用时
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 &lt;&lt; "rawname:" &lt;&lt; rawname &lt;&lt; endl;
printf/"rawname: %s", rawname/;

}



cout

给我 "rawname: file"

printf

给我 "rawname:", 然后是一堆抹布
</filename>
已邀请:

快网

赞同来自:

这是因为 rawname 定义为 std::string. 你需要使用


printf/"rawname: %s", rawname.c_str///;


原因是 printf 从 %s 预计 null 完成的线路 C 心里。 虽然字符串 std::string stl 不是完全生原料 - 她最终 null 结束您的情况,不确定它甚至是一种保证,因为长度是由容器类内部控制的 stl.

编辑

:

如在内部的评论中所示,它将被保证 null 停了下来。 所以你看到了什么 'squiggly lines', 是所有选定但未使用的输出 /或初始化/ 内存在此排中到终结器符号 null.

小明明

赞同来自:

什么工作


printf/"%s", my_string.c_str///;


那不是那么概要

简短的插图 /假设稍后解释/:


std::string s {
// members in unknown order
size_type member: 13 00 00 00 HEAP
const char* member: pointer C to ................ "this and that"
};

You print characters here ^^^^^^ not here ^^^^^.


您无法传输除此之外的数据 POD, 这样的功能
printf//

, 其中采取任意数量的参数使用
...

. /参数 " ... " - 此功能 C++, 继承自 C, 它本质上不适合与复杂对象一起使用。 C++/.

你甚至可以编译它吗?

我的编译器 GCC 不喜欢:


printf/"rawname: %s", rawname/;


GCC 4.5.2 错误:


cannot pass objects of non-trivially-copyable
type 'struct std::string' through '...'


GCC 4.1.2 一个警告 + 执行期间的行为:


cannot pass objects of non-POD type 'struct std::string'
through '...'; call will abort at runtime

# ./printf_string
zsh: illegal hardware instruction ./printf_string


它们不会编译它,因为没有标准的方法来传输对象
...

. 编译器无法从简单计算
...

, 它们是价值还是依值 reference/pointer,, 因此,它不知道要生成哪个代码。

但你的勇敢的编译器做了一些事情。 让我们花一点时间,对象看起来像什么 std::string, 然后返回您的编译器如何获得并访问它。

胃对象 std::string

内部元素 std::string 未指定,但通常包含其中任何一个:

当前成员 OR 指向超出线的结尾 /ala
end//

/

其中任何一个允许您简单地计算另一个,而是一对我检查的标准库实现是针对成员进行了优化的。 pointer/
end//

并计算
size//

- 它与迭代器的惯例周期更好。

在堆中的字符缓冲区上的路标 /在实践中,它最有可能存储 NUL 完成I.
c_str//

直接返回它,但此指针可通过该功能访问 - 成员
data//

, 标准允许向文本吸引未完成的文本 NUL, 所以

理论上

他可以有一个终结者 NUL, 仅在呼叫时添加
c_str//

, 或者
c_str//

可以将文本复制到另一个位置,然后添加 NUL 并将指针返回到此新缓冲区/

数据缓冲区 "short string optimisation", 因此,所有几个字符的行都不应该使用一堆

和/或者

指向其他地方的某些对象的指针 /其中有上述要素 + 参考电表 a mutex,...?/

示例:简单的String Store Store

它们可以按任何顺序。 所以,最简单的可能性 - 这是什么 - 那似乎是:


std::string s = "this and that";


现在,

"this and that"-这是

字符串字面量

, 说,at. "A"; 该数据被复制到
string

;
string

不是

记得他在哪里拿走他们


s

- 这是实际对象
std::string

, 说,at. "B"; 让我们想象一下,这是最容易的:


size_type size_;

/将包含值 13, 平等的
strlen/"this and that"/

/


const char* p_data_;

将指示一些新分配的堆积内存,在地址 "C" - 其中复制了 "这是我 that\0"


重要的是要注意地址 "A", 地址 "B" 和地址 "C" 不同的!

如何 printf// 看 std::string

如果我们有一个糟糕的编译器,可以尝试传输我们的对象
std::string


printf//

, 也就是说,这两件事
printf//

可以得到
const char*

, 哪一个
"%s"

说要期待:

1/ 指向对象的指针
std::string

, 即。地址 "B"

2/
sizeof/std::string/

复制字节数据



地址 "A" 一些地址堆栈 "B" 和 / 或注册在哪里
printf//

如果它可以应对这些东西,我会期待这个; - P

然后
printf//

开始从此地址打印字节,就像它们是符号,直到字节发现 0/NUL:

对于脚本 1 上面它在对象中打印字节,例如:

让我们说
size_type

- 这是 4 字节和对象的开头; 尺寸 13 可能是 be 13, 0, 0, 0 或者 0, 0, 0, 13 根据机器是否使用存储协议 big-endian 或者 little-endian... 考虑到他第一次停止 NUL, 它将打印一个符号 13 /结果是一个值 ASCII carriage-return/CR, 将光标返回到行的开头/, 然后停下来,或者他可以绝对打印。 在你自己的情况下,你的行的内容是不同的,所以它会打印一些其他垃圾,但是进入之前只有一个或两个字符 0/NUL.

让我们说
const char*

在突出显示的桩缓冲区中 "C" 位于对象的开头,然后将打印此地址中的各个字符:对于32位指针,这可能是 4 垃圾符号 /假设他们都不会 0/NUL/, 为了 64-bit 这将是 8, 然后他将继续与下一个领域合作
std::string

/可能跟踪指针
end//

, 但如果这是一个领域
size_type

, 然后具有更大的概率 0/NUL/./.



printf//

可以解释对象数据的前四个字节
std::string

作为进一步文本数据的指针......它与之不同 1/: 让我们说一个会员
size_type

是第一个,价值是 13,
printf//

可能错误地将其解释为
const char*

对于地址 13, 然后尝试从那里读取字符。 它实际上保证无法密封一些东西 /现代 OSes/, 因此,这种行为真的很不可能让我们留下 "1".

石油百科

赞同来自:

你需要打印内部 char* 的 std::string:


printf/"rawname: %s", rawname.c_str///;

八刀丁二

赞同来自:

尝试一下


cout << "rawname:" << rawname << endl;
printf/"rawname: %s", rawname.c_str///;


rawname - 这不是一个字符数组,而是一个类实例 std::string. 要获取实际的字符数组,必须调用函数 c_str//

帅驴

赞同来自:

你尝试过 rawname.c_str// 在 printf?

要回复问题请先登录注册