• Nem Talált Eredményt

Basic data types

It is important that definition and value assignment statements end with a semicolon.

2.3. Basic data types

Basic data types are the equivalents of digits or letters in human language. A PhD dissertation in Mathematics or Winnie the Pooh can be created with the help of them. In the following overview, integer types are divided into smaller groups.

2.3.1. Character types

The char type has a double role. On one hand, it makes it possible to store ASCII (American Standard Code for Information Interchange) characters (Appendix 1. szakasz - ASCII code table), on the other hand, it can be used as one byte signed integer.

char lettera = 'A';

cout << lettera << endl;

char response;

cout << "Yes or No? ";

cin>>response;

// or

response = cin.get();

The double nature of char type is well represented by the possibilities how constant values (literals) can be assigned to them. Characters can be provided between apostrophes or by their integer code. Besides decimal numbers, character codes can be given in octal format (starting with zero) or in a hexadecimal format (starting with 0x). As an example, let's see what the equivalents of capital letter C are.

’C’ 67 0103 0x43

Certain standard control and special characters can be given by the so-called escape sequences. In an escape sequence, character backslash (\) is followed by special characters or numbers, as it can be seen in the table of Appendix 3. szakasz - Escape characters: ‟\n‟, ‟\t‟, ‟\‟‟, ‟\”‟, ‟\\‟.

If we want to work with characters of the 8-bit ANSI code table or with a one-byte integer value, it is recommended to use the unsigned char type.

In order to process a character of the Unicode table, the variable should be the two-byte wchar_t type, and constant character values should be preceded by capital letter L.

wchar_t uch1 = L'\u221E';

wchar_t uch2 = L'K';

wcout<<uch1;

wcin>>uch1;

uch1 = wcin.get();

We should always make sure not to confuse apostrophes (‟) with quotation marks ("). Quotation marks are used for string constants (string literals) in the computer program.

"This is an ANSI string constant."

or

L"This is a Unicode string constant."

2.3.2. Logical Boolean type

Bool type variables can have two values: logical false is 0, while logical true is 1. In Input/Output (I/O) operations logical values are represented by integer values:

bool start=true, end(false);

cout << start;

cin >>end;

This default operation can be overridden by boolalpha and noboolalpha I/O manipulators:

bool start=true, end(false);

cout << boolalpha << start << noboolalpha; // true cout << start; // 1 cin >> boolalpha>> end; // false cout << end; // 0

2.3.3. Integer types

Probably the most frequently used basic data type of the C++ language is int together with its type modifiers.

When an integer value is provided in the program, compilers attempt to assign automatically the int type. If the value is out of the value range of the int type, it uses an integer type with a broader range or it gives an error message in case of a too big constant.

The type of constant integer values can be provided by the U and L postfixes. U means unsigned, L means long:

2012 int

2012U unsigned int

2012L long int

2012UL unsigned long int

2012LL long long int

2012ULL unsigned long long int

Of course, integer values can be given not only in decimal format (2012) but also in octal (03724) or hexadecimal (0x7DC) number system. The choice of these number systems can be expressed in I/O operations by stream manipulators ( dec , oct , hex ), the effects of which last until the next manipulator:

#include <iostream>

using namespace std;

int main() {

int x=20121004;

cout << hex << x << endl;

cout << oct << x << endl;

cout << dec << x << endl;

cin>> hex >> x;

}

It is not needed to provide the prefixes indicating number systems in case of data entering. There are some manipulators that ensure simple formatting possibilities. With parameterized manipulator setw () the width of the field to be used in printing operations can be set; and within that the content can be aligned to the ( left ) or to the right ( right ), which is the default value. setw () effects only the next data element, while alignment manipulators keep their effect until the next alignment manipulator.

#include <iostream>

#include <iomanip>

using namespace std;

int main() {

unsigned int number = 123456;

cout<<'|' << setw(10) << number << '|' << endl;

cout<<'|' << right << setw(10) << number << '|' << endl;

cout<<'|' << left << setw(10) << number << '|' << endl;

cout<<'|' << setw(10) << number << '|' << endl;

}

The output reflects the effects of these manipulators well:

| 123456|

| 123456|

|123456 |

|123456 |

2.3.4. Floating point types

Mathematical and technical calculations require the use of real numbers containing fractions as well. Since the place of the decimal point is not fixed in these values, these numbers can be stored by floating point types: float, double, long double. These types are only different from one another concerning the necessary memory size, the range of values and the number of exact decimal places (see Appendix 4. szakasz - C++ data types and their range of values). (Contrary to the standard recommendation, Visual C++ treats the long double type as double.) It has to be noted already at the very beginning that floating point types do not make it possible to represent fractions precisely, because the numbers are stored in the scientific form (mantissa, exponent), in the binary number system.

double d =0.01;

float f = d;

cout<<setprecision(12)<<d*d<< endl; // 0.0001

cout<<setprecision(12)<<f*f<< endl; // 9.99999974738e-005

There is only one value the value of which is surely exact: 0. Therefore if floating point variables are set to 0, their value is 0.0.

Floating point constants can be provided in two ways. In case of smaller numbers decimal representation is used generally, where the decimal point separates the integer part from the fraction part, e.g. 3.141592653, 100., 3.0.

In case of bigger numbers, the computerized version of scientific form, well known from mathematics is applied, where letter e or E is followed by the exponent (the power of 10): 12.34E-4, 1e6.

Floating point constant values are double type by default. Postfix F designates a float type variable, whereas L designates a long double variable: 12.3F, 1.2345E-10L. (It is a frequent programming error that if the constant contains neither decimal point nor exponent, the constant value will be treated as an integer and not as a floating point type as expected.)

During printing the value of floating point variables, the already mentioned field width ( setw ()), as well as the number of digits after the decimal point - setprecision () can be set (see Appendix 10. szakasz - Input/Output (I/O) manipulators). If this value cannot be printed in the set format the default visualization is used.

Manipulator fixed is used for decimal representation whereas scientific is applied for scientific representation.

#include <iostream>

#include <iomanip>

using namespace std;

int main() {

double a = 2E2, b=12.345, c=1.;

cout << fixed;

cout << setw(10)<< setprecision(4) << a << endl;

cout << setw(10)<< setprecision(4) << b << endl;

cout << setw(10)<< setprecision(4) << c << endl;

}

The results of program running are:

200.0000 12.3450 1.0000

Before getting on, it is worth having a look at automatic type conversion between C++ arithmetical types. It is evident that a type with a smaller value range can be converted into a type with a wider range without data loss.

However, in the reverse direction, the conversion generally provokes data loss for which compilers do not alert, and one part of the bigger number may appear in the "smaller" type variable.

short int s;

double d;

float f;

unsigned char b;

s = 0x1234;

b = s; // 0x34 ↯

// --- f = 1234567.0F;

b = f; // 135 ↯ s = f; // -10617 ↯

// --- d = 123456789012345.0;

b = d; // 0 ↯ s = d; // 0 ↯

f = d; // f=1.23457e+014 – precision loss ↯

2.3.5. enum type

In computer programs integer type constant values that are logically in connection with one another are often used. The readability of our programs is much better if these values are replaced by names. For that purpose, it is worth defining a new type (enum) with its range of values:

enum 〈 type identifier〉 { enumeration };

If type identifier is not given, the type is not created only the constants. Let's see the following example with an enumeration that contains the days of the week.

enum workdays {Monday, Tuesday, Wednesday, Thursday, Friday};

A separate integer value is associated to the names in this enumeration. By default, the value of the first element (Monday) is 0, that of the next one (Tuesday) is 1, and so on (the value of Friday is 4).

In enumerations, we can directly assign values to their elements. In that case, automatic incrementation continues from the given value. It is not a problem if the same values are repeated or if we assign negative values to the elements. However, we have to make sure that in the definitions there are not two enum elements with the same name within a given visibility scope (namespace).

enum consolecolours {black,blue,green,red=4,yellow=14,white};

In the enumeration named consolecolours the value of white is 15.

In enumerations that do not contain direct value assignment, the number of elements can be obtained by adding an extra element:

enum stateofmatter { ice, water, vapour, numberofstates};

The value of element numberofstates equals to the number of states, i.e. 3.

In the following example the usage of enum types and enum constants are demonstrated:

#include <iostream>

using namespace std;

int main() {

enum card { clubs, diamonds, hearts, spades };

enum card cardcolour1 = diamonds;

card cardcolour2 = spades;

cout << cardcolour2 << endl;

int colour = spades;

cin >> colour;

cardcolour1 = card(colour);

}

Enumeration type variables can be defined according to the rules of both C and C++ languages. In C language enum types are defined by keyword enum and type identifiers together. In C++ language type identifiers represent alone enum types.

When we print an enumeration type variable or an enumeration constant, by default we get the integer corresponding to the given element. However, when the input is read in, the situation is completely different.

Since enum is not a predefined type of C++ language, contrary to the above mentioned types, cin does not know it. As it can be seen in the example, reading in can be realized by using an int type variable. However, the typedness of C++ language may cause problems here since it only does certain conversions if it is "asked" to do so with type conversion (cast) operation: typename(value). (The programmers have to check the values since C++ does not deal with them.)

2.3.6. sizeof operation

C++ language contains an operator that is evaluated during compilation and that determines the size of any type or any variable and expression type in bytes.

sizeof(typename)

sizeofvariable/expression sizeof(variable/expression)

From that, we can infer the type of the result of a given expression:

cout << sizeof('A' + 'B') <<endl; // 4 - int cout << sizeof(10 + 5) << endl; // 4 - int cout << sizeof(10 + 5.0) << endl; // 8 - double cout << sizeof(10 + 5.0F) << endl; // 4 - float