我正在尝试用C ++实现一个基本的移位密码。在找出导致分段错误的原因之前,我不能继续前进。 我使用gdb逐步完成代码,问题似乎源于迭代器。
1 #include <iostream>
2 #include <string>
3
4 std::string encrypt (std::string plain, int key);
5
6 int main()
7 {
8 std::string plaintext;
9 std::getline(std::cin,plaintext,'\n');
10 encrypt(plaintext,3);
11 }
12
13 std::string encrypt(std::string plain, int key)
14 {
15 std::string::iterator ic;
16 for (ic= plain.begin(); ic != plain.end();++ic)
17 {
18 std::cout <<*ic + key << std::endl;
19 }
20 }
错误:
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7b73ef1 in std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() () from /usr/lib/libstdc++.so.6
答案 0 :(得分:8)
您已将encrypt
声明为返回std::string
,但您不会从该函数返回任何内容。您需要返回一个值,或者需要将返回类型更改为void
以指示该函数不返回任何内容。
至于为什么它会像写的一样崩溃,我只能推测。编译器可能已在std::string
中生成对main
析构函数的调用,以清除std::string
返回的encrypt
对象。由于encrypt
实际上没有返回任何内容,因此析构函数最终会被调用一个不存在的对象。应该包含对象的内存可能只包含垃圾数据,析构函数不喜欢它。
答案 1 :(得分:5)
[C ++ 2003标准第6.6.3-2节]流程结束了 功能相当于一个回报 没有价值;这导致了 一个未定义的行为 价值回归功能。
如果您的编译器没有警告您,这是一个非常容易犯的错误。通过启用尽可能多的编译器警告,您可以节省大量调试。在gcc / g ++的情况下,我建议使用“-Wall -Werror”为您正在编写的任何新代码进行编译。使用这些选项,此程序的编译失败,并显示以下消息:
cc1plus: warnings being treated as errors
In function 'std::string encrypt(std::string, int)':
Line 20: warning: control reaches end of non-void function
答案 2 :(得分:3)
编写循环,但将其从使用索引更改为使用迭代器通常是一个错误。如果您打算使用显式循环,那么继续使用索引通常更有意义,至少对于允许随机访问的string
这样的东西。迭代器的主要目的是启用未与容器耦合的通用算法。要充分利用迭代器,请将其与算法一起使用:
int main() {
std::string plaintext;
std::getline(std::cin, plaintext);
std::transform(plaintext.begin(), plaintext.end(),
std::ostream_iterator<char>(std::cout),
std::bind2nd(std::plus<int>(), 3));
return 0;
}
编辑:自从汉斯帕斯特提出以来,使用lambda表达式的版本将如下所示:
std::transform(line.begin(), line.end(),
std::ostream_iterator<char>(std::cout),
[](char ch) { return ch+'\03'; });
只有相对较新的编译器支持此功能 - gcc&gt; = 4.6,Visual Studio&gt; = 2010。
答案 3 :(得分:1)
问题是您的encrypt
函数缺少return
语句。
添加
return "blah blah";
除了修复它之外,请考虑通过引用传递字符串const
,如
std::string const& plain
干杯&amp;第h。,