【Learncpp中文翻译版】【1.9、1.10、1.11】

原文链接:1.9 — Introduction to literals and operators
原文链接:1.10 — Introduction to expressions
原文链接:1.11 — Developing your first program

声明:

  • 本文旨在方便了解学习C++语法,切勿用于任何商业用途。
  • 由于本人英语水平有限,文章中可能存在语义错误,如有疑问请参照原文,也可以在评论区指出错误。

1.9 — Introduction to literals and operators

文字

请考虑以下两个语句:

std::cout << "Hello world!";
int x{ 5 };

什么是“你好世界!”和“5”?它们是字面意思。文本(也称为文本常量)是直接插入到源代码中的固定值。

文本和变量都有一个值(和一个类型)。但是,文本的值是固定的,不能更改(因此称为常量),而变量的值可以通过初始化和赋值来更改。


运算符

在数学中,运算是涉及零个或多个输入值(称为操作数)的数学计算,该值产生新值(称为输出值)。要执行的特定操作由称为运算符的符号表示。

例如,作为孩子,我们都知道 2 + 3 等于 5。在这种情况下,文字 2 和 3 是操作数,符号 + 是告诉我们对操作数应用数学加法以产生新值 5 的运算符。

在C++,操作按预期工作。例如:

#include <iostream>

int main()
{
    std::cout << 1 + 2;

    return 0;
}

在这个程序中,文字1和2是加号(+)运算符的操作数,它产生输出值3。然后将该输出值打印到控制台。在C++中,操作的输出值通常称为返回值。
您可能已经非常熟悉数学中常用的标准算术运算符,包括加法(+)、减法(-)、乘法(*)和除法(/)。在C++中,赋值(=)也是运算符,插入(<<)、提取(>>)和相等(= =)也是运算符。虽然大多数运算符都有名称符号(例如+或= =),但也有一些运算符是单词(例如new、delete和throw)。

作者备注:
由于在我们更详细地讨论运算符时会变得清楚的原因,对于作为符号的运算符,通常将运算符的符号附加到单词运算符。
例如,加号运算符将被写入运算符+,而提取运算符将被写为运算符>>。

运算符作为输入的操作数称为运算符的arity。很少有人知道这个词的意思,所以不要把它放在谈话中,希望任何人都知道你在说什么。C++中的运算符有四种不同的算术:

一元运算符作用于一个操作数。一元运算符的一个示例是-运算符。例如,给定-5,运算符-取文字操作数5并翻转其符号以产生新的输出值-5。

二元运算符作用于两个操作数(通常称为左操作数和右操作数,因为左操作数出现在运算符的左侧,而右操作数显示在运算符的右侧)。二进制运算符的一个例子是 + 运算符。例如,给定 3 + 4 ,运算符 + 取左操作数 3 和右操作数 4,并应用数学加法产生新的输出值7。插入(<<)和提取(>>)运算符是二进制运算符,左侧为std::coutstd::cin,右侧为要输出的值或要输入的变量。

三元运算符作用于三个操作数。C++ 中只有其中一种(条件运算符),我们稍后将介绍。

空运算符作用于零操作数。C++ 中也只有其中一个(抛出运算符),我们稍后也会介绍。

注意,有些运算符有多种含义,具体取决于它们的使用方式。例如,运算符( - )有两个用处,它可以以一元形式用于反转数字的符号(例如,将5转换为-5,反之亦然),也可以以二进制形式用于进行减法(例如,4 - 3)。


链接运算符

运算符可以链接在一起,这样一个运算符的输出可以用作另一个运算符输入。例如,给定以下条件:2*3+4,乘法运算符首先执行,并将左操作数2和右操作数3转换为返回值6(成为加号运算符的左操作数)。接下来,执行加号运算符,并将左操作数6和右操作数4转换为新值10。
当我们深入探讨运算符的主题时,我们将进一步讨论运算符的执行顺序。现在,只要知道算术运算符的执行顺序与标准数学中的相同就足够了:首先是圆括号,然后是指数,然后是乘除,然后是加法和减法。


返回值和副作用

C++中的大多数运算符只是使用它们的操作数来计算返回值。例如,-5产生返回值-5,2+3产生返回值5。有一些运算符不产生返回值(例如delete和throw)。稍后我们将介绍这些功能。
某些运算符有其他行为。除了产生返回值之外,具有一些可观察到的效果的运算符被称为具有副作用。例如,当计算x=5时,赋值运算符具有将值5赋值给变量x的副作用。即使在运算符完成执行之后,x的变化值也是可观察的(例如,通过打印x的值)。std::cout<<5具有将5打印到控制台的副作用。我们可以观察到,即使在std::cout<<5执行完毕后,5也已打印到控制台。
具有副作用的运算符通常被调用为副作用的行为,而不是那些运算符产生的返回值(如果有的话)。

对于我们主要为其返回值调用的运算符(例如运算符 + 或运算符 * ),其返回值通常很明显(例如操作数的和或积)。

对于我们主要为其副作用而调用的运算符(例如运算符 = 或运算符 << ),它们产生的返回值并不总是显而易见的(如果有的话)。例如,您希望x=5具有什么返回值?

运算符 = 和运算符 <<(用于将值输出到控制台时)都返回其左操作数。因此,x = 5返回 x,std::cout<<5返回std::cout。这样做是为了可以链接这些运算符。

例如,x = y = 5计算为x = ( y = 5 )。首先y = 5将 5 赋值给 y 。此操作然后返回 y ,然后可以将 y 赋值给 x 。

std::cout<<“Hello”<<“world”的评估结果为(std::cout<<”Hello“)<<”world!“。这首先向控制台打印“Hello”。此操作返回std::cout,然后也可以使用它将“world!”打印到控制台。

1.10 — Introduction to expressions

表达式

考虑以下一系列声明:

// five() is a function that returns the value 5
int five()
{
    return 5;
}

int main()
{
    int a{ 2 };             // initialize variable a with literal value 2
    int b{ 2 + 3 };         // initialize variable b with computed value 5
    int c{ (2 * 3) + 4 };   // initialize variable c with computed value 10
    int d{ b };             // initialize variable d with variable value 5
    int e{ five() };        // initialize variable e with function return value 5

    return 0;
}

这些语句中的每一个都定义了一个新变量,并用一个值初始化它。注意,上面显示的初始化器使用了各种不同的构造:文本、变量、运算符和函数调用。不知怎么的,C++正在将所有这些不同的东西转换成一个单独的值,然后可以用作变量的初始化值。

所有这些都有什么共同点?他们使用一个表达式。

表达式是计算单个值的文本、变量、运算符和函数调用的组合。执行表达式的过程称为求值,生成的单个值称为表达式的结果。

相关内容

虽然大多数表达式都用于计算值,但表达式也可以标识对象(可以对其求值以获取对象所持有的值)或函数(可以调用该函数以获取函数返回的值)。我们在第9.2课——价值类别(左值和右值)中对此进行了更多讨论。现在,我们假设所有表达式都计算值。

计算表达式时,将计算表达式中的每个项,直到保留一个值。下面是一些不同类型的表达式的示例,并附有说明它们如何求值的注释:

2               // 2 is a literal that evaluates to value 2
"Hello world!"  // "Hello world!" is a literal that evaluates to text "Hello world!"
x               // x is a variable that evaluates to the value of x
2 + 3           // operator+ uses operands 2 and 3 to evaluates to value 5
five()          // evaluates to the return value of function five()

正如您所看到的,文字根据其自身的值求值。变量的计算结果为变量的值。运算符(如运算符+)使用其操作数计算为其他值。我们还没有涉及函数调用,但在表达式的上下文中,函数调用的计算结果是函数返回的值。

涉及具有副作用的运算符的表达式有点棘手:

x = 5           // has side effect of assigning 5 to x, evaluates to x
x = 2 + 3       // has side effect of assigning 5 to x, evaluates to x
std::cout << x  // has side effect of printing x to console, evaluates to std::cout

请注意,表达式不以分号结尾,并且不能自己编译。例如,如果要尝试编译表达式x=5,编译器会抱怨(可能是缺少分号)。相反,表达式始终作为语句的一部分进行求值。

例如,使用以下语句:

int x{ 2 + 3 }; // 2 + 3 is an expression that has no semicolon -- the semicolon is at the end of the statement containing the expression

如果要将此语句分解为其语法,它将如下所示:

type identifier { expression };

类型可以是任何有效的类型(我们选择了int)。标识符可以是任何有效的名称(我们选择了x<)。表达式可以是任何有效的表达式(我们选择了2+3,它使用两个文本和一个运算符)。


表达式语句

某些表达式(如x=5)对其副作用很有用(在本例中,将值5赋给变量x)。然而,我们在上面提到,表达式不能自己执行——它们必须作为语句的一部分存在。那么我们如何使用这样的表达呢?

幸运的是,很容易将任何表达式转换为等效语句。表达式语句是由表达式后跟分号组成的语句。执行表达式语句时,将对表达式求值。

因此,我们可以使用任何表达式(例如x=5),并将其转换为将编译的表达式语句(x=5;)。
在表达式语句中使用表达式时,表达式生成的任何返回值都将被丢弃(因为它未被使用)。


无用的表达式语句

我们还可以生成编译但没有效果的表达式语句。例如,表达式语句(2*3;)是一个表达式语句,其表达式的结果值为6,然后将其丢弃。虽然语法上有效,但这样的表达式语句是无用的。一些编译器(如gcc和Clang)如果能够检测到表达式语句是无用的,就会产生警告。


1.11 — Developing your first program

前面的课程介绍了许多术语和概念,我们将在创建的每个程序中使用这些术语和概念。在本课中,我们将介绍将这些知识集成到第一个简单程序中的过程。

乘以2

首先,让我们创建一个程序,要求用户输入一个整数,等待他们输入一个数字,然后告诉他们这个数字的2倍。该程序应该产生以下输出(假设我输入了4作为输入):

Enter an integer: 4
Double that number is: 8

我们如何解决这个问题?在步骤中。

最佳实践

新程序员经常试图一次编写一个完整的程序,然后在产生大量错误时不知所措。一个更好的策略是一次添加一个片段,确保它能够编译并测试它。然后当你确定它有效时,继续下一个片段。

我们将在这里利用这一战略。在我们完成每个步骤时,将每个程序键入(不要复制/粘贴)到编译器中,编译并运行它。

首先,创建一个新的控制台项目。

现在让我们从一些基本的脚手架开始。我们知道我们将需要一个main()函数(因为所有C++程序都必须有一个),所以如果您的IDE在创建新项目时没有创建一个空函数,那么让我们创建一个:

int main()
{
	return 0;
}

我们知道我们需要将文本输出到控制台,并从用户的键盘获取文本,因此我们需要包含iostream以访问std::coutstd::cin

#include <iostream>

int main()
{
	return 0;
}

现在让我们告诉用户,我们需要他们输入一个整数:

#include <iostream>

int main()
{
	std::cout << "Enter an integer: ";

	return 0;
}

此时,程序应生成以下结果:

Enter an integer:

然后终止。

接下来,我们将获取用户的输入。我们将使用std::cin和operator>>来获取用户的输入。但我们还需要定义一个变量来存储该输入以供以后使用。

#include <iostream>

int main() // note: this program has an error somewhere
{
	std::cout << "Enter an integer: ";

	int num{ }; // define variable num as an integer variable
	std::cin << num; // get integer value from user's keyboard

	return 0;
}

是时候编译我们的更改了…
噢!以下是作者在Visual Studio 2017上获得的内容:

1>------ Build started: Project: Double, Configuration: Release Win32 ------
1>Double.cpp
1>c:\vcprojects\double\double.cpp(8): error C2678: binary '<<': no operator found which takes a left-hand operand of type 'std::istream' (or there is no acceptable conversion)
1>c:\vcprojects\double\double.cpp: note: could be 'built-in C++ operator<<(bool, int)'
1>c:\vcprojects\double\double.cpp: note: while trying to match the argument list '(std::istream, int)'
1>Done building project "Double.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

我们遇到了编译错误!

首先,由于该程序是在我们进行最新更新之前编译的,并且现在没有编译,所以错误必须出现在我们刚刚添加的代码中(第7行和第8行)。这大大减少了查找错误所需扫描的代码量。第7行非常简单(只是一个变量定义),因此错误可能不存在。因此,第8行可能是罪魁祸首。

其次,此错误消息不太容易阅读。但是,让我们分离一些关键元素:编译器告诉我们它在第8行遇到了错误。这意味着实际误差可能在第8行,或者可能在前一行,这加强了我们之前的评估。

接下来,编译器告诉您,它找不到具有std::istream类型(std::cin类型)的左手操作数的’<<'运算符。换句话说,运算符<<不知道如何处理std::cin,因此错误必须是使用std::xin或运算符<<。

现在看到错误了吗?如果你没有,花点时间看看你能不能找到它。

以下是包含更正代码的程序:

#include <iostream>

int main()
{
	std::cout << "Enter an integer: ";

	int num{ };
	std::cin >> num; // std::cin uses operator >>, not operator <<!

	return 0;
}

现在程序将编译,我们可以测试它。程序将等待您输入一个数字,所以让我们输入4。输出应如下所示:

Enter an integer: 4

快到了!最后一步是将数字加倍。

一旦完成最后一步,我们的程序将成功编译并运行,产生所需的输出。

我们(至少)有三种方法可以做到这一点。让我们从最坏到最好。


不好的解决方案

#include <iostream>

// worst version
int main()
{
	std::cout << "Enter an integer: ";

	int num{ };
	std::cin >> num;

	num = num * 2; // double num's value, then assign that value back to num

	std::cout << "Double that number is: " << num << '\n';

	return 0;
}

在这个解决方案中,我们使用一个表达式将num乘以2,然后将该值赋回num。从那时起,num将包含我们的加倍数。

为什么这是一个糟糕的解决方案:

  • 在赋值语句之前,num包含用户的输入。赋值后,它包含一个不同的值。这太令人困惑了。
  • 我们通过为输入变量分配一个新值来重写用户的输入,因此如果我们想扩展程序以稍后使用该输入值执行其他操作(例如,将用户的输入增加三倍),那么它已经丢失了。

最好的解决方案

#include <iostream>

// less-bad version
int main()
{
	std::cout << "Enter an integer: ";

	int num{ };
	std::cin >> num;

	int doublenum{ num * 2 }; // define a new variable and initialize it with num * 2
	std::cout << "Double that number is: " << doublenum << '\n'; // then print the value of that variable here

	return 0;
}

这个解决方案非常容易阅读和理解,并解决了在最坏的解决方案中遇到的两个问题。

这里的主要缺点是我们定义了一个新变量(这增加了复杂性)来存储我们只使用一次的值。我们可以做得更好。


首选解决方案

#include <iostream>

// preferred version
int main()
{
	std::cout << "Enter an integer: ";

	int num{ };
	std::cin >> num;

	std::cout << "Double that number is: " <<  num * 2 << '\n'; // use an expression to multiply num * 2 at the point where we are going to print it

	return 0;
}

这是该组的首选解决方案。当std::cout执行时,将对表达式num*2求值,结果将是num值的两倍。该值将被打印。num本身的值不会被更改,因此我们可以稍后根据需要再次使用它。

此版本是我们的参考解决方案。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
### 回答1: 这个警告的意思是,你正在使用 Java 9 作为你程序的源代码本,但是你的目标运行环境却是 Java 1.9。这意味着你的程序可能使用了 Java 9 中的一些特性或者 API,而这些东西在 Java 1.9 中可能并没有。这可能会导致编译错误或者运行时错误。 要解决这个问题,你需要修改你的编译器设置,将目标发行设置为 Java 9 或者更高本。你也可以尝试修改你的代码,使用可以在 Java 1.9 中使用的特性或者 API。 ### 回答2: Java语言本升级过程中,会对新特性进行添加和旧特性进行废弃或删除。在进行编译时,编译器会校验源代码的发行本与目标发行本之间的匹配关系。 当我们在使用较高本的Java编译器(例如jdk9)编译源代码时,如果源代码中使用了较低本(例如jdk1.8)所不支持的特性或语法,编译器会给出警告,提示我们源代码与目标发行本不匹配。 具体到这个错误提示信息:"警告: 源发行 9 需要目标发行 1.9",意思是我们在使用jdk9编译源代码时,源代码中使用了jdk9所支持的特性或语法,但我们指定的目标发行本较低(1.9)。换句话说,源代码中包含了较高本的特性,但我们希望将其编译成较低本的字节码文件。 为了解决这个警告,我们可以采取以下两种方法之一: 1. 将目标发行本升级至与源发行本相匹配。在命令行或编译器参数中,指定目标发行本为9,即与源发行本相同。这样就可以编译通过,并生成与源发行本相同的字节码文件。 2. 修改源代码,将其中使用了较高本特性的部分进行改写,使其适配目标发行本。可以通过查阅相关文档或参考其他编码规范,找到合适的替代方案或写法。 需要注意的是,当目标发行本较低时,有些较高本的特性可能无法使用或无法正常运行。因此,在选择升级发行本或改写代码时,需要综合考虑项目的需求和兼容性要求。 ### 回答3: 当我们在命令行中编译和运行Java程序时,有时会收到警告信息,如"警告: 源发行 9 需要目标发行 1.9"。 这个警告表示使用的Java本不兼容。源发行指的是我们使用的Java编译器的本,而目标发行指的是我们要运行程序所需的Java本。 在这个警告中,源发行是Java 9,这意味着我们使用的Java编译器是Java 9本。然而,目标发行却是1.9,这表明运行该程序所需的Java本是1.9。这两个本号不匹配,因此会出现警告。 为了解决这个警告,我们需要进行一些修改。我们可以通过以下两种方法之一来解决这个问题: 1. 升级源发行:将源发行升级到与目标发行相匹配的本。在这种情况下,我们需要将源发行升级到Java 1.9,以与目标发行1.9匹配。 2. 修改目标发行:将目标发行修改为与源发行相匹配的本。在这种情况下,我们需要将目标发行修改为Java 9,以与源发行Java 9匹配。 根据具体情况,选择哪种方法来解决这个警告。这通常取决于我们的需求和环境。确保源发行和目标发行本匹配,可以确保我们的程序能够顺利编译和运行,避免出现不兼容的错误。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Eternity_GQM

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值