Skip to Content

C++ con la línea de comandos

Conceptos básicos de la línea de comandos

Recursos
FuenteRecursoNotas
CPH1.1 - C++ Code Template

cómo se ve compilar un programa simple

Linux

Recursos
FuenteRecursoNotas
William ShottsThe Linux Command Line
Ubuntu.comThe 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.

Recursos
FuenteRecursoNotas
Jim HoskinsIntro to OS X Command Line
Rahul SaigalMac Terminal Cheat Sheet

atajos de teclado / comandos de terminal

Armin BriegelMoving to zsh

Windows

Recursos
FuenteRecursoNotas
PrincetonWindows Command Prompt in 15 Minutes

Java

ComputerHopeWindows 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

  1. Instalar las herramientas de línea de comandos de Xcode.

    xcode-select --install

    Si se instalaron antes, puede hacer falta actualizarlas:

    softwareupdate --list # list updates softwareupdate -i -a # installs all updates

    Después de este paso, clang debería estar instalado (probar clang --version en Terminal).

  2. Instalar Homebrew .

  3. Instalar gcc con Homebrew.

    brew install gcc

    Según esto  si brew parece no terminar por un buen rato, entonces

    brew install gcc --force-bottle

    probablemente alcanza.

  4. Se debería poder compilar con g++-#, donde # es el número de versión (p. ej. 10). Ejecutar el siguiente comando

    g++-10 --version

    deberí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.
  5. Si se quiere poder compilar solo con g++, ¡escribir un alias de shell! Poner las siguientes líneas en el archivo rc del shell (~/.bashrc si se usa bash, y ~/.zshrc si se usa zsh).

    alias g++=g++-10

    Una vez hecho eso, g++ --version debería imprimir lo mismo que g++-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)

Recursos
FuenteRecursoNotas
MicrosoftMinGW with VS Code

Configurar MinGW con VS Code

JetbrainsConfiguring 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.

Recursos
FuenteRecursoNotas
MicrosoftVSCode - 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-essential

En distros basadas en Arch como Arch Linux:

sudo pacman -Sy base-devel

Hay 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 .

Recursos
FuenteRecursoNotas
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 name

Luego se puede ejecutar el programa:

./name

Si 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 && ./name

Nó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.txt

Si se quiere escribir la salida estándar en out.txt, usar lo siguiente:

./name > out.txt

También se pueden usar juntos, como se muestra abajo:

./name < inp.txt > out.txt

Vé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
  • -O2 le dice a g++ 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++17 permite usar funcionalidades que se agregaron a C++ en 2017. USACO pasó recientemente de C++11 a C++17.
  • -Wall revisa 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.

Primero, crear el .zshrc si todavía no existe.

touch ~/.zshrc

Abrir el .zshrc con un editor de texto.

open ~/.zshrc

o algún editor de texto (p. ej. Sublime Text con subl).

subl ~/.zshrc

Se 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?

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)

Recursos
FuenteRecursoNotas
CFHow to Find Total Memory Consumption of C++ Program

para Linux

SOtime -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: 0

Nótese que 10710^7 enteros requieren 4107103400004\cdot 10^7\cdot 10^{-3}\approx 40000 kilobytes de memoria, que está cerca de 4021640216 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.

Recursos
FuenteRecursoNotas
WikipediaStack 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

Recursos
FuenteRecursoNotas
SOChange 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

Recursos
FuenteRecursoNotas
CFTerminal 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 16716^7 bytes 256\approx 256 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.