C++ Syntax Basics

Code Framework

If you do not want to delve into the underlying principles, you can simply memorize this “framework” when you are starting out:

#include <cstdio>
#include <iostream>

int main() {
  // do something...
  return 0;
}
What is include?

#include is actually a preprocessing directive. It means to “place” a file at the location of this directive; the file being “placed” is called a header file. In other words, during compilation, the compiler “copies” the contents of the header file iostream and “pastes” them at the statement #include <iostream>. This allows you to use the objects provided by iostream, such as std::cin, std::cout, and std::endl.

If you have learned C, you will find that the header files in the C++ we have encountered so far generally do not have an .h suffix, while the C header files xx.h have become cxx, such as stdio.h becoming cstdio. Since C++ maintains compatibility with C, it directly uses the header files from C; the c prefix distinguishes C++ header files from C header files.

Generally speaking, you should determine which header files to #include according to the needs of the C++ program you are writing. However, if you #include extra header files, they only increase compilation time and have almost no effect on running time. So far we have encountered only the two header files iostream and cstdio; if you only need scanf and printf, you do not need to #include <iostream>.

Can you #include a header file that you wrote yourself? The answer is yes.

You can write a header file yourself, such as myheader.h. Then put it in the same directory as your code and use #include "myheader.h". Note that custom header files must use quotation marks rather than angle brackets. Of course, you can also use the compilation option -I <header_file_path> to tell the compiler where to look for the header file, so it does not need to be placed in the same directory as the code.

What is main()?

It can be understood that the code in main() is executed when the program runs.

In fact, the main function is called by the system or an external program. For example, when you call your program on the command line, you are calling the main function in your program (the construction of global variables is completed first).

The final return 0; indicates that the program ran successfully. By default, returning 0 when the program ends indicates that everything is normal; otherwise, the return value indicates an error code (under Windows, the hexadecimal form of this error code can be looked up on the Windows Error Codes website). To whom is this value returned? It is returned to the system or external program that called the program you wrote, which receives the return value when your program ends. If there is no return statement, the default return value when the program ends normally is also 0.

In C or C++, a nonzero return value from the program causes a runtime error (RE).

Comments

There are two ways to write comments in C++ code:

  1. Inline comments

    They begin with //, and all subsequent content on the line is a comment.

  2. Comment blocks

    They begin with /* and end with */; all content in between is a comment and may span multiple lines.

Comments do not affect program execution. They can be used to explain what a program means, and can also make a section of code not execute while retaining it in the source file.

In project development, comments can facilitate later maintenance and reading by others.

In OI, few people write many comments, but comments can make it easier to organize one's thoughts while writing code or to review it later. Moreover, if one is writing an editorial or tutorial, a suitable amount of commenting can make it easier for readers to read and understand the intent of the code. We hope everyone can develop the good habit of writing comments.

Input and Output

cin and cout

#include <iostream>

int main() {
  int x, y;                          // Declare variables
  std::cin >> x >> y;                // Read x and y
  std::cout << y << std::endl << x;  // Output y, a newline, then x
  return 0;                          // End the main function
}
What is a variable?

See the variables page.

What is std?

std is the namespace used by the C++ standard library. Namespaces are used to avoid duplicate names.

For detailed knowledge about namespaces, see the namespace page.

scanf and printf

scanf and printf are actually functions provided by the C language. In most cases, they are faster than cin and cout, and they make it convenient to control input and output formats.

Input/Output Optimization

For the specific differences between cin/cout and scanf/prinf, and for input/output optimization, see the input/output optimization page.

#include <cstdio>

int main() {
  int x, y;
  scanf("%d%d", &x, &y);   // Read x and y
  printf("%d\n%d", y, x);  // Output y, a newline, then x
  return 0;
}

Here, %d means that the variable being read/output is a signed integer (int) variable.

Similarly:

  1. %s represents a string.
  2. %c represents a character.
  3. %lf represents a double-precision floating-point number (double).
  4. %lld represents a long integer (long long). Depending on the system, it may also be %I64d.
  5. %u represents an unsigned integer (unsigned int).
  6. %llu represents an unsigned long integer (unsigned long long), and may also be %I64u.

In addition to type specifiers, there are ways to control formatting. Many are not commonly used; two common ones are listed below:

  1. %1d represents an integer with a length of 1. When reading, digits can be read one by one even without spaces. When outputting, if the specified length is greater than the number of digits, spaces are used to pad before the number. If the specified length is less than the number of digits, it has no effect.
  2. %.6lf, used for output, retains six decimal places.

Other numbers can be filled in at the corresponding positions of these two operators. For example, %.3lf retains three decimal places.

What are “double-precision floating-point numbers” and “long integers”?

These denote variable types. As above, they will be explained together in Variables.

Why is there an & operator in scanf?

Here, & is actually the address-of operator and returns the address of a variable in memory. The parameters accepted by scanf are the addresses of variables. It may be necessary to study pointers to explain this completely; for now, you only need to remember it.

What is \n?

\n is an escape character representing a newline.

Escape characters are used to represent characters that cannot be entered directly, such as a newline that cannot be entered directly because a string literal cannot contain a line break, quotation marks that cannot be entered because they have special meanings, and backslashes that cannot be entered because they represent escape characters.

Common escape characters include:

  1. \t represents a tab.

  2. \\ represents \.

  3. \" represents ".

  4. \0 represents the null character and is used to mark the end of a C-style string.

  5. \r represents a carriage return. The newline character in Linux is \n, while in Windows it is \r\n. In OI, use \n when output needs a newline. However, when reading character by character, line endings may cause some problems that require attention. For example, gets treats \n as the end of a string; if the line ending is \r\n, \r remains at the end of the string.

  6. In particular, %% represents % and can only be used in printf or scanf; in other string literals, simply use %.

What is a literal?

A “literal” is a program fragment that directly serves as a value in code. For example, 3 is an int literal, and 'c' is a char literal. The "hello world" in the program we wrote above is also a string literal.

A literal without explanation or justification is also called a “magic number”, and this is highly discouraged if the code needs to be read by others.

Some Extensions

Whitespace in C++

In C++, all whitespace characters (spaces, tabs, and newlines), whether multiple or single, are treated alike. (Of course, those inside quotation marks that form part of a string do not count.)

Therefore, you can freely use any coding style (except that inline comments, string literals, and preprocessing directives must be on a single line), for example:

#include <iostream>

 int 

    main(){
int/**/x, y;  std::cin
>> x >>y;
                std::cout <<
          y  <<std::endl   
     << x
          
          ;
    
    return       0;     }

Of course, doing this is not recommended.

A coding style that is also widely used but differs from the style required by OI Wiki:

#include <iostream>

int main()
{
    int x, y;

    std::cin >> x >> y;
    std::cout << y << std::endl << x;

    return 0;
}

The #define Command

#define is a preprocessing directive used to define macros; it is essentially text replacement. For example:

#include <iostream>
#define n 233

// n is not a variable; the compiler replaces all n text in the code with 233, but n as part of an identifier
// is not replaced, so fn is not replaced with f233, and neither is n inside a string

int main() {
  std::cout << n;  // Output 233
  return 0;
}
What is an identifier?

An identifier is a group of characters that can be used as a variable name. For example, abcd and abc1 are valid identifiers, while 1a and c+b are not valid identifiers.

An identifier begins with an English letter or an underscore and may contain only English letters, underscores, and digits afterward. Note that keywords (such as int, for, and if) cannot be used as identifiers.

What is a preprocessing directive?

A preprocessing directive is a command accepted by the preprocessor and used for preliminary text transformations on code, such as file inclusion with #include and macro processing with #define. For GCC, the output of the preprocessing stage is not retained as an .i file by default. The -E option can be used to retain the output file.

Macros can take parameters, and parameterized macros can be used like functions:

#include <iostream>
#define sum(x, y) ((x) + (y))
#define square(x) ((x) * (x))

int main() {
  std::cout << sum(1, 2) << ' ' << 2 * sum(3, 5) << std::endl;  // Output 3 16
}

However, parameterized macros differ from functions. Since macros are text replacement, they can cause many problems. For example:

#include <iostream>
#define sum(x, y) x + y
// This should be #define sum(x, y) ((x) + (y))
#define square(x) ((x) * (x))

int main() {
  std::cout << sum(1, 2) << ' ' << 2 * sum(3, 5) << std::endl;
  // The output is 3 11 because #define is text replacement, and the following statement is replaced with 2 * 3 + 5
  int i = 1;
  std::cout << square(++i) << ' ' << i;
  // The output is undefined because ++i is executed twice
  // Modifying the same variable multiple times in one statement is undefined behavior (with exceptions)
}

Using #define is risky (because the scope of #define is the entire program, it may cause text to be replaced unintentionally, so #undef should be used to cancel definitions in time), so it should be used with caution. The more recommended approach is to declare constants with the const qualifier and use functions instead of macros.

However, in OI, #define still has its uses (the following two are not recommended because they reduce code standardization):

  1. #define int long long+signed main(). Usually used to avoid errors caused by forgetting to enable long long, or to rule out the possibility of errors caused by forgetting to enable long long during debugging. (It may also increase constants and even cause TLE, or cause MLE because of excessive memory usage.)
  2. #define For(i, l, r) for (int i = (l); i <= (r); ++i), #define pb push_back, and #define mid ((l + r) / 2), used to shorten code.

However, #define also has advantages. For example, combined with preprocessing directives such as #ifdef, it can have remarkable effects:

#ifdef LINUX
// code for linux
#else
// code for other OS
#endif

The compiled code can be controlled with -DLINUX without modifying the source file. This has another advantage: an executable compiled with -DLINUX does not contain code for other operating systems, because that code has already been deleted during preprocessing.

#define can also use the # and ## operators, which greatly facilitate debugging.

This content comes from OI Wiki: C++ Syntax Basics. See the original for authors and revision history. AIOJ has adapted the formatting, in-site links, and resource paths.

Content is shared under CC BY-SA 4.0 and SATA license; additional terms are governed by the original notice. Thanks to the OI Wiki authors and contributors; per the SATA terms, please visit the OI Wiki repository and star it to show your support.