我想学习如何编写好的代码。现在从简单的程序开始。因此,有关样式,可读性或更有效的实现方式等方面的任何建议将不胜感激!

#include <algorithm>
#include <iostream>
using namespace std;

int main(int argc, char** argv) 
{
  bool running = true;

  while(running == true)
  {
    string input;
    cout << "[Enter 'exit' to exit the program]\n";
    cout << "Enter the text you want to reverse: ";
    getline(cin, input);

    if (input.compare("exit") == 0)
    {
      running = false;
      break;
    }

    reverse(input.begin(), input.end());
    cout << "The reversed version of your text is: " << input << endl << endl;
  }      
  return 0;
}


评论

几乎从来没有将布尔值与(运行)或while(!找到)进行比较。

它不处理unicode(或任何多字节编码)

@JoopEggen为什么不呢?我希望您不是要说永远不要将两个布尔值相互比较

@Celeritas比较布尔值始终是一种难得的乐趣,可用于等效等。因此认为“差不多”。但是,如果(正在运行==假)==假,则有人会听到思考。

for循环也应该是if(!getline(cin,input)|| input ==“ exit”)。

#1 楼

不要using namespace std;


因为可能发生名称冲突,这被认为是不好的做法,...尽管没有人会伤害您,因为这是一个很小的程序:)
< br请勿将布尔值与布尔值进行比较

完全不需要running == true之类的东西,因为running本身已经是一个条件。只需使用running即可。

不需要running


不需要变量running。您需要一个用于嵌套循环(要同时突破),但对于单个循环,最好使用单个break和无限循环。

为什么要使用compare

看到input.compare("exit") == 0会让我直接进入文档,因为我不知道compare的返回值是什么。

if (input == "exit");


更清楚。

不要连续刷新2次(或根本不刷新)

std::endl打印新行,然后刷新stdout。这会导致性能下降,因此最好输出实际的换行符。在您的情况下:

std::cout << something << "\n\n";


请注意,在某些平台上(或如果需要),必须冲洗蒸汽才能看到输出。在这种情况下,最好显式并使用std::flush

您没有使用命令行参数

那么为什么要命名它们呢?您可以省略名称,或定义不带任何参数的main

int main(int, char**) {} //1)
int main() {} //2)


我更喜欢选项2。

您的代码使用实现特定行为

std::string标头中定义了string。并非每个编译器都包括带有stringiostreamalgorithm(VS不包括),因此您必须显式包括它。不要依赖自动包含。

从技术上讲,您不需要return 0;


仅对于main,如果省略return 0;,编译器会添加它对您而言,因此从技术上讲,您无需指定它。

评论


\ $ \ begingroup \ $
要点:行为是特定于实现的,而不是“定义实现”;后者是标准中的术语,需要编译器来记录其行为。
\ $ \ endgroup \ $
–贝克特(Pete Becker)
16-09-23在12:45



\ $ \ begingroup \ $
当C ++标准说某事是“实现定义的”时,这意味着一个合格的实现必须记录它的工作。对于头文件,允许C ++实现将其他#include指令放入头文件(与C头不同)。因此,当您#include 时,您可能还会从中获得所有内容。那是特定于实现的(或您喜欢的其他任何术语)。它不是实现定义的,因为C ++标准不需要实现来记录其#include结构。
\ $ \ endgroup \ $
–贝克特(Pete Becker)
16-09-23在19:22

\ $ \ begingroup \ $
“不要使用命名空间std;”为什么不?该建议仅对头文件(或打算包含的文件)有效。 “不要将布尔值与布尔值进行比较”那么您希望将它们与之进行比较?也许您的意思是常量,例如true / false。
\ $ \ endgroup \ $
–luk32
16-09-24在14:24

\ $ \ begingroup \ $
@ luk32不是。在源文件中仍然可能发生名称冲突。它还包括许多通用名称,字符串,列表,向量,for_each等,因此不可用。是的,我是那个意思。
\ $ \ endgroup \ $
–Rakete1111
16-09-24在14:26

\ $ \ begingroup \ $
@ luk32我看不到以std ::前缀所有内容如何损害可读性。如果一个类定义了一个反向函数,并且使用了命名空间std;在源文件的顶部,您将获得模糊的功能。但是可以,有时候由于编码风格而没有必要(例如,每个函数都以大写字母开头)。
\ $ \ endgroup \ $
–Rakete1111
16-09-24在14:38

#2 楼

除了以前的答案:


输入后还应检查流状态(例如,用户可以按Ctrl + Z并输入,或者可以到达输入文件的末尾)。

return 0;函数中不需要main
您也可以将此代码移至该函数,然后将break;替换为return;


我的版本:

#include <iostream>
#include <string>
#include <algorithm>

int main(int argc, char** argv)
{
    using std::cout;
    using std::endl;
    while (true)
    {
        std::string input;
        cout << "[Enter 'exit' to exit the program]\n";
        cout << "Enter the text you want to reverse: ";

        if (!getline(std::cin, input) || input.compare("exit") == 0)
            break;

        std::reverse(input.begin(), input.end());
        cout << "The reversed version of your text is: " << input << endl << endl;
    }
}


#3 楼

一个小小的nitpick,在下面的代码中:

string input;
cout << "[Enter 'exit' to exit the program]\n";
cout << "Enter the text you want to reverse: ";
getline(cin, input);


我会将字符串输入向下移到getline(...)中使用它的位置旁边:

cout << "[Enter 'exit' to exit the program]\n";
cout << "Enter the text you want to reverse: ";
string input;
getline(cin, input);


仅有助于将通用代码保持在一起。在像这样的一个小例子中,很容易找借口,但是说在字符串输入和getline之间有20条或更多的语句。读者必须记住输入是在阅读其他不相关的语句时定义的。

很小,但是有些东西要记在脑海中。

#4 楼

删除“类型退出退出”的东西。如果有人想撤消“退出”→“提示”怎么办?只需使用结束程序的标准^ C(Control-C)。您甚至不需要执行任何操作。如果有人想退出,则只需按Control-C。

最终版本:



#include <algorithm>
#include <iostream>
using namespace std;

int main(int argc, char** argv) 
{

  while(true)
  {
    string input;
    cout << "Enter the text you want to reverse: ";
    getline(cin, input);

    reverse(input.begin(), input.end());
    cout << "The reversed version of your text is: " << input << endl << endl;
  }      
  return 0;
}


评论


\ $ \ begingroup \ $
使用SIGINT可能是结束程序的标准(尽管我从未见过如此命名),但是通常您必须处理该信号,否则您将不做任何清理就退出。而且,它是特定于实现的,即POSIX。不确定Windows上的应用程序如何处理Control-C。最好只说“输入文本<...>或按Enter退出”。
\ $ \ endgroup \ $
–俄罗斯
16 Sep 24'6:54



\ $ \ begingroup \ $
@Ruslan是的,您可以将其发布为另一个答案。
\ $ \ endgroup \ $
–没了
16-09-24在8:56

#5 楼

除了别人说的以外,您的程序现在正在运行,因为iostream恰好有一个#include <string>,但这不是必需的。最好包含您正在使用的内容,这样您就知道该程序在任何情况下都可以使用,除了您的2个包含项之外,您还应该添加

#include <string>


#6 楼

在开始时,应尽可能避免不良做法。


请勿使用namespace std;这是不好的做法,以后会伤害您。因此,请尽快将其删除,并在需要时开始添加std::

std::reverse是通用例程,因此,我建议您探索实现该目标的不同方法。

for (auto it = input.rbegin(); it != input.rend(); ++it) {
    std::cout << *it++;
}
std::cout << std::endl;


请注意,这段代码将使您的字符串不受影响,而您当前的代码实际上是反转字符串,然后将其打印出来。



评论


\ $ \ begingroup \ $
(我最喜欢的折衷方法是使用std :: cout;。)
\ $ \ endgroup \ $
–灰胡子
16-09-23在8:28

\ $ \ begingroup \ $
如果一次引出整个字符串比一次引出一个字符的效率更高,我不会感到惊讶。
\ $ \ endgroup \ $
–coderodde
16-09-23在8:42



\ $ \ begingroup \ $
@coderodde可能是正确的,但是这样做的主要原因是数据保持不变
\ $ \ endgroup \ $
– miscco
16-09-23在9:03

\ $ \ begingroup \ $
我投票赞成,因为您使用的是auto&it。您很幸运,任何临时都可以转换为const ref,这就是为什么所引用的对象仍然有效。反正应该是自动的吧
\ $ \ endgroup \ $
–难以置信
16-09-23在11:35



\ $ \ begingroup \ $
@misco为什么不编辑答案来修复代码?
\ $ \ endgroup \ $
–俄罗斯
16-09-24在7:01

#7 楼

我可以在一个简短的程序中给出的唯一提示是,您可以消除running布尔变量:

while(true)
{
    string input;
    cout << "[Enter 'exit' to exit the program]\n";
    cout << "Enter the text you want to reverse: ";
    getline(cin, input);

    if (input.compare("exit") == 0)
    {
        break;
    }

    reverse(input.begin(), input.end());
    cout << "The reversed version of your text is: " << input << endl << endl;
}


希望有所帮助。

#8 楼

假设您实际上希望用户输入脱离程序而不是使用Ctrl-C,则可以执行以下操作:

说了关于您的基础知识,但在本示例中已经实现了它们。

#9 楼

在这种情况下,这实际上不是必需的,但是如果您要写一个大字符串的反义字,那么就不应该就位反转它然后打印。而是直接打印它:

std::copy(in.rbegin(), in.rend(),
   std::ostreambuf_iterator<char>(std::cout));


在循环中使用std::ostreambuf_iterator比在循环中使用operator<<更可取,因为后者会为每个单个字符构造一个哨兵对象而产生开销,而前者只需要一个哨兵。

评论


\ $ \ begingroup \ $
看一下miscco的答案。
\ $ \ endgroup \ $
–灰胡子
16-09-24在7:03

\ $ \ begingroup \ $
@greybeard我以前没看过,谢谢指出。我仍然认为我的答案是合理的:它显示了执行此处最简单的操作的唯一(?)方法:反向打印字符串(在单个输出操作中)请参见我的编辑。
\ $ \ endgroup \ $
–Daniel Jour
16 Sep 24 '17:10