>> DAVID MALAN: Tudo bem, bem-vindo de volta.
Isto é CS50.
Este é o início da semana de sete.
Por isso, já faz um tempo, então pensei que tinha fazer um passeio turbilhão de onde nós
parou e para onde estamos indo agora.
>> Então, essa coisa aqui pode ter causou alguma angústia em primeiro lugar.
Mas espero que, você está começando a aclimatar com o que isso denota aqui -
estrela que representa um ponteiro, o qual é o que, em termos mais leigos?
Portanto, é um endereço.
>> Portanto, é o endereço de algo em memória.
E começamos a descascar as camadas um par de semanas atrás, coisas como
GetString e outras funções tais todo esse tempo foram retornando
endereços de coisas na memória, como o endereço do primeiro caractere
alguma seqüência.
>> Então, nós também introduziu valgrind, que você vai começar a usar para este problema
definido, em particular para a próxima conjunto de problemas também.
E valgrind faz o que para nós?
Ele verifica se há vazamentos de memória, e também verifica a existência de abuso de memória.
>> É possível, com alguma probabilidade, se detectar seu código vai tocar de memória
que simplesmente não deveria.
Então, não necessariamente uma fuga, mas se você ir além das fronteiras de alguns
array, e você realmente executar valgrind e induzir a que o comportamento enquanto
valgrind está sendo executado em seu programa rodando dentro dele, você vai ter
mensagens como esta - "inválido de escrever tamanho 4 ", que, lembre-se de um par de
semanas atrás significava que eu tinha acidentalmente procura de um int demasiado
além dos limites de um array.
E assim tamanho 4 significa aqui o tamanho de que int particular.
>> Então dê confiança no fato de que saída do valgrind, o formato do mesmo,
é simplesmente atroz.
É realmente difícil de ver através da bagunça pela informação interessante.
Então, o que temos feito aqui é apenas trecho alguns dos pares de mais
linhas interessantes.
Mas percebemos que 80% dos valgrind de saída vai ser um pouco de
distração.
>> Basta olhar para os padrões como estes - inválido direita, inválido ler, 40 bytes
e um certo número de blocos são definitivamente perdido, palavras-chave como essa.
E o que você espera ver alguma tipo de vestígio de que a função do
erro é realmente dentro
Neste caso, aqui, no qual a linha de meu código era aparentemente o erro?
>> 26 em um arquivo chamado memory.c, que era o exemplo que estavam brincando com
no momento.
Portanto, não é, provavelmente, em malloc.
Foi provavelmente no meu código em seu lugar.
Então, vamos ver isso de novo e novamente em pouco tempo.
>> Então scanf, esta surgiu em um algumas formas até agora.
Vimos sscanf brevemente.
Era algo que uma série de você mergulhou em sua
preparativos para o teste.
E scanf é realmente o que o CS50 biblioteca está usando por baixo da
capa por algum tempo, a fim para obter a entrada do usuário.
>> Por exemplo, se eu passar para o CS50 aparelho aqui, deixe-me abrir uma
exemplo, hoje, que é chamado de scanf-0.C E é super simples.
É apenas algumas linhas de código.
Mas ele demonstra realmente como getInt vem trabalhando todo esse tempo.
>> Neste programa aqui, na linha 16 , Repare que eu declarar um int.
Assim, não ponteiros, nada de mágico lá, apenas um int.
Em seguida, na linha 17, que solicitará ao usuário para um número, por favor.
Então, no final de 18, eu uso o scanf aqui.
E eu especifiquei, tipo como printf, que eu estou esperando Citação
unquote por cento i.
>> Assim por cento de i, é claro, denota um int.
Mas note que a segunda argumento de scanf é.
Como você descreveria o segundo argumento depois da vírgula?
O que é isso?
>> É o endereço de x.
Então, isso é útil porque fornecendo scanf com o endereço de x, o que faz
que capacitam essa função para fazer?
Não é só ir lá, mas também fazer o quê?
>> Fazer uma mudança para ela.
Porque você pode ir lá, é uma espécie de como um mapa para a localização na memória.
E assim, desde que você forneça scanf, ou qualquer função com um tal mapa, isto
função pode ir lá, e não só olhar para o valor, mas também pode
alterar esse valor, o que é útil quando a propósito na vida de scanf é
digitalizar a entrada do utilizador, especificamente a partir do teclado.
E o f denota formatado, assim como printf, o f denota uma formatado
string que você deseja imprimir.
>> Assim, em breve, essa linha 18 simplesmente diz: tente ler um int do usuário do
teclado e armazená-lo dentro de x, em qualquer endereço x acontece a viver em.
E então, finalmente, a linha 19 apenas diz: obrigado pela int, neste caso.
>> Então deixe-me ir em frente e fazer isso.
Então faça scanf 0.
Deixe me ir em frente e zoom in
Vou correr com esta pontos cortar scanf 0.
Número, por favor?
50.
Obrigado pela 50.
Por isso, é muito simples.
>> Agora, o que é que não está fazendo?
Ele não está fazendo um grupo inteiro de verificação de erros.
Por exemplo, se eu não cooperar, e eu não digitar um número, mas
em vez disso, escrever algo como "Olá", isso é apenas uma espécie de estranho.
E assim, uma das coisas que o CS50 biblioteca tem vindo a fazer para nós por algum
tempo é que reprompting e reprompting.
>> A nova tentativa frase foi retirada em cs50.c, e essa é a razão que getInt em
a biblioteca CS50 é realmente um conjunto bando de longas filas, porque nós somos
verificação de coisas estúpidas como esta.
Será que o usuário não dar nós, na verdade, um int?
Será que ele ou ela nos dar algo como uma letra alfabética?
Se assim for, queremos detectar isso e gritar com eles.
>> Mas as coisas ficam mais interessantes Neste próximo exemplo.
Se eu for para scanf-1.c, que é a única coisa que mudou fundamentalmente em
Neste próximo exemplo?
Estou usando char *, é claro, em vez de int.
>> Então, isso é interessante, porque char *, recordo, é realmente apenas o
mesma coisa que a string.
Então, parece que talvez isso seja um super implementação simples de GetString.
Mas eu desmascarado a camada da biblioteca CS50, por isso estou
chamando este char * agora.
Então vamos ver onde, se em qualquer lugar, nós erramos.
>> Linha 17 -
Volto a dizer, por favor, me dar alguma coisa, neste caso, uma cadeia de caracteres.
E, em seguida, na linha seguinte, eu chamo scanf, mais uma vez, dando-lhe um código de formato,
mas desta vez por cento s.
E, em seguida, desta vez, eu sou dando-lhe tampão.
>> Agora note, eu não estou usando o comercial.
Mas por que é que, provavelmente, OK aqui?
Porque o que é já tampão?
Já é um ponteiro.
Já é um endereço.
>> E vamos a palavra "confundir", deixe-me basta chamá-lo s, por exemplo, para
simplicidade.
Mas eu chamei-tampão porque em geral, na programação, se você tiver um
pedaço de memória, que uma seqüência realmente apenas é, você pode chamá-lo de um buffer.
É um lugar para armazenar informações.
>> Semelhante a coisas como o YouTube, quando eles estão de tamponamento, por assim dizer, que
significa apenas que ele está baixando pedaços de a internet e armazená-los em um
array local, um pedaço locais de memória para que você pode vê-lo mais tarde, sem
ele pular ou pendurado você durante a reprodução.
>> Portanto, há um problema aqui, porém, porque eu estou dizendo scanf, esperar um
corda do usuário.
Aqui está o endereço do um pedaço de memória.
Coloque a corda lá.
Por que é que bound dar nos problemas, embora?
>> O que é isso?
Tenho permissão para acessar que parte da memória?
Você sabe, eu não sei.
Porque tem tampão foi inicializado para alguma coisa?
Não é verdade.
E por isso é que temos vindo a chamar um valor de lixo, que
não é uma palavra formal.
Significa apenas que nós não temos nenhuma idéia do que pedaços estão dentro das quatro bytes
Tenho alocado como buffer.
>> Eu não chamei malloc.
Eu definitivamente não é chamado GetString.
Então, quem sabe o que é realmente dentro de tampão de?
E ainda dizendo scanf cegamente, vai lá e colocar o que o usuário digitou.
>> Então, o que é susceptível de causar em nosso código, se executá-lo?
Provavelmente um segfault.
Talvez não, mas provavelmente um segfault.
E eu digo talvez não, porque às vezes você faz, às vezes
você não tem um segfault.
Às vezes você apenas ter sorte, mas é mesmo assim vai ser
um bug no nosso programa.
>> Então deixe-me ir em frente e compilar isso.
Eu vou fazer do jeito old school.
Então bumbum traço 0, scanf-1, scanf-1.c, Enter.
Opa, escola muito antiga.
Vamos ver.
Onde é que eu vou?
Oh, buffer de char *.
Oh, thank you -
Salvar, OK -
escola muito antiga.
Tudo bem, isso já faz um tempo.
>> Então, eu acabei de salvar o arquivo depois fazendo que temporária
mudar de um momento atrás.
E agora eu compilei ele manualmente com Clang.
E agora eu estou indo para ir em frente e executar scanf-1, Enter.
Cordas favor.
Eu vou digitar "Olá".
>> E agora, aqui está em que, francamente, printf pode é um pouco irritante.
Não está indo realmente para segfault neste caso.
Printf é um pouco especial, porque é tão super comumente utilizado, que
essencialmente printf está fazendo -nos um favor e perceber,
isso não é um ponteiro válido.
Deixe-me levá-la a mim apenas para imprimir em parênteses nulo, mesmo
embora não seja necessariamente o que que nos esperava.
>> Portanto, não podemos muito facilmente induzir um segfault com isso, mas claramente este
não é o comportamento que eu queria.
Então, qual é a solução mais simples?
Bem, em scanf-2, deixe-me propor que em vez de verdade, apenas a atribuição de uma
char *, deixe-me ser um pouco mais esperto sobre isso, e deixe-me alocar buffer
como uma seqüência de 16 caracteres.
>> Então, eu posso fazer isso de duas maneiras.
Eu absolutamente poderia usar malloc.
Mas eu posso voltar a duas semanas, quando Eu só precisava de um monte de
caracteres.
Isso é apenas uma matriz.
Então me deixe em vez redefinir tampão a ser uma matriz de 16 caracteres.
>> E agora, quando eu passar tampão in -
e isso é algo que não fez falar em duas semanas -
mas você pode tratar uma variedade de mas é um endereço.
Tecnicamente, como vimos, eles são um pouco diferente.
Mas scanf não vai se importar se você passá-lo o nome de um array, porque o que
Clang fará por nós é essencialmente tratar o nome do array como o
endereço do bloco de 16 bytes.
>> Portanto, este é melhor.
Isto significa que agora que eu espero que possa faça o seguinte.
Deixe-me afastar por um momento e fazem scanf-2, compilada OK.
Agora, deixe-me que tenho barra scanf-2.
Cordas favor. "Olá". E parecia estar a trabalhar neste momento.
>> Mas alguém pode propor um cenário em que não pode ainda funciona?
Sim?
Algo mais do que 16 caracteres.
E, na verdade, podemos ser um pouco mais precisa.
Algo mais então 15 personagens, porque realmente precisamos ter em mente
que precisamos que barra invertida de zero implicitamente no final da cadeia,
que é um aparte scanf irá tipicamente cuidar para nós.
>> Então deixe-me fazer algo assim -
Às vezes, podemos apenas deixá-lo assim.
OK, então nós agora induzido nossa falha de segmentação.
Por quê?
Porque eu digitei a mais de 15 caracteres, e por isso nós realmente
memória tocado que eu realmente não deveria ter.
>> Então, qual é realmente a solução aqui?
Bem, e se precisamos de uma seqüência mais longa?
Bem, talvez torná-lo 32 bytes.
Bem, e se isso não é o suficiente?
Como cerca de 64 bytes?
E se isso não é o suficiente?
Como cerca de 128 bytes ou 200?
O que é realmente a solução aqui no caso geral, se não sabemos em
avançar o que o usuário vai digitar?
>> É apenas uma espécie de grande dor na bunda, para ser honesto, é por isso que o
Biblioteca CS50 tem algumas dezenas de linhas de código que implementar coletivamente
GetString cordas de uma forma que nós não tem que saber com antecedência o que o
de usuário vai digitar.
Em particular, se você olhar para trás, cs50.c de duas semanas atrás, você vai ver
GetString que realmente faz Não utilizar scanf desta maneira.
Em vez disso, ele lê um caractere de cada vez.
>> Porque a única coisa agradável sobre leitura de um personagem é o que pudermos
nós garantimos para sempre ter pelo menos um caractere.
Eu só posso declarar um char, e em seguida, tomar estes passos verdadeiramente bebê para apenas
leia um personagem em um tempo a partir do teclado.
E então, o que você vai ver GetString faz é cada vez ficar sem,
digamos, 16 bytes de memória, ele usa malloc, ou um seu primo, a
alocar mais memória, copiando o antigo memória para o novo, e, em seguida, rastejando
junto, obtendo um personagem de cada vez, e quando ele é executado fora do que
pedaço de memória, joga fora, agarra uma fatia maior de memória, copia velho
em novos e repete.
E é realmente uma dor de verdade implementar algo tão simples como
se a entrada de um usuário.
>> Então você pode usar scanf.
Você pode usar outras funções semelhantes.
E um monte de livros e on-line exemplos fazer, mas todos eles são
vulnerável a problemas como este.
E finalmente, se um segfault é meio chato.
Não é bom para o usuário.
>> Mas, na pior das hipóteses, o que faz fundamentalmente coloque o
codificar em risco de?
Algum tipo de ataque, potencialmente.
Nós conversamos sobre um tal ataque - transbordamento da pilha.
Mas, em geral, se você está autorizado a estourar um buffer, como nós fizemos um
Algumas semanas atrás, com apenas escrever mais do que "Olá" na pilha, você
pode realmente assumir, potencialmente, um computador, ou pelo menos começar a dados
não pertence a você.
>> Então, em suma, é por isso que temos essas rodinhas.
Mas, agora, começamos a tirá-las, como os nossos programas não precisa mais,
necessariamente, a entrada do utilizador.
Mas, no caso de problema de definir seis, sua contribuição virá de uma enorme
arquivo de dicionário com 150 alguns ímpares mil palavras.
>> Assim, você não terá que se preocupar com entrada arbitrária do utilizador.
Nós vamos dar-lhe algumas suposições sobre esse arquivo.
Qualquer dúvida sobre ponteiros ou scanf ou a entrada do usuário em geral?
>> Tudo bem, então um olhar rápido, em seguida, em um fuga tópico de duas semanas atrás.
E que era essa noção de um struct.
Não que - esta noção de um struct, o que era o quê?
O que struct fazer por nós?
>> Definir -
arrependido?
Definir um tipo de variável.
Então, mais ou menos.
Na verdade, estamos combinando dois tópicos.
Assim, com typedef, lembre-se que podemos declarar um tipo de nossa própria, como um
sinônimo, como string para char *.
Mas o uso de typedef e struct, podemos realmente criar nossas próprias estruturas de dados.
>> Por exemplo, se eu voltar para o gedit aqui só por um momento, e eu ir em frente
e fazer algo assim, deixe-me salvar isso como, digamos, structs.c
temporariamente, eu só vou para ir em frente e incluem
standardio.h, int void main.
E então, aqui, vamos supor que eu quero para escrever um programa que armazena
vários alunos de vários casas, por exemplo.
Então, é como um registrarial banco de dados de algum tipo.
>> Então, se eu preciso do nome de um estudante, eu poderia fazer algo parecido com o nome de char *,
e eu vou fazer algo parecido -
na verdade, vamos usar a biblioteca CS50 por apenas um momento para fazer deste um
pouco mais simples, para que possamos emprestar essas dezenas de linhas de código.
E vamos mantê-lo simples.
Vamos mantê-lo string, e agora GetString.
>> Então eu afirmo agora que eu tenho guardado o nome de algum aluno, ea casa de
algum aluno, simplesmente usando variáveis como fizemos e em uma semana.
Mas suponho que agora querem apoiar vários alunos.
Tudo bem, então meus instintos estão a fazer corda nome2, fica GetString, corda
house2 fica GetString.
E então o nosso terceiro estudante, vamos fazer name3 GetString.
>> Certo, então isso é sorte impressionante lo como uma espécie de idiota,
porque este processo é realmente nunca vai acabar, e ela só vai
fazer o meu código parece pior e pior e pior.
Mas nós resolvemos isso também em duas semanas.
Qual foi a nossa solução relativamente limpa quando tivemos múltiplas variáveis ​​do
mesmo tipo de dados que estão relacionados, mas nós não queremos essa confusão atroz
de variáveis ​​de nome semelhante?
O que vamos fazer em vez disso?
>> Então, eu acho que eu ouvi alguns lugares.
Tivemos uma matriz.
Se você quiser várias instâncias do alguma coisa, por que não vamos limpar isso tudo
e apenas dizer, me dar array chamado nomes?
>> E, por enquanto, vamos 3 código rígido.
E então me dar outro array chamados casas, e deixe-me por
agora rígido código 3.
E eu maciçamente limpou o bagunça que acabou de criar.
Agora, eu ainda codificado 3, mas mesmo o 3 poderia vir dinamicamente a partir do
utilizador, ou argv, ou semelhantes.
Então, isso já é mais limpo.
>> Mas o que é irritante sobre isso é que agora, mesmo que um nome é de alguma forma
fundamentalmente ligada à casa de um aluno -
é um estudante que eu realmente deseja representar -
Agora tenho duas matrizes que são paralelas no sentido de que eles são os
mesmo tamanho, e os nomes de suporte 0 presumivelmente mapas para casas suporte 0,
e os nomes de Suporte 1 mapas às casas suporte 1.
Em outras palavras, que o aluno vive em aquela casa, e que outro aluno
que vive em outra casa.
Mas, certamente, isso poderia ser feito ainda mais limpa.
>> Bem, isso pode, de fato.
E deixe-me ir em frente e abrir se structs.h, e você vai
veja essa idéia aqui.
Repare que eu usei typedef, como você aludiu há pouco para declarar o nosso
tipo de dados próprio.
Mas eu também estou usando essa outra palavra-chave chamado struct que me dá uma nova
estrutura de dados.
>> E essa estrutura de dados que afirmam que vai ter duas coisas no interior da
- uma string chamada nome, e uma série chamada casa.
E o nome que eu vou dar para esta estrutura de dados que vai
a ser chamado de estudante.
Eu poderia chamá-lo de qualquer coisa que eu quero, mas semanticamente fazer
sentido para mim em minha mente.
>> Então, agora, se eu abrir uma versão melhor do programa comecei a escrever
lá, deixe-me ir até o topo.
E há mais algumas linhas de código aqui, mas deixe-me concentrar para
o momento em um.
Eu já declarou uma constante chamada estudantes e codificado 3 por enquanto.
Mas agora, observe como limpo meu código começa a ficar.
>> Na linha 22, declaro conjunto de alunos.
E notem que o aluno é, aparentemente, agora um tipo de dados.
Porque no início deste arquivo, observe Eu incluí o arquivo de cabeçalho
que eu puxei apenas um momento atrás.
E esse arquivo de cabeçalho simplesmente tinha esta definição de um estudante.
>> Então, agora, eu criei meus próprios dados personalizados tipo que os autores do C anos
atrás não pensar com antecedência.
Mas não há problema.
Eu posso fazer isso sozinho.
Portanto, esta é uma matriz chamada estudantes, cada um dos membros cujos
é uma estrutura do estudante.
E eu quero que três desses na matriz.
>> E agora, o que faz o resto deste programa faz?
Eu precisava de algo um pouco arbitrária.
Assim, a partir online 24 em diante, Eu iterar de 0 a 3.
Eu, então, pedir ao usuário para o nome do aluno.
E então eu uso GetString como antes.
Então eu pergunto para a casa do aluno, e eu uso GetString como antes.
>> Mas aviso - um pouco nova pedaço de sintaxe -
Ainda posso índice para o i-th estudante, mas como faço para obter os dados específicos
campo dentro da estrutura?
Bem, o que é, aparentemente, a nova peça de sintaxe?
É apenas o operador ponto.
>> Nós não temos realmente visto isso antes.
Você já vi isso em pset cinco, se você tem mergulhou já com arquivos de bitmap.
Mas o ponto significa apenas dentro deste struct ou vários campos, dar ponto
nome, ou me dar dot casa.
Isso significa ir para dentro da estrutura e obter os campos específicos.
>> O que faz o resto deste programa faz?
Não é tudo o que sexy.
Observe que uma iteração de 0 a 3, novamente, e eu simplesmente criar um Inglês
frase como fulano de tal está em tal e tal casa, passando em nome de ponto de
o i-th aluno e sua casa também.
>> E então, finalmente, agora vamos começar a ter anal com isso, agora que estamos
familiarizado com o que malloc e outras funções tenham sido
fazendo todo esse tempo.
Por que eu tenho de libertar tanto o nome ea casa, apesar de eu
não chamar malloc?
>> GetString fez.
E esse foi o pequeno segredo sujo para várias semanas, mas tem GetString
sido vazamento de memória em todo o colocar todo o semestre até o momento.
E Valgrand vai finalmente revelar isso para nós.
>> Mas não é um grande negócio, porque eu sei que eu posso simplesmente liberar o nome
ea casa, apesar de, tecnicamente, a ser super, super seguro, eu deveria ser
fazer alguma verificação de erros aqui.
Quais são os seus instintos lhe dizendo?
O que devo estar verificando antes de liberar o que é um
string, aka que um char *?
>> Eu realmente deveria estar verificando se os alunos suporte i nome dot não
igual nulo.
Em seguida, ele vai ficar bem para ir em frente e livre esse ponteiro, e o mesmo ou outro
um bem.
Se os alunos suporte i dot casa não é igual a zero, isso agora vai proteger
contra o canto caso em que GetString retorna algo como nulo.
E vimos há pouco, printf vai proteger-nos aqui apenas dizendo
nulo, o que vai ficar estranho.
Mas pelo menos ele não vai segfault, como já vimos.
>> Bem, deixe me fazer uma outra coisa aqui. structs-0 é um tipo de programa estúpido
porque eu entro todos esses dados e, em seguida, ele perdeu uma vez o programa termina.
Mas deixe-me ir em frente e fazer isso.
Deixe-me fazer o terminal janela um pouco maior.
Deixe-me fazer-estruturas 1, que é uma nova versão deste.
>> Vou ampliar um pouco.
E agora deixe-me correr dot reduzir structs-1.
Nome do aluno -
David Mather, vamos fazer Rob Kirkland, vamos fazer Lauren Leverett.
O que é interessante agora é prévio -
e eu só sei disso porque Eu escrevi o programa -
há um arquivo agora na minha atual diretório chamado students.csv.
Alguns de vocês podem ter visto estas no mundo real.
>> O que é um arquivo CSV?
Valores separados por vírgulas.
É como uma espécie de homem pobre versão de um arquivo Excel.
É uma tabela de linhas e colunas que você pode abrir em um programa como o Excel,
ou os números em um Mac.
>> E se eu abrir esse arquivo aqui no gedit, prévio - e os números não estão lá.
Isso é apenas gedit dizendo me os números das linhas.
Repare na primeira linha deste arquivo é David e Mather.
A próxima linha é Rob vírgula Kirkland.
E a terceira linha é Lauren vírgula Leverett.
>> Então, o que eu criei?
Eu já escrevi um programa em C que efetivamente pode gerar planilhas
que pode ser aberto numa programa como o Excel.
Nem tudo o que obrigar um conjunto de dados, mas se você tem pedaços muito maiores de
dados que você realmente quer manipular e fazer gráficos de e
gosto, este é talvez um maneira de criar esses dados.
Além disso, CSVs são realmente super-comum apenas para armazenar dados simples -
Yahoo Finance, por exemplo, se você receber cotações de ações através de seu chamado
API, o serviço gratuito que permite que você esteja em stock, up-to-the-data atual
citações para as empresas, que dar os dados de volta no
Super formato CSV simples.
>> Então, como vamos fazer isso?
Bem notar, a maior parte deste programa de quase a mesma.
Mas note-se aqui, ao invés de impressão os alunos para fora, na linha 35
em diante, eu afirmo que estou guardando o estudantes em disco, para salvar um arquivo.
>> Então, repare que eu estou declarando um FILE * -
Agora, isso é uma espécie de anomalia no C. Por alguma razão, o FILE é todas as tampas,
o que não é como a maioria dos outros tipos de dados em C. Mas este é um built-in
tipo de dados, FILE *.
E eu estou declarando um ponteiro para um arquivo, é como você pode pensar isso.
>> fopen significa arquivo aberto.
O arquivo que você quer abrir?
Eu quero abrir um arquivo que eu vou arbitrariamente chamar students.csv.
Eu poderia chamar isso de qualquer coisa que eu quiser.
>> E, em seguida, dar um palpite.
O que faz o segundo argumento para fopen provavelmente significa?
Certo, w para escrever, poderia ser r para leitura.
Há uma para anexar se deseja adicionar linhas e não
substituir a coisa toda.
>> Mas eu só quero criar este arquivo uma vez, por isso vou usar citação unquote w.
E eu sei que só de ter lido a documentação, ou a página de manual.
Se o arquivo não é nulo - em outras palavras, Se nada deu errado lá -
deixe-me repetir ao longo do os alunos de 0 a 3.
>> E agora percebe que há algo sempre assim ligeiramente diferente
sobre a linha 41 aqui.
Não é printf.
É fprintf para o arquivo printf.
Então, ele vai gravar no arquivo.
Que arquivo?
Aquele cujo ponteiro que você especifique como o primeiro argumento.
>> Então nós especificar uma seqüência de formato.
Então nós especificamos o que queremos cadeia plug-in para o primeiro por cento s, e
em seguida, uma outra variável ou o segundo por cento s.
Depois, feche o arquivo com fclose.
Que eu liberar a memória como antes, embora Eu deveria voltar e adicionar
algumas verificações para null.
>> E é isso.
fopen, fprintf, fclose me dá a capacidade de criar arquivos de texto.
Agora, você vai ver problema em conjunto de cinco, que envolve imagens, que você vai usar
arquivos binários vez.
Mas, fundamentalmente, a idéia é a mesma, mesmo que as funções que você vai
ver é um pouco diferente.
>> Então rápido tour, mas você vai ter muito familiarizado com o arquivo I/O--
entrada e saída - com pset cinco.
E qualquer dúvida sobre a fundamentos iniciais aqui?
Sim?
>> E se você tentar libertar um valor nulo?
Eu acredito que, a menos que tenha obtido a livre pouco mais user-friendly, você pode
potencialmente segfault.
Passando-o nulo é ruim porque eu não acreditam livre preocupa em verificar para você,
porque seria potencialmente um desperdício de tempo para que ele faça a si mesmo para
todos no mundo.
Boa pergunta, no entanto.
>> Tudo bem, então esse tipo de fica nos a um tema interessante.
O tema do conjunto de problemas cinco é forense.
Pelo menos essa é a parte do conjunto de problemas.
Forensics geralmente se refere à recuperação de informações que podem ou
não pode ter sido excluído deliberadamente.
E então eu pensei que eu iria dar-lhe um rápido gosto do que realmente está acontecendo em todos os
desta vez sob o capa de seu computador.
>> Por exemplo, se você tem dentro do seu laptop ou computador de mesa a
disco rígido, ou é um mecânico dispositivo que realmente gira -
há coisas circulares chamados platters que parece muito com o que eu
só tinha acima na tela aqui, embora esta é a escola cada vez mais velho.
Esta é uma de três e meia polegadas disco rígido.
E três centímetros e meio refere-se de com a coisa quando você instalá-lo
em um computador.
>> Muitos de vocês em seus laptops agora têm drives de estado sólido, ou SSD,
que não têm partes móveis.
Eles são mais como RAM e menos como estes dispositivos mecânicos.
Mas as idéias ainda são os mesmos, certamente como eles se relacionam
para o problema de definir cinco.
>> E se você pensar agora um disco rígido representa ser um círculo, que
Eu vou desenhar como este aqui.
Quando você cria um arquivo no seu computador, se é um SSD, ou em
Neste caso, uma antiga escola de disco rígido, esse arquivo é composto por vários bits.
Vamos dizer que é este 0 e 1, um monte de 0s e 1s.
Portanto, este é o meu disco rígido inteiro.
Isto é, aparentemente, um arquivo muito grande.
E ele está usando a 0s e 1s em que porção do prato física.
>> Bem, o que é a parte física?
Bem, acontece que em um disco rígido, pelo menos deste tipo, não há
essas minúsculas partículas magnéticas.
E eles têm essencialmente norte e pólos sul para eles, de modo que se você
transformar uma dessas partículas magnéticas Desta forma, pode-se dizer que é
representando um 1.
E se está de cabeça para baixo para o sul para norte, você poderia dizer que é
representa um 0.
>> Assim, no mundo físico real, que é como você pode representar algo em
estado binário de 0 a 1 e um.
Então, isso é tudo que um arquivo é.
Há um monte de magnético partículas que são deste modo ou sua
Desta forma, a criação de padrões de 0s e 1s.
>> Mas acontece quando você salvar um arquivo, algumas informações são salvas separadamente.
Portanto, esta é uma pequena mesa, um diretório, por assim dizer.
E eu vou chamar este nome de coluna e Vou ligar para este local coluna.
>> E eu vou dizer, suponha este é o meu currículo.
Meu RESUME.DOC é armazenado a localização, vamos dizer 123.
Eu sempre vou para esse número.
Mas basta dizer que, assim como na memória RAM, você pode levar um disco rígido
isso é um gigabyte ou 200 gigabytes ou um terabyte, e você pode
número de todos os bytes.
Você pode enumerar todos os blocos de 8 bits.
>> Então, vamos dizer que este é a localização 123.
Portanto, este diretório dentro da minha operação sistema lembra que o meu
currículo é no local 123.
Mas fica interessante quando você apaga um arquivo.
>> Assim, por exemplo -
e, felizmente, a maior parte do mundo tem peguei para isso - o que acontece quando
você arrastar um arquivo para seu sistema operacional Mac Trash ou a sua Lixeira do Windows?
Qual é a finalidade de fazer isso?
É, obviamente, para livrar-se do arquivo, mas o que faz o ato de arrastar e
cair em seu lixo ou o seu Lixeira fazer em um computador?
>> Absolutamente nada, na verdade.
É como uma pasta.
É uma pasta especial, para ter certeza.
Mas será que isso realmente excluir o arquivo?
>> Bem, não, porque alguns de vocês provavelmente ter sido, oh caramba, você não fez
quero fazer isso.
Assim que você clicar duas vezes o Trash ou Lixeira.
Você já cutucou ao redor e você recuperou o arquivo apenas arrastando-o
de lá.
Então, claramente, não é necessariamente excluí-lo.
>> OK, você é mais esperto do que isso.
Você sabe que apenas arrastando-o para o Trash ou Lixeira não significa
você esvaziar a lixeira.
Então você vai até o menu, e você diz Esvaziar Lixeira ou Esvaziar Lixeira.
Então o que acontece?
>> Sim, por isso é eliminada mais.
Mas tudo o que acontece é o seguinte.
O computador se esquece de onde RESUME.DOC era.
>> Mas o que não mudou, aparentemente, na foto?
Os bits, os 0s e 1s que eu afirmo é no local de algum aspecto físico
o hardware.
Eles ainda estão lá.
É apenas o computador tem esqueceu o que eles são.
>> Portanto, é essencialmente livre do arquivo bits de modo que eles podem ser reutilizados.
Mas não até que você crie mais arquivos, e mais arquivos e mais arquivos serão
probabilisticamente, os 0s e 1s, aquelas partículas magnéticas, são reutilizados,
de cabeça ou do lado direito para cima, para outros arquivos, 0s e 1s.
>> Então você tem essa janela de tempo.
E não é de previsível comprimento, realmente.
Depende do tamanho do seu disco unidade e quantos arquivos você tem e
o quão rápido você fazer novos.
Mas há esta janela de tempo durante o que esse arquivo ainda é perfeitamente
recuperável.
>> Então, se você nunca usar programas como o McAfee ou Norton para tentar recuperar
de dados, tudo o que estamos fazendo é tentando recuperar este chamado diretório para
descobrir onde o arquivo foi.
E às vezes Norton e dirá: do arquivo é de 93% recuperável.
Bem, o que isso significa?
Isso só significa que algum outro arquivo coincidentemente acabou usando, por exemplo,
esses bits fora do seu arquivo original.
>> Então, o que está realmente envolvido na recuperação de dados?
Bem, se você não tem algo parecido Norton pré-instalado em seu computador,
o melhor que você às vezes pode fazer é olhar em todo o disco rígido à procura de
padrões de bits.
E um dos temas do conjunto de problemas cinco é que você vai pesquisar a
equivalente a um disco rígido, um forense imagem de um cartão de memória flash compacto a partir de um
câmera digital, buscando a 0s 1s e que normalmente, com elevada
probabilidade, representam o início de uma imagem JPEG.
>> E vocês podem recuperar aquelas imagens por supondo que, se eu vejo esse padrão de
bits na imagem forense, com elevada probabilidade, que marca
o início de um JPEG.
E se eu ver o mesmo padrão de novo, que provavelmente marca o início de
outro JPEG, e outro JPEG, e outro JPEG.
E este é tipicamente como recuperação de dados vai funcionar.
O que é agradável sobre JPEGs é mesmo o formato de arquivo em si é um pouco
complexo, no início de cada tal arquivo é realmente bastante identificável
e simples, como você vai ver, Se você não tiver já.
>> Então, vamos dar uma olhada embaixo o capô como a exatamente o que tem sido
acontecendo, e que estes 0s e 1s são, para lhe dar um pouco mais de um
contexto para este desafio particular.
>> [REPRODUÇÃO]
>> -Onde seu PC armazena mais dos seus dados permanentes.
Para isso, os dados viajam de RAM juntamente com os sinais de software que contam
o disco rígido como armazenar esses dados.
Os circuitos do disco rígido traduzir esses sinais em tensão
flutuações.
Estes, por sua vez, controlam o disco rígido do partes móveis, alguns dos poucos
partes móveis deixados no computador moderno.
>> Alguns dos sinais de controlo de um motor que gira bandejas de metal revestidas.
Seus dados são realmente armazenados sobre estas travessas.
Outros sinais de mover a leitura / gravação cabeças de leitura ou
gravar dados sobre os pratos.
Esta máquina tão preciso que um ser humano cabelo não poderia mesmo passar entre a
cabeças e pratos giratórios.
No entanto, tudo funciona em velocidades incríveis.
>> [FIM REPRODUÇÃO DE VÍDEO]
>> DAVID MALAN: Zoom em um pouco mais profunda agora o que está
realmente nesses pratos.
>> [REPRODUÇÃO]
>> -Vejamos o que acabamos de vi em câmera lenta.
Quando um breve pulso de eletricidade é enviado para a cabeça de leitura / gravação, se vira
em uma pequena electromagnética para uma fração de segundo.
O ímã cria um campo, que muda a polaridade de um pequeno, minúsculo
parte das partículas metálicas que casaco de cada superfície do prato.
>> A série padrão desses pequenos, cobrada até áreas no disco
representa um único bit dados no número binário
sistema usado pelos computadores.
Agora, se a corrente é enviada uma maneira através da leitura / escrita cabeça, a área
é polarizada em uma direção.
Se a corrente é enviada na sentido oposto, o
polarização é invertida.
>> Como você obter dados fora do disco rígido?
Apenas reverter o processo.
Por isso é que as partículas no disco que obtenha a corrente no
leitura / escrita cabeça se movendo.
Juntos milhões destes segmentos magnetizados e
você tem um arquivo.
>> Agora, as peças de um único arquivo pode ser espalhados por toda a unidade de
pratos, como o tipo de bagunça de papéis em sua mesa.
Assim, um arquivo muito especial mantém o controle de onde está tudo.
Você não gostaria de ter algo assim?
>> [FIM REPRODUÇÃO DE VÍDEO]
>> DAVID MALAN: OK, provavelmente não.
Assim como muitos de vocês Cresci com isso?
OK, por isso é cada vez menos mãos a cada ano.
Mas eu estou feliz que você esteja pelo menos familiarizado com eles, porque este e a nossa própria
demonstração livro, infelizmente, estão morrendo muito retardar a morte aqui de familiaridade.
>> Mas isso é o que eu, pelo menos, de volta ensino médio, o uso usada para backups.
E foi incrível, porque você pode armazenar 1,4 megabytes em
este disco em particular.
E esta foi a versão de alta densidade, como indicado pela HD, que tem
ou seja, antes de videos de hoje em HD.
>> Densidade padrão era de 800 kilobytes.
E antes disso, havia Discos de 400 kilobytes.
E antes disso, havia 5 e 1/4 discos polegadas, que eram verdadeiramente flexível,
e um pouco mais largo e mais alto que essas coisas aqui.
Mas você pode realmente ver o chamado aspecto disquete destes discos.
>> E funcionalmente, eles são realmente bastante semelhante ao de discos rígidos de pelo
menos deste tipo.
Mais uma vez, os SSDs em computadores mais novos trabalhar um pouco diferente.
Mas se você se move, que guia de metal pouco, você pode realmente ver um pouco de biscoito,
ou travessa.
>> Não é de metal como este.
Este é realmente um pouco mais barato material plástico.
E você pode tipo de manobra-lo.
E você trully apenas limpou alguns número de bits ou partículas magnéticas
a partir deste disco.
>> Então, graças a Deus, não há nada sobre ele.
Se aquela coisa está no caminho - e cobrir seus olhos e os de seu vizinho -
você pode apenas puxar este tipo de toda off bainha assim.
Mas há uma pequena mola, que assim seja ciente de que, com os seus olhos.
Então agora você tem realmente um disquete.
>> E o que é notável sobre esta é que, na medida em que este é um
representação em pequena escala de uma maior disco rígido, essas coisas são super,
super simples.
Se você apertar a parte inferior do mesmo, agora que que coisa de metal está fora, e descasque
las abertas, tudo o que há é duas peças de feltros e o chamado disquete
com uma peça de metal no interior.
>> E lá se vai metade do conteúdo do meu disco.
Lá vai outra metade deles.
Mas isso é tudo o que estava girando dentro de seu computador no passado.
>> E, novamente, para colocar isto em perspectiva, quão grande é a maioria de seu
discos rígidos de hoje em dia?
500 gigabytes, um terabyte, talvez em um computador desktop, dois terabytes, 3
terabytes, 4 terabytes, certo?
Este é um megabyte, mais ou menos, que não pode sequer colocar um MP3 típico
digitamos mais alguns dias ou algumas arquivo de música similar.
>> Assim, uma pequena lembrança para você hoje, e também para ajudar a contextualizar o
nós vamos tomar para concedido agora no problema definir cinco.
Portanto, estas são de sua propriedade.
Então deixe-me transição para onde será passar a próxima pset bem.
Então, nós temos agora definir esta página para - oh, um par de anúncios rapidamente.
>> Nesta sexta-feira, se você quiser se juntar a CS50 para o almoço, vá para o lugar de costume,
cs50.net/rsvp.
E projeto final -
então por o programa, nós postamos o especificação do projeto final já.
Perceba que isso não significa que é devido particularmente em breve.
Está publicado, na verdade, apenas para obter vocês pensando nisso.
E, de fato, um super significativa percentagem será enfrentar
projetos finais de material que nem sequer chegou a na classe,
mas será já na próxima semana.
>> Observe, porém, que a especificação exige alguns componentes diferentes do
projeto final.
A primeira, em algumas semanas, é um pré-proposta, um e-mail muito casual para
o TF para lhe dizer ou o que você está pensando para o seu projeto, com
nenhum compromisso.
Proposta será seu especial compromisso, dizendo, aqui, é isso que
Eu gostaria de fazer para o meu projeto.
O que você acha?
Muito grande?
Muito pequena?
É viável?
E você vê a especificação para mais detalhes.
>> Duas semanas após o que é o estado relatório, que é uma forma semelhante
email casual para o seu TF para dizer o quão muito para trás você está no seu final,
implementação do projeto, seguido por o CS50 Hackathon para o qual todos
é convidado, que será um evento de 20:00 em uma noite até 07:00
AM na manhã seguinte.
Pizza, como eu já mencionei na semana zero, wil ser servido às 9:00 horas,
Comida chinesa em 1h00.
E se você ainda estiver acordado à 5h00, vamos levá-lo para IHOP no café da manhã.
>> Assim, o Hackathon é um dos mais experiências memoráveis ​​na classe.
Em seguida, a implementação é devido, e em seguida, o CS50 Fair clímax.
Mais detalhes sobre todos esses nas semanas que virão.
>> Mas vamos voltar para algo escola de idade -
outra vez, uma matriz.
Assim, uma matriz foi bom, porque ele resolve problemas como vimos apenas um
momento atrás, com estruturas estudantis ficando um pouco fora de controle se
quer ter um aluno, estudante dois, estudante três, estudante dot dot dot,
um número arbitrário de alunos.
>> Então, matrizes, algumas semanas atrás, mergulhou em e resolveu todos os nossos problemas de não
sabendo de antemão quantas coisas de algum tipo que pode querer.
E temos visto que estruturas pode nos ajudar ainda organizar e manter o nosso código
variáveis ​​conceitualmente semelhantes, como a nome e uma casa, em conjunto, de modo que podemos
pode tratá-los como uma entidade, dentro dos quais existem pedaços menores.
>> Mas matrizes têm algumas desvantagens.
Quais são algumas das desvantagens nós encontramos
com matrizes até agora?
O que é isso?
Tamanho fixo - isso mesmo que você poderia ser capaz de alocar memória para um
matriz, uma vez que você sabe quantos alunos você tem, quantos caracteres você tem
do usuário, uma vez que você tenha alocado a matriz, você tipo de pintado
sozinho em um canto.
>> Porque você não pode inserir novos elementos no meio de uma matriz.
Você não pode inserir mais elementos no final de uma matriz.
Realmente, você tem que recorrer à criação de um Toda nova matriz, como já discutido,
copiando o antigo para o novo.
E mais uma vez, que é a dor de cabeça que Lida com GetString para você.
>> Mas, novamente, você não pode ainda inserir algo no meio da matriz
se a taxa não está completamente cheia.
Por exemplo, se essa matriz aqui de tamanho seis tem apenas cinco coisas nele,
Bem, você pode apenas alinhavar algo para o efeito.
Mas e se você quiser inserir algo no meio da
matriz, embora possa ter cinco dos seis coisas nele?
>> Bem, o que nós fizemos quando tivemos tudo dos nossos voluntários humanos no palco
semana passado?
Se quiséssemos colocar alguém aqui, também essas pessoas como mover este
modo, ou essas pessoas como mover este forma, e que se tornou caro.
O deslocamento de pessoas no interior de um série acabou somando e custando
nos tempo, portanto, muito do nosso n ao quadrado vezes funcionando como um tipo de inserção, por
exemplo, no pior dos casos.
Assim, as matrizes são grandes, mas você tem que saber de antemão o quão grande você quiser.
>> Então, bem, aqui está a solução.
Se eu não saber de antemão quantos os alunos que eu poderia ter, e eu sei que uma vez
Eu decido, porém, eu estou preso com que muitos estudantes, por que não eu sempre
alocar o dobro do espaço como eu poderia pensar que eu preciso?
Isso não é uma solução razoável?
>> Na realidade, eu não acho que nós somos vai precisar de mais de 50 vagas
em uma matriz para uma classe de tamanho médio, então vamos arredondar para cima.
Vou fazer 100 slots em meu array, apenas para que possamos definitivamente o
número de alunos que esperam ser, de alguma classe de tamanho médio.
Então por que não reunir e alocar mais memória, tipicamente, por uma matriz
que você acha que pode até mesmo precisar?
O que é isso pushback simples a essa idéia?
>> Você está apenas perdendo memória.
Literalmente todos os programas que você escreve, em seguida, é talvez usando o dobro da memória como
você realmente precisa.
E isso só não se sente como um particularmente solução elegante.
Além disso, apenas diminui o probabilidade de um problema.
Se acontecer de você ter um curso popular um semestre e tem 101
estudantes, o programa ainda é fundamentalmente enfrentando o mesmo problema.
>> Então, felizmente, há uma solução para Esse anúncio todos os nossos problemas, na forma
de estruturas de dados que são mais complexos do que os
temos visto até agora.
Isso, eu afirmo, é uma lista encadeada.
Esta é uma lista de números -
9, 17, 22, 26 e 34 -
que foram ligadas entre si por forma do que eu desenhei como flechas.
>> Em outras palavras, se eu queria representar uma matriz, que eu poderia fazer
algo como isto.
E eu vou colocar isso a sobrecarga em apenas um momento.
Eu poderia fazer -
Olá, tudo bem.
Stand by.
Novo computador aqui, claro -
tudo bem.
>> Então, se eu tenho esses números em ordem -
9, 17, 22, 26, 24 -
não necessariamente à escala.
Tudo bem, isso aqui é minha matriz -
oh meu deus.
Tudo bem, isso aqui é minha matriz.
Oh meu deus.
>> [Risos]
>> DAVID MALAN: Pretend.
É muito esforço para voltar e corrigir isso, então lá -
26.
Então nós temos esse conjunto de 9, 17, 22, 26, e 34.
Para aqueles de vocês pode ver o erro embaraçoso que acabou de fazer,
aí está.
>> Então, eu afirmo que este é um solução muito eficiente.
Eu alocado como muitos ints como Eu preciso - um, dois, três,
quatro, cinco ou seis -
e eu então armazenados os números dentro dessa matriz.
Mas vamos supor que, então, eu quero inserir um valor como o número 8?
Bem, para onde ela vai?
Suponha que eu queira inserir um número como 20.
Bem, para onde ele vai?
Em algum lugar no meio, ou o número 35 tem de passar
algures no final.
Mas eu estou fora do espaço.
>> E por isso este é um desafio fundamental das matrizes que não são a solução.
Afirmei há pouco, GetString resolve este problema.
Se você deseja inserir um sexto número nessa matriz, o que é, pelo menos, um
solução que você pode voltar a cair, com certeza, assim como fazemos com GetString?
O que é isso?
>> Bem, torná-lo maior é mais fácil de dizer do que fazer.
Nós não podemos necessariamente fazer a matriz maior, mas o que podemos fazer?
Faça uma nova matriz que é maior, de tamanho 6, ou talvez tamanho 10, se quisermos
para chegar à frente das coisas, e então copie o array antigo para o novo, e, em seguida,
libertar a antiga matriz.
>> Mas o que é o tempo de execução agora desse processo?
É grande S de n, porque a cópia vai lhe custar algumas unidades de
tempo, por isso não é tão ideal, se for preciso alocar uma nova matriz, o que está acontecendo
para consumir o dobro memória temporária.
Copie velho em novo -
Quero dizer, é só uma dor de cabeça, que é, mais uma vez, por que nós escrevemos
GetString para você.
>> Então, o que podemos fazer em vez disso?
Bem, e se a nossa estrutura de dados na verdade, tem lacunas nele?
Suponha que eu relaxo meu objetivo de ter blocos contíguos de memória, onde 9
é bem próximo a 17, o que é ao lado 22, e assim por diante.
>> E suponha que 9 pode ser aqui em RAM, e 17 pode ser aqui na RAM,
e 22 pode ser aqui na RAM.
Em outras palavras, eu não preciso deles mesmo voltar para trás mais.
Eu só tenho que de alguma forma enfiar uma agulha através de cada um desses números, ou cada
desses nós, como vamos chamar o retângulos como eu desenhei-los, para
lembrar de como chegar até o último tal nó do primeiro.
>> Então o que é construir a programação vimos há pouco tempo com o qual eu
pode implementar esse segmento, ou traçada aqui, com o qual eu posso
implementar essas flechas?
Ponteiros assim, certo?
Se eu não alocar apenas um int, mas um nó - e por
nó, eu só quero dizer container.
E visualmente, eu quero dizer um retângulo.
Assim, um nó aparentemente precisa para conter dois valores -
o próprio int, e então, como se conclui da a metade inferior do retângulo,
espaço suficiente para um int.
>> Então, basta pensar no futuro aqui, quão grande é este nó, este
recipiente em questão?
Quantos bytes para o int?
Presumivelmente, 4, se é o mesmo que o habitual.
E então quantos bytes para o ponteiro?
4.
Portanto, este recipiente, ou esse nó, é vai ser uma estrutura de 8 bytes.
Oh, e isso é uma feliz coincidência que que acaba de introduzir a noção de
uma estrutura, ou uma estrutura C.
>> Então eu reclamar que eu quero dar um passo para isso mais sofisticado
implementação de uma lista de números, um lista encadeada de números, eu preciso fazer uma
pouco mais o pensamento na frente e declarar não apenas um int, mas um struct
que eu ligo, convencionalmente aqui nó.
Poderíamos chamá-lo de qualquer coisa que quisermos, mas nó vai ser temática em um monte
das coisas que começar a olhar para agora.
>> Dentro desse nó é um int n.
E então essa sintaxe, um pouco estranho à primeira vista -
struct node * seguinte.
Bem pictoricamente, o que é isso?
Essa é a metade inferior da o retângulo que vimos
apenas um momento atrás.
>> Mas por que estou dizendo struct node * ao invés de apenas nó *?
Porque se esse ponteiro está apontando em outro nó, ele é apenas o
endereço de um nó.
Isso é consistente com o que nós temos discutido sobre ponteiros até o momento.
Mas por que, se eu reclamar esta estrutura é chamado de nó, que eu tenho a dizer struct
nó aqui dentro?
>> Exatamente.
É uma espécie de uma realidade estúpida C. O typedef, por assim dizer, não tem
aconteceu ainda.
C é super literal.
Ele lê o seu código para cima baixo, da esquerda para a direita.
E até atingir esse ponto e vírgula no linha de fundo, acho que não funciona
existir como um tipo de dados?
Nó, o nó entre aspas.
>> Mas por causa da mais detalhado declaração que eu fiz na primeira linha -
typedef struct node -
porque que veio primeiro, antes do chaves, que é uma espécie de como
pré-educar Clang isso, você Sabe, me dê um struct
chamado nó struct.
Francamente, eu não gosto de coisas que chamam struct node, struct node tudo
todo o meu código.
Mas eu só vou usá-lo uma vez, apenas dentro, para que eu possa efetivamente
criar uma espécie de referência circular, não um ponteiro para mim mesmo, por si só, mas uma
apontador para outra um do mesmo tipo.
>> Assim, verifica-se que em uma estrutura de dados assim, há alguns
as operações que podem ser de interesse para nós.
Podemos querer inserir em uma lista como esta.
Podemos querer apagar a partir de uma lista como esta.
Podemos querer pesquisar a lista para um valor, ou, mais geralmente, travessia.
E transversal é apenas uma maneira elegante de dizendo início à esquerda e mover todos
o caminho para a direita.
>> E notem, mesmo com esse pouco mais estrutura de dados sofisticado, vamos
me propor que podemos emprestar alguns dos as idéias das últimas duas semanas e
implementar uma função chamada pesquisa como esta.
Vai retornar verdadeiro ou falsa, indicando, sim ou
n, n está na lista.
O segundo argumento é um ponteiro para a própria lista, de modo a
ponteiro para um nó.
>> Tudo o que eu vou fazer em seguida é declarar uma variável temporária.
Vamos chamá-lo de ptr por convenção, para ponteiro.
E eu atribuí-lo igual ao início da lista.
>> E agora observe o loop while.
Enquanto o ponteiro não é igual como nulo, vou verificar.
É ponteiro de seta n igual a o n que foi passado em?
E espere um minuto - novo pedaço de sintaxe.
Qual é a flecha de repente?
Sim?
>> Exatamente.
Assim, enquanto a poucos minutos atrás, usamos a notação de ponto para acessar algo
o interior de uma estrutura, se a variável você não é o struct
si mesmo, mas um ponteiro para um struct, felizmente, um pedaço de sintaxe que
finalmente faz sentido intuitivo.
A seta significa seguir o ponteiro, como nossas flechas normalmente significa
pictoricamente, e ir em campo de dados no interior.
Então seta é a mesma coisa que ponto, mas você usá-lo quando você tem um ponteiro.
>> Então, só para recapitular, então, se o campo de n dentro da estrutura chamada de ponteiro
é igual a igual a n, retorna true.
Caso contrário, essa linha aqui - ponteiro igual ponteiro próximo.
Então o que está fazendo, o aviso prévio, é que se eu atualmente estou apontando para a estrutura
contendo 9 e 9 não é o número Estou procurando - suponho que eu estou procurando
para n igual a 50 -
Eu vou atualizar meu ponteiro temporário para não apontar para este nó
mais, mas ponteiro seta ao lado, que vai me colocar aqui.
>> Agora, percebi que é um turbilhão introdução.
Na quarta-feira, vamos realmente fazer isso com alguns seres humanos, e com um pouco mais
código em um ritmo mais lento.
Mas percebo, agora estamos fazendo os nossos dados estruturas mais complexas para que o nosso
algoritmos podem ficar mais eficiente, o que vai ser requisito para
pset seis anos, quando nós carregamos dentro, mais uma vez, aqueles 150 mil palavras, mas precisa fazê-lo
de forma eficiente e, idealmente, criar um programa que é executado para os nossos usuários não em
linear, não em n ao quadrado, mas, em constante de tempo, no ideal.
>> Vemo-nos na quarta-feira.
>> Palestrante: Na próxima CS50, David esquece o seu caso base.
>> DAVID MALAN: E é assim que você envia mensagens de texto com C. Que -
>> [VÁRIOS MENSAGEM DE TEXTO Sons de notificação]