Speak: Hittills är det troligt att de flesta av dina program har varit lite kortlivad. Du kör ett program som Mario eller giriga. Det gör något, det kanske uppmanas användaren om viss information, skriva ut vissa utdata till skärmen, men sedan när programmet är över, det finns egentligen inga bevis finns det någonsin kör i första hand. Jag menar, visst, du kanske har lämnat Det öppnas i terminalfönstret, men om du rensar din skärm, det finns egentligen inga bevis för att det fanns. Vi har inte ett sätt att lagra ihållande, information som existerar efter vår Programmet har stannat, eller så har vi inte upp till denna punkt. Lyckligtvis gör c ge oss möjlighet att göra detta genom att implementera något som kallas en fil, en struktur som i grund och botten representerar en fil som du skulle fördubbla klicka på din dator, om du är van vid ett grafiskt användarmiljö. Generellt vid arbete med c, vi är faktiskt kommer att arbeta med pekare till files-- fil stars-- med undantag för lite när vi talar om ett par av de funktioner som arbeta med fil pekare. Du behöver inte ha riktigt grävt för djupt för att öka kunskapen pekare själva. Det finns en liten pyttelitet bit där vi kommer att prata om dem, men i allmänhet fil pekare och pekare, medan varandra, är inte exakt samma sak. Nu vad jag menar när Jag säger ihållande data? Vad är beständiga data? Varför vi bryr oss om det? Säg till exempel att du kör ett program eller om du har skrivit om en program som är ett spel, och du vill hålla koll av alla användarens rörelser så att kanske om något går fel, du kan granska filen efter matchen. Det är vad vi menar när vi prata om beständiga data. Under köra din program, skapas en fil. Och när ditt program har stannat, att filen finns fortfarande på ditt system. Och vi kan titta på det och undersöka det. Och så det programmet skulle ställas in på har skapat några beständiga data, Det finns uppgifter efter programmet har körts. Nu har alla dessa funktioner som fungerar med att skapa filer och manipulera dem på olika sätt bor i standard io.h, vilket är en header-fil som du har förmodligen varit pund inbegripet på toppen av vackra mycket alla dina program eftersom den innehåller en av de mest användbara funktioner för oss, printf, som också låter bor i standard io.h. Så du behöver inte pund inkluderar eventuella ytterligare filer förmodligen för att arbeta med fil pekare. Nu varenda filpekaren funktion, eller varje enskild fil I / O, Input Output funktionen accepterar som en av dess parametrar eller insatsvaror en fil pointer-- utom för en, fopen, vilket är vad du använder för att hämta filen pekaren i första hand. Men efter att du har öppnat fil och du får filen pekare, Du kan sedan skicka dem som argument till de olika funktionerna vi kommer att prata om idag, liksom många andra så att du kan arbeta med filer. Så det finns sex ganska gemensamma grundläggande ettor att vi kommer att prata om idag. fopen och dess följeslagare funktion fclose, fgetc och dess följeslagare funktion fputc, och fread och dess följeslagare funktion, fwrite. Så låt oss få rätt till det. fopen-- vad gör det? Tja, öppnar det en fil och det ger dig en fil pekare till det, så att du sedan kan använda det fil pekare som ett argument till någon av de andra fil-I / O-funktioner. Det viktigaste att minnas med fopen är att när du har öppnat fil eller gjorde ett samtal som den här, du behöver för att kontrollera att att pekaren att du kommer tillbaka är inte lika med noll. Om du inte har sett videon på pekare, vilket kanske inte vettigt. Men om du försöker och dereference en null-pekare återkallelse, ditt program kommer sannolikt att bli lidande en segmente [OHÖRBAR]. Vi vill se till att vi fick en legitim pekare tillbaka. Den stora majoriteten av den tid som vi kommer har fått en legitim pekare tillbaka och det kommer inte att vara ett problem. Så hur gör vi ett anrop till fopen? Det ser ut ungefär som den här. Fil stjärna ptr-- PTR vara en generisk namn för fil pointer-- fopen och vi passera i två saker, ett filnamn och en operation som vi vill utföra. Så vi kan ha ett samtal som ser ut this-- fil stjärn ptr en lika fopen fil1.txt. Och operationen jag har valt r. Så vad tror du r är här? Vad är den typ av saker som vi skulle kunna göra för att filer? Så r är den verksamhet som vi välja när vi vill läsa en fil. Så skulle vi i princip när Vi gör ett samtal så här att få oss en filpekare så att vi sedan kan läsa information från fil1.txt. På samma sätt kan vi öppna filen 2.txt för att skriva och så att vi kan passera ptr2, filpekaren jag har skapat här, som ett argument till en funktion som skriver information till en fil. Och liknande till skrivande, det finns också möjlighet att lägga till en. Skillnaden mellan skriva och lägga är att när du skriver till en fil, om du gör ett samtal till fopen för att skriva och att filen redan existerar, det är kommer att skriva över hela filen. Det kommer att börja i början, radera all information det är redan där. Medan om du öppnar det för att lägga, det kommer att gå till slutet av filen Om det redan finns text i det eller informationen i den, och det kommer då att börja skriver därifrån. Så du kommer inte att förlora någon av de information som du har gjort förut. Oavsett om du vill skriva eller lägga sorts beror på situationen. Men du kommer förmodligen vet vad rätt verksamhet är när det är dags. Så det är fopen. Vad sägs om fclose? Tja, ganska enkelt, fclose bara accepterar filpekaren. Och som man kan förvänta sig, det stänger den filen. Och när vi har stängt en fil, vi kan inte utföra mer fil-I / O-funktioner, läser eller skriver på den filen. Vi måste åter öppna fil en annan tid för att fortsätta arbeta med den med hjälp av I / O-funktioner. Så fclose sätt vi gjort arbeta med denna fil. Och allt vi behöver skicka in är namnet på en fil pekare. Så på ett par glider sedan, vi fopened fil 1 dot text för läsning och vi tilldelade att fil pekare till ptr1. Nu har vi beslutat att vi är gjort läsning från den filen. Vi behöver inte göra något mer med det. Vi kan bara fclose ptr1. Och på samma sätt, kunde vi fclose de andra. Okej. Så det är att öppna och stänga. De är de två grundläggande startoperationer. Nu vill vi faktiskt göra några intressanta saker, och första funktion som vi ska se som kommer att göra det är fgetc-- fil får en karaktär. Det är vad fgetc allmänhet skulle översätta till. Dess mål i livet är att Läs nästa tecken, eller om detta är din mycket första samtalet till fgetc för en viss fil, det första tecknet. Men sedan efter det, du får nästa, redan nästa karaktär filen, och lagrar det i ett tecken variabel. Som vi har gjort här, char ch lika fgetc, passera i namnet på en fil pekare. Återigen, det är mycket viktigt här att komma ihåg att för att ha denna operation lyckas, filpekaren själv måste har öppnats för läsning. Vi kan inte läsa en karaktär från en fil pekare som vi öppnade för skrivning. Så det är en av de begränsningar av fopen, eller hur? Vi måste begränsa oss endast utför en operation med en fil pekare. Om vi ​​ville läsa och skriva från samma fil, vi skulle ha öppet två separata fil pekare till samma file-- ett för läsning, en för att skriva. Så återigen, det enda skälet Jag tar upp det nu är för om vi ska ringa till fgetc, den filen pekare måste har öppnats för läsning. Och sedan ganska enkelt, allt vi behöver göra är passera i namnet på filen pekaren. Så röding lm lika fgetc ptr1. Det kommer att få oss nästa character-- eller återigen, om detta är den första När vi har gjort det här samtalet, den första character-- oavsett fil pekas på av ptr1. Minns att det var fil 1 dot text. Det får det första tecknet i det och vi kommer att lagra det i variabeln ch. Ganska enkelt. Så vi har bara tittat på tre funktioner och redan vi kan göra något ganska snyggt. Så om vi tar denna förmåga för att få ett tecken och vi slinga det-- så vi fortsätter att få tecken från en fil över och över och over-- nu vi kan läsa varenda karaktären av en fil. Och om vi trycker varje tecken omedelbart efter att vi läst det, Vi har nu läsa från en fil och tryckta innehållet till skärmen. Vi har faktiskt sammanlänkade den filen på bildskärmen. Och det är vad Linux kommandot cat gör. Om du skriver katt i filnamnet, det kommer att skriva ut hela innehållet av filen i din terminalfönster. Och så denna lilla slinga här, bara tre rader kod, men det effektivt duplicerar Linux kommandot cat. Så här syntaxen kanske ser lite konstigt, men här är vad som händer här. Medan ch lika fgetc, inte ptr lika med EOF-- det är en hel munsbit, men låt oss bryta ner det bara så det är klart på syntax. Jag har konsoliderat det för tydlighets utrymme, även om det är lite syntaktiskt knepigt. Så här delen i grönt till höger nu, vad gör det? Tja, det är bara vår fgetc samtal, eller hur? Vi har sett det förut. Det är få en tecken från filen. Sedan jämföra vi att karaktär mot EOF. EOF är ett speciellt värde som är definieras i standarden io.h, vilket är slutet på filen karaktär. Så i princip vad som kommer att hända är denna slinga kommer att läsa ett tecken, jämföra det med EOF, den filslut karaktär. Om de inte stämmer överens, så vi har inte nått slutet av filen, Vi kommer att skriva tecknet ut. Sedan ska vi gå tillbaka till slingans början igen. Vi får en karaktär, kontrollera mot EOF, skriva ut, och så vidare och så vidare och så vidare, looping igenom på det sättet tills vi har nått slutet av filen. Och sedan vid den tidpunkten, Vi kommer att ha tryckt ut hela innehållet i filen. Så återigen, har vi bara sett fopen, fclose och fgetc och redan kan vi duplicera en linux terminal kommando. Som jag sade i början, Vi hade fgetc och fputc, och fputc var följeslagare funktion av fgetc. Och så, som ni kanske förstår, det är skriv motsvarande. Det ger oss möjlighet att skriva en enstaka tecken till en fil. Återigen, det förbehållet att, precis som det var med fgetc, filen att vi skriver till måste har varit öppnat för att skriva eller lägga till. Om vi ​​försöker använda fputc på en fil att vi har öppnat för läsning, vi kommer att lida en bit av ett misstag. Men samtalet är ganska enkel. fputc huvudstad En ptr2, alla det kommer att göra är att det är kommer att skriva brev i A i fil 2 dot text, som var namnet på den filen som vi öppnade och tilldelas pekaren till ptr2. Så vi kommer att skriva ett kapital A till fil 2 dot text. Och vi kommer att skriva ett utropstecken peka på fil 3 dot text, som utpekas av ptr3. Så återigen, ganska enkelt här. Men nu kan vi göra en annan sak. Vi har detta exempel vi bara gå över om att kunna replikera katten Linux kommando, den som skriver ut till skärmen. Nåväl, nu när vi har förmågan att läsa tecken från filer och skriva tecken till filer, varför inte vi bara ersätta det ringa för att printf med en uppmaning till fputc. Och nu har vi dupliceras cp, en mycket grundläggande linux kommando att vi pratade om hur länge sedan i linux kommandon videon. Vi har på ett effektivt sätt dupliceras denna rätt här. Vi läser en karaktär och då är vi skriftligen tecken till en annan fil. Läsning från en fil, skriva till en annan, om och om igen och om igen tills vi hit EOF. Vi har kommit till slutet av fil vi försöker kopiera från. Och genom att vi har skrivit alla av karaktärerna måste vi filen att vi skriver till. Så det här är cp, kopiera kommandot Linux. Alldeles i början av den här videon hade jag varning att vi skulle prata lite om pekare. Här är särskilt där vi är kommer att tala om pekare förutom till fil pekare. Så här funktionen ser lite skrämmande. Det har fått flera parametrar. Det är mycket som händer här. Det finns en massa olika färger och texter. Men egentligen, det är bara generisk version av fgetc som tillåter oss att få någon mängd information. Det kan vara lite ineffektivt om vi är få tecken ett i taget, iterera igenom filen ett tecken i taget. Skulle det inte vara trevligare att få 100 åt gången eller 500 på en gång? Tja, fread och dess följeslagare funktion fwrite, som vi kommer att prata om i en andra, tillåter oss att göra just detta. Vi kan läsa ett godtyckligt belopp av information från en fil och vi förvara den någonstans tillfälligt. I stället för att kunna precis montera den i en enda variabel, Vi kanske behöver förvara den i en array. Och så, vi passerar i fyra argument att fread-- en pekare till den plats där vi är kommer att lagra information, hur stor varje informationsenhet kommer att bli, hur många enheter av informations Vi vill att förvärva, och från vilken fil vi vill få dem. Illustreras förmodligen bäst med ett exempel här. Så låt oss säga att vi deklarerar en array av 10 heltal. Vi har just förklarat på stapla godtyckligt int arr 10. Så det är ganska enkelt. Nu vad vi gör men är frecall är vi läser storleken på int gånger 10 byte med information. Storlek på int vara four-- det är storleken på ett heltal i c. Så vad vi gör är att vi läser 40 byte till ett värde av uppgifter från filen som utpekas av PTR. Och vi lagrar dem 40 bytes någonstans där vi har avsatt 40 byte värde av minne. Lyckligtvis har vi redan gjort det genom att förklara arr att array där. Som har förmåga att innehav 10 fyra-byte enheter. Så totalt, kan det hålla 40 bytes värde av information. Och vi nu läser 40 byte information från filen, och vi lagra den i arr. Minns från videon på pekare som namnet på en array, såsom arr, är egentligen bara en pekare till dess första elementet. Så när vi passerar i arr där, vi är i själva verket, som passerar i en pekare. På samma sätt kan vi göra this-- Vi gör inte nödvändigtvis måste rädda vår buffert på stacken. Vi kunde också dynamiskt allokera en buffert så här, med hjälp av malloc. Kom ihåg att när vi dynamiskt allokera minne, vi sparar det på hög, inte bunten. Men det är fortfarande en buffert. Det fortfarande, i det här fallet, är hålla 640 byte med information eftersom en dubbel tar upp åtta byte. Och vi ber för 80 av dem. Vi vill ha utrymme att hålla 80 dubbel. Så 80 gånger 8 är 640 bytes information. Och denna uppmaning till fread är samla 640 byte med information från filen som pekas på av PTR och lagra den nu arr2. Nu kan vi också behandla fread precis som ett samtal till fgetc. I det här fallet, vi försöker bara få ett tecken från filen. Och vi behöver inte ett array för att hålla ett tecken. Vi kan bara förvara den i en teckenvariabel. Fångsten är dock att när vi har bara en variabel, Vi behöver skicka i adressen till den variabel eftersom minns att första argumentet till fread är en pekare till platsen och minne där vi vill lagra informationen. Återigen, namnet på en matris är en pekare. Så vi behöver inte göra-tecken array. Men c, karaktären c här är inte en matris. Det är bara en variabel. Och så vi behöver för att klara ett et-c för att indikera att det är den adress där vi vill att lagra denna en byte med information, detta ett tecken som vi samla från PTR. Fwrite-- jag ska gå igenom detta lite mer quickly-- är ganska mycket exakt motsvarighet till fread förutom att det är för att skriva istället för att läsa, bara som other-- vi har haft öppna och nära, få en karaktär, skriva ett tecken. Nu är det få godtycklig mängd information, rätt godtycklig mängd information. Så precis som förut, vi kan har en matris med 10 heltal där vi redan har information som lagras, kanske. Det var förmodligen några rader kod som bör gå mellan dessa två där jag fyller arr med något meningsfullt. Jag fyller den med 10 olika heltal. Och i stället, vad jag gör skriver från arr och samla in information från arr. Och jag tar denna information och sätta in den i filen. Så i stället för att det är från filen till bufferten, vi nu går från bufferten till filen. Så det är bara det omvända. Så återigen, precis som tidigare, kan vi har också en heap bit av minne att vi har dynamiskt fördelas och läsa från den och skriver att till filen. Och vi har också en enda variabel förmåga att hålla en bitgrupp av information, såsom ett tecken. Men återigen, vi måste passera adressen för den variabeln när vi vill läsa från den. Så vi kan skriva ner informationen Vi hittar på denna adress till filpekaren, PTR. Det finns massor av andra stor fil I / O-funktioner att göra olika saker förutom de vi har pratat om i dag. Ett par av dem du kan ha nytta av är fgets och fputs, vilka är ekvivalenta av fgetc och fputc men för läsning en enda sträng från en fil. I stället för ett enda tecken, Det kommer att läsa en hel sträng. fprintf, som i princip gör det möjligt du kan använda printf att skriva till filen. Så precis som du kan göra variabelsubstitution med hjälp av den platshållarna procent i och procent d, och så vidare, med printf kan på liknande sätt ta printf sträng och skriva ut något så där till en fil. fseek-- om du har en DVD-spelare är analogin jag brukar använda här-- är ungefär som att använda din spola tillbaka och snabbspola framåt knapparna för att flytta runt på filmen. På samma sätt kan du flytta runt filen. En av de saker inuti att filstrukturen att c skapar för dig är en indikator av var du befinner dig i filen. Är du på mycket början, vid byte noll? Är du på byte 100, byte 1000, och så vidare? Du kan använda fseek godtyckligt flytta denna indikator framåt eller bakåt. Och ftell, återigen liknar en DVD-spelare, är som en liten klocka som berättar hur många minuter och sekunder dig är i en viss film. På liknande sätt, berättar ftell hur många bytes du är i filen. feof är en annan version detektera om du har nått slutet av filen. Och ferror är en funktion som du kan använda att upptäcka om något har gått fel arbetsdag med en fil. Återigen, detta är bara skrapa på ytan. Det finns fortfarande mycket mer fil-I / O funktioner i standard io.h. Men det kommer förmodligen att få dig började arbeta med fil pekare. Jag är Doug Lloyd. Detta är CS50.