C++ con la línea de comandos
Conceptos básicos de la línea de comandos
| Fuente | Recurso | Notas |
|---|---|---|
| CPH | 1.1 - C++ Code Template | cómo se ve compilar un programa simple |
Linux
| Fuente | Recurso | Notas |
|---|---|---|
| William Shotts | The Linux Command Line | |
| Ubuntu.com | The command line for beginners | Sirve para Linux, Mac y todas las terminales Unix |
Mac
Debería ser casi igual que Linux …
Abrir la aplicación Terminal y familiarizarse con algunos comandos
básicos. Actualizar a zsh
si todavía no se hizo.
| Fuente | Recurso | Notas |
|---|---|---|
| Jim Hoskins | Intro to OS X Command Line | |
| Rahul Saigal | Mac Terminal Cheat Sheet | atajos de teclado / comandos de terminal |
| Armin Briegel | Moving to zsh |
Windows
| Fuente | Recurso | Notas |
|---|---|---|
| Princeton | Windows Command Prompt in 15 Minutes | Java |
| ComputerHope | Windows Command Line |
Instalar g++
USACO (y la mayoría de
los contests)
usa el g++ de GCC
para
compilar y ejecutar el código. Se necesita g++ en concreto para usar el
archivo de cabecera #include <bits/stdc++.h>; véase
Ejecutar código en local
para
detalles.
En Linux
GCC suele venir preinstalado en la mayoría de las distros de Linux. Se puede comprobar si está instalado con
whereis g++Si no está preinstalado, probablemente se pueda instalar con el gestor de paquetes de la distro.
En Mac
-
Instalar las herramientas de línea de comandos de Xcode.
xcode-select --installSi se instalaron antes, puede hacer falta actualizarlas:
softwareupdate --list # list updates softwareupdate -i -a # installs all updatesDespués de este paso,
clangdebería estar instalado (probarclang --versionen Terminal). -
Instalar Homebrew .
-
Instalar
gcccon Homebrew.brew install gccSegún esto si
brewparece no terminar por un buen rato, entoncesbrew install gcc --force-bottleprobablemente alcanza.
-
Se debería poder compilar con
g++-#, donde # es el número de versión (p. ej. 10). Ejecutar el siguiente comandog++-10 --versiondebería mostrar algo como esto:
g++-10 (Homebrew GCC 10.2.0_2) 10.2.0 Copyright (C) 2020 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -
Si se quiere poder compilar solo con
g++, ¡escribir un alias de shell! Poner las siguientes líneas en el archivo rc del shell (~/.bashrcsi se usabash, y~/.zshrcsi se usazsh).alias g++=g++-10Una vez hecho eso,
g++ --versiondebería imprimir lo mismo queg++-10 --version.Nota: evitar sobrescribir el
g++del sistema con un symlink o hard-link, porque casi seguro va a causar problemas. No preocuparse si no se sabe qué significan esos términos.
En Windows
Más simple: Mingw-w64 (Minimalist GNU for Windows)
| Fuente | Recurso | Notas |
|---|---|---|
| Microsoft | MinGW with VS Code | Configurar MinGW con VS Code |
| Jetbrains | Configuring CLion on Windows | Configurar MinGW con CLion |
Más difícil: Windows Subsystem for Linux (WSL)
Si ya se está acostumbrado a la línea de comandos de Linux, esta puede ser la mejor opción.
Windows Subsystem for Linux, conocido como WSL, corre el kernel de Linux (o una capa de emulación, según la versión) dentro de la instalación de Windows. Esto permite usar binarios de Linux sin necesitar Linux como sistema operativo principal.
Mucha gente usa WSL (como Anthony), pero puede ser difícil de configurar bien.
| Fuente | Recurso | Notas |
|---|---|---|
| Microsoft | VSCode - GCC on WSL | difícil para principiantes |
Si se quiere programar en (neo)vim, se puede instalar WSL y programar a través de bash de WSL.
Para instalar las herramientas necesarias después de configurar WSL, se pueden ejecutar los siguientes comandos.
En distros basadas en Debian como Ubuntu:
sudo apt-get install build-essentialEn distros basadas en Arch como Arch Linux:
sudo pacman -Sy base-develHay muchos tutoriales sobre cómo estilizar WSL y hacerlo más cómodo. El primer paso es usar una terminal decente y no la predeterminada que provee Windows. Una opción fácil de usar es Windows Terminal, que se encuentra en el Microsoft Store .
| Fuente | Recurso | Notas |
|---|---|---|
| Set Up and Customize Windows Terminal | Configurar la terminal | |
| Make the command line look good | Conseguir una interfaz de línea de comandos linda |
C++ con la línea de comandos
Conceptos básicos de compilar y ejecutar
Considérese un programa simple como el siguiente, que guardaremos en
name.cpp.
#include <iostream>
using namespace std;
int main() {
int x;
cin >> x;
cout << "FOUND " << x << "\n";
}No es difícil
compilar y ejecutar un programa de C++ .
Primero, abrir Powershell en Windows, Terminal en Mac, o la terminal de
la distro en Linux. Se puede compilar name.cpp en un ejecutable
llamado name con el siguiente comando:
g++ name.cpp -o nameLuego se puede ejecutar el programa:
./nameSi se escribe algún entero y se presiona enter, el programa debería producir salida. Se pueden escribir ambos comandos en una sola línea:
g++ name.cpp -o name && ./nameNótese que && asegura que ./name solo se ejecute si
g++ name.cpp -o name termina con éxito.
Redirigir entrada y salida
Si se quiere leer la entrada estándar de inp.txt, usar lo siguiente:
./name < inp.txtSi se quiere escribir la salida estándar en out.txt, usar lo
siguiente:
./name > out.txtTambién se pueden usar juntos, como se muestra abajo:
./name < inp.txt > out.txtVéase Entrada y salida para cómo hacer E/S por archivos dentro del programa.
Opciones del compilador (flags)
Usar
flags del compilador
para cambiar cómo GCC compila el código. Normalmente usamos algo como
lo siguiente en lugar de g++ name.cpp -o name:
g++ -std=c++17 -O2 name.cpp -o name -Wall-O2le dice ag++que compile el código para que corra más rápido, a costa de aumentar el tiempo de compilación (véase aquí ).-std=c++17permite usar funcionalidades que se agregaron a C++ en 2017. USACO pasó recientemente de C++11 a C++17.-Wallrevisa el programa en busca de errores comunes. Véase Depuración para más información.
Siempre se debería compilar con estos flags.
Agregar atajos (Mac)
Reescribir los flags de arriba puede volverse tedioso. Conviene definir atajos para no tener que escribirlos cada vez.
| Fuente | Recurso | Notas |
|---|---|---|
| Jonathan Suh | Aliases in Terminal | |
| SO | What should / shouldn't go in .zshenv, .zshrc, ... |
Primero, crear el .zshrc si todavía no existe.
touch ~/.zshrcAbrir el .zshrc con un editor de texto.
open ~/.zshrco algún editor de texto (p. ej. Sublime Text con subl).
subl ~/.zshrcSe pueden agregar aliases y funciones aquí, como las siguientes para compilar y ejecutar C++ en Mac.
co() { g++ -std=c++17 -O2 -o "${1%.*}" $1 -Wall; }
run() { co $1 && ./${1%.*} & fg; }Ahora se puede compilar y ejecutar name.cpp fácilmente desde la línea
de comandos con
co name.cpp && ./name o run name.cpp. Nótese que todas las
apariciones de $1 en la función se reemplazan por name.cpp, mientras
que ${1%.*} quita la extensión de $1 para producir name.
¿Para qué sirve & fg?
| Fuente | Recurso | Notas |
|---|---|---|
| SO | Displaying or redirecting a shell's job control messages |
Sea prog.cpp el siguiente archivo:
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> v;
cout << v[-1];
}Según el recurso de arriba, el & fg es necesario para que zsh en
Mac muestre mensajes de crash (como segmentation fault). Por ejemplo,
considérese ejecutar el primer prog.cpp de arriba con run prog.cpp.
Si se quita & fg del comando run de arriba, la terminal no muestra
mensaje alguno. Dejarlo produce lo siguiente (ignorar las dos primeras
líneas):
[2] 30594
[2] - running ./${1%.*}
zsh: segmentation fault ./${1%.*}Medir tiempo y uso de memoria (Mac)
| Fuente | Recurso | Notas |
|---|---|---|
| CF | How to Find Total Memory Consumption of C++ Program | para Linux |
| SO | time -v on Mac | usar gtime |
Por ejemplo, supongamos que prog.cpp consiste en lo siguiente:
#include <bits/stdc++.h>
using namespace std;
const int BIG = 1e7;
int a[BIG];
int main() {
int sum = 0;
for (int i = 0; i < BIG; ++i) sum += a[i];
cout << sum;
}Entonces co prog.cpp && gtime -v ./prog da lo siguiente:
Command being timed: "./prog"
User time (seconds): 0.01
System time (seconds): 0.01
Percent of CPU this job got: 11%
Elapsed (wall clock) time (h:mm:ss or m:ss): 0:00.22
Average shared text size (kbytes): 0
Average unshared data size (kbytes): 0
Average stack size (kbytes): 0
Average total size (kbytes): 0
Maximum resident set size (kbytes): 40216
Average resident set size (kbytes): 0
Major (requiring I/O) page faults: 91
Minor (reclaiming a frame) page faults: 10088
Voluntary context switches: 3
Involuntary context switches: 38
Swaps: 0
File system inputs: 0
File system outputs: 0
Socket messages sent: 0
Socket messages received: 0
Signals delivered: 0
Page size (bytes): 4096
Exit status: 0Nótese que enteros requieren kilobytes de memoria, que está cerca de en la salida de arriba, como se esperaba.
Ajustar el tamaño de pila (Mac)
Sea A.cpp el siguiente programa:
#include <iostream>
using namespace std;
int res(int x) {
if (x == 200000) return x;
return res(x + 1);
}
int main() { cout << res(0) << "\n"; }Si se compila y ejecuta con g++ A.cpp -o A && ./A, imprime 200000.
Sin embargo, cambiar 200000 a 300000 da un segmentation fault. De
forma similar,
#include <iostream>
using namespace std;
int main() {
int arr[2000000];
cout << arr[0] << "\n";
}corre, pero cambiar 2000000 a 3000000 también da un segmentation
fault. Esto es porque el tamaño de pila en Mac parece estar limitado
a 8 megabytes por defecto.
| Fuente | Recurso | Notas |
|---|---|---|
| Wikipedia | Stack overflow | explicación del problema |
Nótese que USACO no tiene límite de tamaño de pila, aparte del límite habitual de 256 MB de memoria. Por eso, código que crashea en local por un error de desbordamiento de pila puede pasar en los servidores de USACO. Para hacer que el código corra en local, usar uno de los métodos de abajo.
Método 1
| Fuente | Recurso | Notas |
|---|---|---|
| SO | Change Stack Size on Mac OS? |
ulimit -s 65532 aumenta el tamaño de pila a unos 64 MB. Por
desgracia, no funciona para números más altos.
Método 2
| Fuente | Recurso | Notas |
|---|---|---|
| CF | Terminal Command on Mac | la gente se queja de FHC todos los años |
Para evitar esto, se puede pasar una
opción del linker .
Según el manual de
ld
(escribir man ld en Terminal), la opción -stack_size size hace lo
siguiente:
Specifies the maximum stack size for the main thread in a program. Without this option a program has a 8MB stack. The argument size is a hexadecimal number with an optional leading 0x. The size should be a multiple of the architecture’s page size (4KB or 16KB).
Así, incluir -Wl,-stack_size,0x10000000 como parte del comando de
compilación fija el tamaño máximo de pila en bytes
megabytes, que suele alcanzar. Sin embargo, ejecutar el
primer programa de arriba con 200000 reemplazado por 1e7 todavía da
error. En ese caso, se puede aumentar más el tamaño máximo de pila
(p. ej. cambiar 0x10000000 a 0xF0000000).
En Windows, agregar -Wl,--stack,268435456 como parte de los flags de
compilación debería funcionar. El 268435456 corresponde a
268435456 bytes, o 256 megabytes. Si se usa Windows PowerShell, hay
que envolverlo entre comillas (así: "-Wl,--stack,268435456"), porque
las comas se consideran caracteres especiales.