Aula 1
- C
- hello, world
- Compiladores
- String
- Blocos do Scratch em C
- Tipos, formatos e operadores
- Mais exemplos
- Memória, imprecisão e estouro
C
-
Hoje vamos aprender uma nova linguagem, C: uma linguagem de programação que tem todos os recursos do Scratch e muito mais, mas talvez um pouco menos amigável pois é totalmente em texto:
#include <stdio.h> int main(void) { printf("hello, world\n"); }- Apesar de as palavras serem novas, as ideias são as mesmas dos blocos "Quando a bandeira verde é clicada" e "diga (hello, world)" do Scratch:

- Apesar de as palavras serem novas, as ideias são as mesmas dos blocos "Quando a bandeira verde é clicada" e "diga (hello, world)" do Scratch:
-
Apesar de parecer complicado, não se esqueça que 2/3 dos alunos do CS50 nunca fizeram ciência da computação antes, então não se assuste! E embora no início, para pegar emprestada uma frase do MIT, tentar absorver todos esses novos conceitos possa parecer como beber de uma mangueira de incêndio, tenha certeza de que até o final do semestre estaremos capacitados e experientes na aprendizagem e aplicação desses conceitos.
- Podemos comparar vários dos construtos em C com blocos que já vimos e usamos no Scratch. A sintaxe é muito menos importante que os princípios, que já nos foram apresentados.
olá, mundo
-
O bloco “quando a bandeira verde for clicada” no Scratch inicia o programa principal; clicar na bandeira verde faz com que o conjunto direito de blocos abaixo comece. Em C, a primeira linha para o mesmo é
int main(void), sobre a qual aprenderemos mais nas próximas semanas, seguida por uma chave aberta{, e uma chave fechada}, envolvendo tudo o que deve estar em nosso programa.int main(void) { } -
O bloco “dizer (olá, mundo)” é uma função e mapeia para
printf("olá, mundo");. Em C, a função para imprimir algo na tela éprintf, ondefsignifica "format", o que significa que podemos formatar a string impressa de diferentes maneiras. Então, usamos parênteses para passar o que queremos imprimir. Temos que usar aspas duplas para circundar nosso texto para que seja entendido como texto, e finalmente, adicionamos um ponto-e-vírgula;para finalizar essa linha de código. - Para que nosso programa funcione, também precisamos de outra linha no topo, uma linha de cabeçalho
#include <stdio.h>que define a funçãoprintfque queremos usar. Em algum lugar há um arquivo em nosso computador,stdio.h, que inclui o código que nos permite acessar a funçãoprintf, e a linha#includediz ao computador para incluir esse arquivo com nosso programa. - Para escrever nosso primeiro programa em Scratch, abrimos o site do Scratch. Da mesma forma, usaremos o CS50 Sandbox para começar a escrever e executar o código da mesma maneira. O CS50 Sandbox é um ambiente virtual baseado em nuvem com as bibliotecas e ferramentas já instaladas para escrever programas em várias linguagens. No topo, há um editor de código simples, onde podemos digitar texto. Abaixo, temos uma janela de terminal, na qual podemos digitar comandos:

- Digitaremos nosso código do início na parte superior, depois de usar o sinal
+para criar um novo arquivo chamadohello.c:

- Finalizamos o arquivo do nosso programa com
.cpor convenção, para indicar que ele foi concebido como um programa C. Observe que nosso código é colorido, para que certas coisas fiquem mais visíveis.
Compiladores
- Uma vez que salvamos o código que escrevemos, que é chamado de código-fonte, precisamos convertê-lo em código de máquina, instruções binárias que o computador entende diretamente.
- Usamos um programa chamado compilador para compilar nosso código-fonte em código de máquina.
- Para fazer isso, usamos o painel Terminal, que tem um prompt de comando. O
$à esquerda é um prompt, após o qual podemos digitar comandos. - Digitamos
clang hello.c(ondeclangsignifica "linguagens C", um compilador escrito por um grupo de pessoas). Mas antes de pressionarmos Enter, clicamos no ícone da pasta no canto superior esquerdo do CS50 Sandbox. Vemos nosso arquivo,hello.c. Então, pressionamos Enter na janela do terminal e vemos que agora temos outro arquivo chamadoa.out(abreviação de "saída de montagem"). Dentro desse arquivo está o código do nosso programa, em binário. Agora, podemos digitar./a.outno prompt do terminal para executar o programaa.outem nossa pasta atual. Acabamos de escrever, compilar e executar nosso primeiro programa!
String
-
Mas depois de executar nosso programa, vemos
hello, world$, com o novo prompt na mesma linha que nossa saída. Acontece que precisamos especificar precisamente que precisamos de uma nova linha após o nosso programa, por isso podemos atualizar nosso código para incluir um caractere de nova linha especial,\n:#include <stdio.h> int main(void) { printf("hello, world\n"); }- Agora precisamos nos lembrar de recompilar nosso programa com
clang hello.cantes de executar esta nova versão.
- Agora precisamos nos lembrar de recompilar nosso programa com
-
A linha 2 de nosso programa está intencionalmente em branco, pois queremos iniciar uma nova seção de código, assim como iniciar novos parágrafos em ensaios. Não é estritamente necessário para que nosso programa execute corretamente, mas ajuda os humanos a ler programas mais longos com mais facilidade.
- Podemos alterar o nome de nosso programa de
a.outpara outra coisa também. Podemos passar argumentos de linha de comando ou opções adicionais para programas no terminal, dependendo do que o programa foi escrito para entender. Por exemplo, podemos digitarclang -o hello hello.c, e-o helloestá dizendo ao programaclangpara salvar a saída compilada como apenashello. Então, possiamo executar apenas./hello. -
Em nosso prompt de comando, podemos executar outros comandos, como
ls(lista), que mostra os arquivos em nossa pasta atual:$ ls a.out* hello* hello.c- O asterisco,
*, indica que esses arquivos são executáveis ou que podem ser executados por nosso computador.
- O asterisco,
-
Podemos usar o comando
rm(remover) para excluir um arquivo:$ rm a.out rm: remove regular file 'a.out'?- Podemos digitar
youyespara confirmar e usarlsnovamente para ver que ele realmente se foi para sempre.
- Podemos digitar
-
Agora, vamos tentar obter a entrada do usuário, como fizemos no Scratch quando queríamos dizer "ola, David":

string answer = get_string("What's your name?\n"); printf("hello, %s\n", answer);- Primeiro, precisamos de uma string, ou parte do texto (especificamente, zero ou mais caracteres em uma sequência entre aspas duplas, como
"","ba", ou “bananas”), que podemos pedir ao usuário, com a funçãoget_string. Passamos o prompt, ou o que queremos perguntar ao usuário, para a função com"What is your name?\n"entre parênteses. À esquerda, queremos criar uma variável,answer, cujo valor será o que o usuário insere. (O sinal de igual=está definindo o valor da direita para a esquerda.) Finalmente, o tipo de variável que queremos éstring, então especificamos isso à esquerda deanswer. - Em seguida, dentro da função
printf, queremos o valor deanswerno que imprimimos de volta. Usamos um espaço reservado para nossa variável de string,%s, dentro da frase que queremos imprimir, como"hello, %s\n", e então damosprintfoutro argumento, ou opção, para dizer que queremos que a variávelanswerseja substituída.
- Primeiro, precisamos de uma string, ou parte do texto (especificamente, zero ou mais caracteres em uma sequência entre aspas duplas, como
-
Se cometermos um erro, como escrever
printf("hello, world"\n);com o\nfora das aspas duplas de nossa string, veremos erros de nosso compilador:$ clang -o hello hello.c hello.c:5:26: error: expected ')' printf("hello, world"\n); ^ hello.c:5:11: note: to match this '(' printf("hello, world"\n); ^ 1 error generated.- A primeira linha do erro nos diz para olhar para
hello.c, linha 5, coluna 26, onde o compilador esperava um parêntese de fechamento, em vez de uma barra invertida.
- A primeira linha do erro nos diz para olhar para
-
Para simplificar as coisas (pelo menos no começo), incluiremos uma biblioteca, ou conjunto de códigos, do CS50. A biblioteca nos fornece o tipo de variável
string, a funçãoget_stringe muito mais. Só temos que escrever uma linha no topo paraincluiro arquivocs50.h:#include <cs50.h> #include <stdio.h> int main(void) { string name = get_string("What's your name?\n"); printf("hello, name\n"); } -
Então vamos criar um novo arquivo,
string.c, com este código:#include <stdio.h> int main(void) { string name = get_string("What's your name?\n"); printf("hello, %s\n", name); } -
Agora, se tentarmos compilar esse código, obteremos muitas linhas de erro. Às vezes, um erro significa que o compilador começa a interpretar o código correto incorretamente, gerando mais erros do que realmente existem. Então, começamos com nosso primeiro erro:
$ clang -o string string.c string.c:5:5: error: use of undeclared identifier 'string'; did you mean 'stdin'? string name = get_string("What's your name?\n"); ^~~~~~ stdin /usr/include/stdio.h:135:25: note: 'stdin' declared here extern struct _IO_FILE *stdin; /* Standard input stream. */- Não queríamos dizer
stdin(“entrada padrão”) em vez destring, então essa mensagem de erro não foi útil. Na verdade, precisamos importar outro arquivo que define o tipostring(na verdade, uma roda de treinamento do CS50, como descobriremos nas próximas semanas).
- Não queríamos dizer
-
Então podemos incluir outro arquivo,
cs50.h, que também inclui a funçãoget_string, entre outras.#include <cs50.h> #include <stdio.h> int main(void) { string name = get_string("What's your name?\n"); printf("hello, %s\n", name); } -
Agora, quando tentarmos compilar nosso programa, teremos apenas um erro:
$ clang -o string string.c /tmp/string-aca94d.o: In function `main': string.c:(.text+0x19): undefined reference to `get_string' clang-7: error: linker command failed with exit code 1 (use -v to see invocation)- Acontece que também temos que dizer ao nosso compilador para adicionar nosso arquivo de biblioteca CS50 especial, com
clang -o string string.c -lcs50, com-lpara “link”.
- Acontece que também temos que dizer ao nosso compilador para adicionar nosso arquivo de biblioteca CS50 especial, com
-
Podemos até mesmo abstrair isso e digitar
make string. Vemos que, por padrão no CS50 Sandbox,makeusaclangpara compilar nosso código destring.cparastring, com todos os argumentos necessários ou sinalizadores passados.
Blocos do Scratch em C
-
O bloco “definir [contador] para (0)” está criando uma variável e, em C, escreveríamos
int contador = 0;, ondeintespecifica que o tipo da nossa variável é um número inteiro.
-
“alterar [contador] por (1)” é
contador = contador + 1;em C. (Em C,=não é como um sinal de igual em uma equação, onde estamos dizendo quecontadoré igual acontador + 1. Em vez disso,=é um operador de atribuição que significa “copiar o valor à direita no valor à esquerda”.) E observe que não precisamos mais dizerint, pois presume-se que já especificamos anteriormente quecontadoré umint, com algum valor existente. Também podemos dizercontador += 1;oucontador++;, ambos os quais são “sintaxe simplificada” ou atalhos que têm o mesmo efeito com menos caracteres para digitar.
-
Uma condição seria mapeada para:

c
if (x < y)
{
printf("x é menor que y\n");
}
-
Observe que, em C, usamos
{e}(bem como indentação) para indicar como as linhas de código devem ser aninhadas. -
Também podemos ter condições se-senão:

c
if (x < y)
{
printf("x é menor que y\n");
}
else
{
printf("x não é menor que y\n");
}
-
Observe que as linhas de código que não são, elas mesmas, uma ação (
if...e as chaves) não terminam em ponto e vírgula. -
E até mesmo
senão se:
c
if (x < y)
{
printf("x é menor que y\n");
}
else if (x > y)
{
printf("x é maior que y\n");
}
else if (x == y)
{
printf("x é igual a y\n");
}
- Observe que, para comparar dois valores em C, usamos
==, dois sinais de igual. -
E, logicamente, não precisamos de
if (x == y)na condição final, pois esse é o único caso restante, e podemos simplesmente dizerelse. -
Os loops podem ser escritos como o seguinte:

c
while (true)
{
printf("olá, mundo\n");
}
-
A palavra-chave
whiletambém requer uma condição, então usamostruecomo a expressão booleana para garantir que nosso loop seja executado para sempre. Nosso programa verificará se a expressão é avaliada comotrue(o que sempre será o caso) e, em seguida, executará as linhas dentro das chaves. Em seguida, repetirá isso até que a expressão não seja mais verdadeira (o que não mudará neste caso). -
Poderíamos fazer algo um certo número de vezes com
while:
c
int i = 0;
while (i < 50)
{
printf("olá, mundo\n");
i++;
}
- Criamos uma variável,
i, e a definimos como 0. Então, enquantoi < 50, executamos algumas linhas de código e adicionamos 1 aiapós cada execução. -
As chaves em torno das duas linhas dentro do loop
whileindicam que essas linhas serão repetidas e podemos adicionar linhas adicionais ao nosso programa depois, se quisermos. -
Para fazer a mesma repetição, mais comumente podemos usar a palavra-chave
for:
c
for (int i = 0; i < 50; i++)
{
printf("olá, mundo\n");
}
- Novamente, primeiro criamos uma variável chamada
ie a definimos como 0. Então, verificamos sei < 50toda vez que alcançamos o início do loop, antes de executar qualquer parte do código dentro dele. Se essa expressão for verdadeira, então executamos o código interno. Finalmente, depois de executar o código interno, usamosi++para adicionar um aie o loop se repete.
Tipos, formatos, operadores
- Há outros tipos que podemos usar para as nossas variáveis
bool, uma expressão booleana detrueoufalsechar, um único caractere comoaou2double, um valor de ponto flutuante com ainda mais dígitosfloat, um valor de ponto flutuante, ou número real com um valor decimalint, inteiros até um determinado tamanho, ou número de bitslong, inteiros com mais bits, para que possam contar mais altostring, uma cadeia de caracteres
- E a biblioteca CS50 tem funções correspondentes para obter entrada de vários tipos:
get_charget_doubleget_floatget_intget_longget_string
- Para
printf, também, há diferentes espaços reservados para cada tipo:%cpara caracteres%fpara flutuantes, duplos%ipara ints%lipara longos%spara strings
- E existem alguns operadores matemáticos que podemos usar:
+para adição-para subtração*para multiplicação/para divisão%para resto
Mais exemplos
- Para cada um desses exemplos, você pode clicar nos links do sandbox para executar e editar suas próprias cópias deles.
-
Em
int.c, obtemos e imprimimos um inteiro:#include <cs50.h> #include <stdio.h> int main(void) { int idade = get_int("Qual é a sua idade?\n"); int dias = idade * 365; printf("Você tem pelo menos %i dias de idade.\n", dias); }- Observe que usamos
%ipara imprimir um inteiro. - Agora podemos executar
make inte executar nosso programa com./int. -
Podemos combinar linhas e remover a variável
diascom:int idade = get_int("Qual é a sua idade?\n"); printf("Você tem pelo menos %i dias de idade.\n", idade * 365); -
Ou mesmo combinar tudo em uma linha:
printf("Você tem pelo menos %i dias de idade.\n", get_int("Qual é a sua idade?\n") * 365); -
No entanto, quando uma linha fica muito longa ou complicada, pode ser melhor manter duas ou até três linhas para facilitar a leitura.
- Observe que usamos
-
Em
float.c, podemos obter números decimais (chamados de valores de ponto flutuante em computadores, porque o ponto decimal pode "flutuar" entre os dígitos, dependendo do número):#include <cs50.h> #include <stdio.h> int main(void) { float preço = get_float("Qual é o preço?\n"); printf("Seu total é %f.\n", preço * 1.0625); }- Agora, se compilarmos e executarmos nosso programa, veremos um preço impresso com impostos.
- Podemos especificar o número de dígitos impressos após a vírgula decimal com um espaço reservado como
%.2fpara dois dígitos após a vírgula decimal.
-
Com
parity.c, podemos verificar se um número é par ou ímpar:#include <cs50.h> #include <stdio.h> int main(void) { int n = get_int("n: "); if (n % 2 == 0) { printf("par\n"); } else { printf("ímpar\n"); } }- Com o operador
%(módulo), podemos obter o restante denapós sua divisão por 2. Se o restante for 0, sabemos quené par. Caso contrário, sabemos quené ímpar. - Funções como
get_intda biblioteca CS50 fazem a verificação de erros, onde apenas as entradas do usuário que correspondem ao tipo desejado são aceitas.
- Com o operador
-
Em
conditions.c, transformamos os trechos de condição anteriores em um programa:// Condições e operadores relacionais #include <cs50.h> #include <stdio.h> int main(void) { // Solicita ao usuário x int x = get_int("x: "); // Solicita ao usuário y int y = get_int("y: "); // Compara x e y if (x < y) { printf("x é menor que y\n"); } else if (x > y) { printf("x é maior que y\n"); } else { printf("x é igual a y\n"); } }- As linhas que começam com
//são comentários, ou nota para humanos que o compilador irá ignorar. - Para David compilar e executar este programa em seu sandbox, ele primeiro precisava executar
cd src1no terminal. Isso altera o diretório ou pasta para aquele no qual ele salvou todos os arquivos de origem da aula. Então, ele poderia executarmake conditionse./conditions. Compwd, ele pode ver que está em uma pastasrc1(dentro de outras pastas). Ecdpor si só, sem argumentos, nos levará de volta para nossa pasta padrão no sandbox.
- As linhas que começam com
-
Em
agree.c, podemos pedir ao usuário para confirmar ou negar algo:// Operadores lógicos #include <cs50.h> #include <stdio.h> int main(void) { // Solicita ao usuário que concorde char c = get_char("Você concorda?\n"); // Verifica se concordou if (c == 'S' || c == 's') { printf("Concordo.\n"); } else if (c == 'N' || c == 'n') { printf("Não concordo.\n"); } }- Usamos duas barras verticais,
||, para indicar um "ou" lógico, seja qual for a expressão que pode ser verdadeira para que a condição seja seguida. - E se nenhuma das expressões for verdadeira, nada acontecerá, pois nosso programa não tem um loop.
- Usamos duas barras verticais,
-
Vamos implementar o programa de tosse da semana 0:
#include <stdio.h> int main(void) { printf("tosse\n"); printf("tosse\n"); printf("tosse\n"); } -
Podemos usar um loop
for:#include <stdio.h> int main(void) { for (int i = 0; i < 3; i++) { printf("tosse\n"); } }- Por convenção, os programadores tendem a começar a contar em 0 e, portanto,
iterá os valores de0,1e2antes de parar, para um total de três iterações. Também poderíamos escreverfor (int i = 1; i <= 3; i++)para o mesmo efeito final.
- Por convenção, os programadores tendem a começar a contar em 0 e, portanto,
-
Podemos mover a linha
printfpara sua própria função:#include <stdio.h> void tosse(void); int main(void) { for (int i = 0; i < 3; i++) { tosse(); } } void tosse(void) { printf("tosse\n"); }- Declaramos uma nova função com
void tosse(void);antes que nossa funçãomaina chame. O compilador C lê nosso código de cima para baixo, então precisamos dizer a ele que a funçãotosseexiste, antes de usá-la. Então, após nossa funçãomain, podemos implementar a funçãotosse. Dessa forma, o compilador sabe que a função existe e podemos manter nossa funçãomainperto do topo. - E nossa função
tossenão recebe nenhuma entrada, então temostosse(void).
- Declaramos uma nova função com
-
Podemos abstrair a
tosseainda mais:#include <stdio.h> void tosse(int n); int main(void) { tosse(3); } void tosse(int n) { for (int i = 0; i < n; i++) { printf("tosse\n"); } }- Agora, quando queremos imprimir "tosse" qualquer número de vezes, podemos simplesmente chamar a mesma função. Observe que, com
void tosse(int n), indicamos que a funçãotosserecebe como entrada umint, que chamamos den. E dentro detosse, usamosnem nosso loopforpara imprimir "tosse" o número correto de vezes.
- Agora, quando queremos imprimir "tosse" qualquer número de vezes, podemos simplesmente chamar a mesma função. Observe que, com
-
Vamos dar uma olhada em
positivo.c:#include <cs50.h> #include <stdio.h> int obter_ inteiro_positivo(void); int main(void) { int i = obter_inteiro_positivo(); printf("%i\n", i); } // Solicita ao usuário um inteiro positivo int obter_ inteiro_positivo(void) { int n; faça { n = get_int("%s", "Inteiro positivo: "); } Enquanto (n < 1); Retorno n; }- A biblioteca CS50 não tem uma função
obter_inteiro_positivo, mas podemos escrever uma nós mesmos. Nossa funçãoint obter_inteiro_positivo(void)solicitará ao usuário uminte retornará esseint, que nossa funçãomainarmazena comoi. Emobter_inteiro_positivo, inicializamos uma variável,int n, sem atribuir um valor a ela ainda. Então, temos uma nova construção,faça ... enquanto, que faz algo primeiro, então verifica uma condição e repete até que a condição deixe de ser verdadeira. - Assim que o loop terminar porque temos um
nque não é "< 1", podemos retorná-lo com a palavra-chavereturn. E de volta à nossa funçãomain, podemos definirint ipara esse valor.
- A biblioteca CS50 não tem uma função
Telas
-
Podemos desejar um programa que imprima parte de uma tela de um videogame, como Super Mario Bros. Em
mario0.c, temos:// Imprime uma linha de 4 pontos de interrogação #include <stdio.h> int main(void) { printf("????\n"); } -
Podemos pedir para o usuário um número de pontos de interrogação e, em seguida, imprimi-los, com
mario2.c:#include <cs50.h> #include <stdio.h> int main(void) { int n; do { n = get_int("Largura: "); } while (n < 1); for (int i = 0; i < n; i++) { printf("?"); } printf("\n"); } -
E podemos imprimir um conjunto bidimensional de blocos com
mario8.c:// Imprime uma grade nxn de tijolos com um loop #include <cs50.h> #include <stdio.h> int main(void) { int n; do { n = get_int("Tamanho: "); } while (n < 1); for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { printf("#"); } printf("\n"); } }- Observe que temos dois loops aninhados, onde o loop externo usa
ipara fazer tudo dentro das vezesne o loop interno usaj, uma variável diferente, para fazer algonvezes para cada uma daquelas vezes. Em outras palavras, o loop externo imprimen“linhas” ou linhas, e o loop interno imprimen“colunas” ou caracteres “#”, em cada linha.
- Observe que temos dois loops aninhados, onde o loop externo usa
-
Outros exemplos não abordados em aula estão disponíveis em “Código-fonte” para a Semana 1.
# Memória imprecisão e overflow
- Nosso computador possui memória em chips de hardware chamados RAM, memória de acesso aleatório. Nossos programas utilizam essa RAM para armazenar dados enquanto são executados, porém essa memória é finita. Portanto, com um número finito de bits não podemos representar todos os números possiveis (dos quais existe um número infinito). Então nosso computador tem um determinado número de bits para cada
floateinte tem de arredondar para o valor decimal mais próximo em determinado ponto. -
Com
floats.cpodemos ver o que acontece quando usamos floats:#include <cs50.h> #include <stdio.h> int main(void) { // Solicita o x ao usuário float x = get_float("x: "); // Solicita o y ao usuário float y = get_float("y: "); // Executa a divisão printf("x / y = %.50f\n", x / y); }- Com
%50f, podemos especificar o número de casas decimais exibidos. -
Hmm, agora obtemos...
x: 1 y: 10 x / y = 0.10000000149011611938476562500000000000000000000000 -
Acontece que isso se chama imprecisão de ponto flutuante, onde não temos bits suficientes para armazenar todos os valores possíveis então o computador tem de armazenar o valor mais próximo possível de 1 dividido por 10.
- Com
-
Podemos ver um problema similar em
overflow.c:#include <stdio.h> #include <unistd.h> int main(void) { for (int i = 1; ; i *= 2) { printf("%i\n", i); sleep(1); } }- No nosso laço
for, definimosicomo1e o dobramos com*= 2. (E continuaremos fazendo isso para sempre, então não há condição para verificação.) - Também usamos a função
sleepdounistd.hpara permitir que nosso programa pause sempre. -
Agora, quando executamos esse programa veremos o número crescer cada vez mais até que:
1073741824 overflow.c:6:25: runtime error: signed integer overflow: 1073741824 * 2 cannot be represented in type 'int' -2147483648 0 0 ... -
Acontece que nosso programa reconheceu que um inteiro assinado (um inteiro com um sinal positivo ou negativo) não poderia armazenar esse próximo valor e exibiu um erro. Então, uma vez que ele tentou dobrá-lo de qualquer forma,
ise tornou um número negativo e então 0. - Esse problema é chamado de overflow de inteiro, onde um inteiro pode ser somente tão grande antes que acabem os bits e ele "reinicie". Podemos imaginar adicionar um ao número 999 decimal. O último digito se torna 0, pegamos o 1 emprestado para que o próximo digito se torne 0 e obtemos 1000. Mas se tivéssemos apenas três digitos, acabaríamos com 000 pois não há lugar para o 1 final!
- No nosso laço
-
O problema da virada do milênio surgiu porque muitos programas armazenavam o ano-calendário com apenas dois digitos, como 98 para 1998 e 99 para 1999. Porém quando o ano 2000 se aproximou, os programas teriam armazenado 00, levando a confusão entre os anos 1900 e 2000.
- Um avião Boeing 787 também teve um bug onde um contador no gerador tinha overflow após um certo número de dias de operação contínua, visto que o número de segundos que havia rodado já não cabia mais naquele contador.
- Portanto, vimos alguns problemas que podem acontecer, mas agora entendemos por que e como prevení-los.
- Com o problema definido nesta semana, usaremos o CS50 Lab, construído no CS50 Sandbox, para escrever alguns programas com orientações para nos guiar.