Would you like to inspect the original subtitles? These are the user uploaded subtitles that are being translated:
0
00:00:00,000 --> 00:00:05,330
1
00:00:05,330 --> 00:00:07,870
>> SPEAKER: So far, it's likely that most of your programs
2
00:00:07,870 --> 00:00:10,170
have been a bit ephemeral.
3
00:00:10,170 --> 00:00:13,310
You run a program like Mario or Greedy.
4
00:00:13,310 --> 00:00:17,350
It does something, it maybe prompts the user for some information,
5
00:00:17,350 --> 00:00:20,400
print some output to the screen, but then when your program's over,
6
00:00:20,400 --> 00:00:23,252
there's really no evidence there it was ever run in the first place.
7
00:00:23,252 --> 00:00:25,960
I mean, sure, you might have left it open in the terminal window,
8
00:00:25,960 --> 00:00:29,770
but if you clear your screen, there's really no evidence that it existed.
9
00:00:29,770 --> 00:00:33,720
We don't have a means of storing persistent information, information
10
00:00:33,720 --> 00:00:36,890
that exists after our program has stopped running,
11
00:00:36,890 --> 00:00:39,241
or we haven't up to this point.
12
00:00:39,241 --> 00:00:41,490
Fortunately though, c does provide us with the ability
13
00:00:41,490 --> 00:00:44,220
to do this by implementing something called
14
00:00:44,220 --> 00:00:48,330
a file, a structure that basically represents a file that you would double
15
00:00:48,330 --> 00:00:53,826
click on your computer, if you're used to a graphical user environment.
16
00:00:53,826 --> 00:00:55,700
Generally when working with c, we're actually
17
00:00:55,700 --> 00:00:59,965
going to be working with pointers to files-- file stars--
18
00:00:59,965 --> 00:01:02,090
except for a little bit when we talk about a couple
19
00:01:02,090 --> 00:01:04,560
of the functions that work with file pointers.
20
00:01:04,560 --> 00:01:08,990
You don't need to have really dug too deep into understanding pointers
21
00:01:08,990 --> 00:01:09,730
themselves.
22
00:01:09,730 --> 00:01:12,870
There's a little teeny bit where we will talk about them,
23
00:01:12,870 --> 00:01:18,090
but generally file pointers and pointers, while interrelated,
24
00:01:18,090 --> 00:01:20,290
are not exactly the same thing.
25
00:01:20,290 --> 00:01:22,440
>> Now what do I mean when I say persistent data?
26
00:01:22,440 --> 00:01:23,650
What is persistent data?
27
00:01:23,650 --> 00:01:25,232
Why do we care about it?
28
00:01:25,232 --> 00:01:27,190
Say, for example, that you're running a program
29
00:01:27,190 --> 00:01:29,850
or you've rewritten a program that's a game,
30
00:01:29,850 --> 00:01:32,960
and you want to keep track of all of the user's moves
31
00:01:32,960 --> 00:01:36,620
so that maybe if something goes wrong, you can review the file after the game.
32
00:01:36,620 --> 00:01:39,970
That's what we mean when we talk about persistent data.
33
00:01:39,970 --> 00:01:43,930
>> In the course of running your program, a file is created.
34
00:01:43,930 --> 00:01:45,680
And when your program has stopped running,
35
00:01:45,680 --> 00:01:48,689
that file still exists on your system.
36
00:01:48,689 --> 00:01:50,230
And we can look at it and examine it.
37
00:01:50,230 --> 00:01:53,670
And so that program would be set to have created some persistent data,
38
00:01:53,670 --> 00:01:57,390
data exist after the program has finished running.
39
00:01:57,390 --> 00:02:02,320
>> Now all of these functions that work with creating files and manipulating
40
00:02:02,320 --> 00:02:04,940
them in various ways live in standard io.h,
41
00:02:04,940 --> 00:02:08,210
which is a header file that you've likely been pound
42
00:02:08,210 --> 00:02:10,910
including at the top of pretty much all of your programs
43
00:02:10,910 --> 00:02:14,130
because it contains one of the most useful functions for us,
44
00:02:14,130 --> 00:02:16,130
printf, that also lets lives in standard io.h.
45
00:02:16,130 --> 00:02:20,400
So you don't need to pound include any additional files probably
46
00:02:20,400 --> 00:02:23,540
in order to work with file pointers.
47
00:02:23,540 --> 00:02:29,980
>> Now every single file pointer function, or every single file I/O, input output
48
00:02:29,980 --> 00:02:33,310
function, accepts as one of its parameters or inputs
49
00:02:33,310 --> 00:02:35,822
a file pointer-- except for one, fopen, which
50
00:02:35,822 --> 00:02:38,280
is what you use to get the file pointer in the first place.
51
00:02:38,280 --> 00:02:41,010
But after you've opened the file and you get file pointers,
52
00:02:41,010 --> 00:02:43,510
you can then pass them as arguments to the various functions
53
00:02:43,510 --> 00:02:46,720
we're going to talk about today, as well as many others
54
00:02:46,720 --> 00:02:48,520
so that you can work with files.
55
00:02:48,520 --> 00:02:50,980
>> So there are six pretty common basic ones
56
00:02:50,980 --> 00:02:52,870
that we're going to talk about today.
57
00:02:52,870 --> 00:02:57,160
fopen and its companion function fclose, fgetc
58
00:02:57,160 --> 00:03:02,670
and its companion function fputc, and fread and its companion function,
59
00:03:02,670 --> 00:03:03,820
fwrite.
60
00:03:03,820 --> 00:03:05,180
So let's get right into it.
61
00:03:05,180 --> 00:03:07,050
>> fopen-- what does it do?
62
00:03:07,050 --> 00:03:10,050
Well, it opens a file and it gives you a file pointer to it,
63
00:03:10,050 --> 00:03:14,000
so that you can then use that file pointer as an argument
64
00:03:14,000 --> 00:03:16,730
to any of the other file I/O functions.
65
00:03:16,730 --> 00:03:19,100
The most important thing to remember with fopen
66
00:03:19,100 --> 00:03:24,222
is that after you have opened the file or made a call like the one here,
67
00:03:24,222 --> 00:03:26,930
you need to check to make sure that the pointer that you got back
68
00:03:26,930 --> 00:03:28,320
is not equal to null.
69
00:03:28,320 --> 00:03:31,320
If you haven't watched the video on pointers, this might not make sense.
70
00:03:31,320 --> 00:03:35,639
But if you try and dereference a null pointer recall,
71
00:03:35,639 --> 00:03:38,180
your program will probably suffer a segmentation [INAUDIBLE].
72
00:03:38,180 --> 00:03:40,540
We want to make sure that we got a legitimate pointer back.
73
00:03:40,540 --> 00:03:43,665
The vast majority of the time we will have gotten a legitimate pointer back
74
00:03:43,665 --> 00:03:45,280
and it won't be a problem.
75
00:03:45,280 --> 00:03:46,760
>> So how do we make a call to fopen?
76
00:03:46,760 --> 00:03:48,051
It looks pretty much like this.
77
00:03:48,051 --> 00:03:52,690
File star ptr-- ptr being a generic name for file pointer-- fopen
78
00:03:52,690 --> 00:03:57,300
and we pass in two things, a file name and an operation we want to undertake.
79
00:03:57,300 --> 00:04:01,690
So we might have a call that looks like this-- file star ptr 1 equals fopen
80
00:04:01,690 --> 00:04:04,040
file1.txt.
81
00:04:04,040 --> 00:04:07,020
And the operation I've chosen is r.
82
00:04:07,020 --> 00:04:08,639
>> So what do you think r is here?
83
00:04:08,639 --> 00:04:11,180
What are the kinds of things we might be able to do to files?
84
00:04:11,180 --> 00:04:13,760
85
00:04:13,760 --> 00:04:17,500
So r is the operation that we choose when we want to read a file.
86
00:04:17,500 --> 00:04:20,260
So we would basically when we make a call like this
87
00:04:20,260 --> 00:04:25,440
be getting ourselves a file pointer such that we could then read information
88
00:04:25,440 --> 00:04:27,770
from file1.txt.
89
00:04:27,770 --> 00:04:34,190
>> Similarly, we could open file 2.txt for writing and so we can pass ptr2,
90
00:04:34,190 --> 00:04:38,210
the file pointer I've created here, as an argument to any function that
91
00:04:38,210 --> 00:04:40,080
writes information to a file.
92
00:04:40,080 --> 00:04:43,767
And similar to writing, there's also the option to append, a.
93
00:04:43,767 --> 00:04:45,600
The difference between writing and appending
94
00:04:45,600 --> 00:04:50,920
being that when you write to a file, if you make a call to fopen for writing
95
00:04:50,920 --> 00:04:54,761
and that file already exists, it's going to overwrite the entire file.
96
00:04:54,761 --> 00:04:56,510
It's going to start at the very beginning,
97
00:04:56,510 --> 00:04:58,820
deleting all the information that's already there.
98
00:04:58,820 --> 00:05:02,210
>> Whereas if you open it for appending, it will go to the end of the file
99
00:05:02,210 --> 00:05:04,340
if there's already text in it or information in it,
100
00:05:04,340 --> 00:05:06,040
and it will then start writing from there.
101
00:05:06,040 --> 00:05:08,570
So you won't lose any of the information you've done before.
102
00:05:08,570 --> 00:05:12,110
Whether you want to write or append sort of depends on the situation.
103
00:05:12,110 --> 00:05:16,840
But you'll probably know what the right operation is when the time comes.
104
00:05:16,840 --> 00:05:18,020
So that's fopen.
105
00:05:18,020 --> 00:05:18,930
>> What about fclose?
106
00:05:18,930 --> 00:05:21,600
Well, pretty simply, fclose just accepts the file pointer.
107
00:05:21,600 --> 00:05:24,000
And as you might expect, it closes that file.
108
00:05:24,000 --> 00:05:29,270
And once we've closed a file, we can't perform any more file I/O functions,
109
00:05:29,270 --> 00:05:31,420
reading or writing, on that file.
110
00:05:31,420 --> 00:05:36,444
We have to re-open the file another time in order
111
00:05:36,444 --> 00:05:38,610
to continue working with it using the I/O functions.
112
00:05:38,610 --> 00:05:41,520
So fclose means we're done working with this file.
113
00:05:41,520 --> 00:05:44,690
And all we need to pass in is the name of a file pointer.
114
00:05:44,690 --> 00:05:50,010
So on a couple slides ago, we fopened file 1 dot text for reading
115
00:05:50,010 --> 00:05:52,854
and we assigned that file pointer to ptr1.
116
00:05:52,854 --> 00:05:55,020
Now we've decided we're done reading from that file.
117
00:05:55,020 --> 00:05:56,561
We don't need to do any more with it.
118
00:05:56,561 --> 00:05:58,890
We can just fclose ptr1.
119
00:05:58,890 --> 00:06:01,950
And similarly, could we fclose the other ones.
120
00:06:01,950 --> 00:06:02,450
All right.
121
00:06:02,450 --> 00:06:03,700
So that's opening and closing.
122
00:06:03,700 --> 00:06:05,780
Those are the two basic starting operations.
123
00:06:05,780 --> 00:06:08,050
>> Now we want to actually do some interesting stuff,
124
00:06:08,050 --> 00:06:11,940
and the first function that we'll see that will do that is fgetc--
125
00:06:11,940 --> 00:06:14,110
file get a character.
126
00:06:14,110 --> 00:06:17,350
That's what fgetc generally would translate to.
127
00:06:17,350 --> 00:06:20,190
Its goal in life is to read the next character,
128
00:06:20,190 --> 00:06:22,079
or if this is your very first call to fgetc
129
00:06:22,079 --> 00:06:23,870
for a particular file, the first character.
130
00:06:23,870 --> 00:06:26,210
But then after that, you get the next one,
131
00:06:26,210 --> 00:06:31,500
the very next character of that file, and stores it in a character variable.
132
00:06:31,500 --> 00:06:34,490
As we've done here, char ch equals fgetc,
133
00:06:34,490 --> 00:06:36,389
pass in the name of a file pointer.
134
00:06:36,389 --> 00:06:38,180
Again, it's very important here to remember
135
00:06:38,180 --> 00:06:41,430
that in order to have this operation succeed,
136
00:06:41,430 --> 00:06:45,690
the file pointer itself must've been opened for reading.
137
00:06:45,690 --> 00:06:50,589
We can't read a character from a file pointer that we opened for writing.
138
00:06:50,589 --> 00:06:52,630
So that's one of the limitations of fopen, right?
139
00:06:52,630 --> 00:06:55,470
We have to restrict ourselves to only performing
140
00:06:55,470 --> 00:06:57,710
one operation with one file pointer.
141
00:06:57,710 --> 00:07:00,220
If we wanted to read and write from the same file,
142
00:07:00,220 --> 00:07:03,840
we would have open two separate file pointers to the same file--
143
00:07:03,840 --> 00:07:05,670
one for reading, one for writing.
144
00:07:05,670 --> 00:07:08,400
>> So again, the only reason I bring that up now is
145
00:07:08,400 --> 00:07:11,920
because if we're going to make a call to fgetc, that file pointer must've
146
00:07:11,920 --> 00:07:14,172
been opened for reading.
147
00:07:14,172 --> 00:07:15,880
And then pretty simply, all we need to do
148
00:07:15,880 --> 00:07:17,546
is pass in the name of the file pointer.
149
00:07:17,546 --> 00:07:21,060
So char ch equals fgetc ptr1.
150
00:07:21,060 --> 00:07:23,200
>> That's going to get us the next character--
151
00:07:23,200 --> 00:07:25,575
or again, if this is the first time we've made this call,
152
00:07:25,575 --> 00:07:29,750
the first character-- of whatever file is pointed to by ptr1.
153
00:07:29,750 --> 00:07:32,210
Recall that that was file 1 dot text.
154
00:07:32,210 --> 00:07:36,490
It'll get the first character of that and we'll store it in the variable ch.
155
00:07:36,490 --> 00:07:37,941
Pretty straightforward.
156
00:07:37,941 --> 00:07:40,190
So we've only looked at three functions and already we
157
00:07:40,190 --> 00:07:43,070
can do something pretty neat.
158
00:07:43,070 --> 00:07:46,320
>> So if we take this ability of getting a character
159
00:07:46,320 --> 00:07:48,943
and we loop it-- so we continue to get characters
160
00:07:48,943 --> 00:07:51,390
from a file over and over and over-- now we
161
00:07:51,390 --> 00:07:54,500
can read every single character of a file.
162
00:07:54,500 --> 00:07:58,670
And if we print every character immediately after we read it,
163
00:07:58,670 --> 00:08:01,960
we have now read from a file and printed its contents to the screen.
164
00:08:01,960 --> 00:08:05,610
We've effectively concatenated that file on the screen.
165
00:08:05,610 --> 00:08:09,670
And that's what the Linux command cat does.
166
00:08:09,670 --> 00:08:13,250
>> If you type cat in the file name, it will print out the entire contents
167
00:08:13,250 --> 00:08:15,160
of the file in your terminal window.
168
00:08:15,160 --> 00:08:19,010
And so this little loop here, only three lines of code,
169
00:08:19,010 --> 00:08:23,270
but it effectively duplicates the Linux command cat.
170
00:08:23,270 --> 00:08:25,210
So this syntax might look a little weird,
171
00:08:25,210 --> 00:08:26,670
but here's what's happening here.
172
00:08:26,670 --> 00:08:31,460
While ch equals fgetc, ptr is not equal to EOF-- it's a whole mouthful,
173
00:08:31,460 --> 00:08:34,669
but let's break it down just so it's clear on the syntax.
174
00:08:34,669 --> 00:08:37,169
I've consolidated it for the sake of space,
175
00:08:37,169 --> 00:08:39,049
although it's a little syntactically tricky.
176
00:08:39,049 --> 00:08:41,194
>> So this part in green right now, what is it doing?
177
00:08:41,194 --> 00:08:42,860
Well, that's just our fgetc call, right?
178
00:08:42,860 --> 00:08:44,530
We've seen that before.
179
00:08:44,530 --> 00:08:49,500
It's obtaining one character from the file.
180
00:08:49,500 --> 00:08:53,220
Then we compare that character against EOF.
181
00:08:53,220 --> 00:08:57,470
EOF is a special value that's defined in standard io.h, which
182
00:08:57,470 --> 00:08:59,390
is the end of file character.
183
00:08:59,390 --> 00:09:03,450
So basically what's going to happen is this loop will read a character,
184
00:09:03,450 --> 00:09:07,445
compare it to EOF, the end of file character.
185
00:09:07,445 --> 00:09:10,070
If they don't match, so we haven't reached the end of the file,
186
00:09:10,070 --> 00:09:11,490
we'll print that character out.
187
00:09:11,490 --> 00:09:13,740
Then we'll go back to the beginning of the loop again.
188
00:09:13,740 --> 00:09:18,310
We'll get a character, check against EOF, print it out, and so on
189
00:09:18,310 --> 00:09:21,094
and so on and so on, looping through in that way
190
00:09:21,094 --> 00:09:22,760
until we've reached the end of the file.
191
00:09:22,760 --> 00:09:24,593
And then by that point, we will have printed
192
00:09:24,593 --> 00:09:26,210
out the entire contents of the file.
193
00:09:26,210 --> 00:09:29,450
So again, we've only seen fopen, fclose, and fgetc
194
00:09:29,450 --> 00:09:34,950
and already we can duplicate a Linux terminal command.
195
00:09:34,950 --> 00:09:38,850
>> As I said at the beginning, we had fgetc and fputc,
196
00:09:38,850 --> 00:09:41,860
and fputc was the companion function of fgetc.
197
00:09:41,860 --> 00:09:44,880
And so, as you might imagine, it is the writing equivalent.
198
00:09:44,880 --> 00:09:49,440
It allows us to write a single character to a file.
199
00:09:49,440 --> 00:09:53,290
>> Again, the caveat being, just like it was with fgetc, the file
200
00:09:53,290 --> 00:09:56,660
that we're writing to must've been opened for writing or for appending.
201
00:09:56,660 --> 00:10:00,820
If we try and use fputc on a file that we've opened for reading,
202
00:10:00,820 --> 00:10:02,760
we're going to suffer a bit of a mistake.
203
00:10:02,760 --> 00:10:04,440
But the call is pretty simple.
204
00:10:04,440 --> 00:10:08,000
fputc capital A ptr2, all that's going to do is it's
205
00:10:08,000 --> 00:10:12,040
going to write the letter into A into file 2 dot
206
00:10:12,040 --> 00:10:14,760
text, which was the name of the file that we opened and assigned
207
00:10:14,760 --> 00:10:17,280
the pointer to ptr2.
208
00:10:17,280 --> 00:10:20,430
So we're going to write a capital A to file 2 dot text.
209
00:10:20,430 --> 00:10:24,592
And we'll write an exclamation point to file 3 dot
210
00:10:24,592 --> 00:10:27,330
text, which was pointed to by ptr3.
211
00:10:27,330 --> 00:10:29,730
So again, pretty straightforward here.
212
00:10:29,730 --> 00:10:32,727
>> But now we can do another thing.
213
00:10:32,727 --> 00:10:34,560
We have this example we were just going over
214
00:10:34,560 --> 00:10:38,950
about being able to replicate the cat Linux command, the one that prints out
215
00:10:38,950 --> 00:10:40,500
to the screen.
216
00:10:40,500 --> 00:10:43,510
Well, now that we have the ability to read characters from files
217
00:10:43,510 --> 00:10:46,590
and write characters to files, why don't we just substitute that
218
00:10:46,590 --> 00:10:50,720
call to printf with a call to fputc.
219
00:10:50,720 --> 00:10:54,090
>> And now we've duplicated cp, a very basic Linux command
220
00:10:54,090 --> 00:10:59,100
that we talked about way long ago in the Linux commands video.
221
00:10:59,100 --> 00:11:01,070
We've effectively duplicated that right here.
222
00:11:01,070 --> 00:11:04,790
We're reading a character and then we're writing that character to another file.
223
00:11:04,790 --> 00:11:07,660
Reading from one file, writing to another, over and over
224
00:11:07,660 --> 00:11:11,350
and over again until we hit EOF.
225
00:11:11,350 --> 00:11:14,250
We've got to the end of the file we're trying to copy from.
226
00:11:14,250 --> 00:11:18,500
And by that we'll have written all of the characters we need to the file
227
00:11:18,500 --> 00:11:19,500
that we're writing to.
228
00:11:19,500 --> 00:11:24,270
So this is cp, the Linux copy command.
229
00:11:24,270 --> 00:11:26,550
>> At the very beginning of this video, I had the caveat
230
00:11:26,550 --> 00:11:29,840
that we would talk a little bit about pointers.
231
00:11:29,840 --> 00:11:32,480
Here is specifically where we're going to talk about pointers
232
00:11:32,480 --> 00:11:34,800
in addition to file pointers.
233
00:11:34,800 --> 00:11:37,870
So this function looks kind of scary.
234
00:11:37,870 --> 00:11:39,120
It's got several parameters.
235
00:11:39,120 --> 00:11:40,430
There's a lot going on here.
236
00:11:40,430 --> 00:11:42,760
There's a lot of different colors and texts.
237
00:11:42,760 --> 00:11:47,100
But really, it's just the generic version of fgetc
238
00:11:47,100 --> 00:11:50,110
that allows us to get any amount of information.
239
00:11:50,110 --> 00:11:53,560
It can be a bit inefficient if we're getting characters one at a time,
240
00:11:53,560 --> 00:11:55,770
iterating through the file one character at a time.
241
00:11:55,770 --> 00:12:00,230
Wouldn't it be nicer to get 100 at a time or 500 at a time?
242
00:12:00,230 --> 00:12:03,250
>> Well, fread and its companion function fwrite, which we'll talk about
243
00:12:03,250 --> 00:12:05,490
in a second, allow us to do just that.
244
00:12:05,490 --> 00:12:08,480
We can read an arbitrary amount of information from a file
245
00:12:08,480 --> 00:12:10,290
and we store it somewhere temporarily.
246
00:12:10,290 --> 00:12:12,980
Instead of being able to just fit it in a single variable,
247
00:12:12,980 --> 00:12:15,790
we might need to store it in an array.
248
00:12:15,790 --> 00:12:19,980
And so, we pass in four arguments to fread-- a pointer
249
00:12:19,980 --> 00:12:23,940
to the location where we're going to store information,
250
00:12:23,940 --> 00:12:29,180
how large each unit of information will be, how many units of information
251
00:12:29,180 --> 00:12:35,192
we want to acquire, and from which file we want to get them.
252
00:12:35,192 --> 00:12:37,150
Probably best illustrated with an example here.
253
00:12:37,150 --> 00:12:41,640
So let's say that we declare an array of 10 integers.
254
00:12:41,640 --> 00:12:45,080
We've just declared on the stack arbitrarily int arr 10.
255
00:12:45,080 --> 00:12:46,970
So that's pretty straightforward.
256
00:12:46,970 --> 00:12:51,970
Now what we're doing though is the frecall is we're reading size of int
257
00:12:51,970 --> 00:12:54,180
times 10 bytes of information.
258
00:12:54,180 --> 00:12:59,040
Size of int being four-- that's the size of an integer in c.
259
00:12:59,040 --> 00:13:02,790
>> So what we're doing is we're reading 40 bytes worth of information
260
00:13:02,790 --> 00:13:05,850
from the file pointed to by ptr.
261
00:13:05,850 --> 00:13:08,600
And we're storing those 40 bytes somewhere
262
00:13:08,600 --> 00:13:12,080
where we have set aside 40 bytes worth of memory.
263
00:13:12,080 --> 00:13:15,970
Fortunately, we've already done that by declaring arr, that array right there.
264
00:13:15,970 --> 00:13:19,770
That is capable of holding 10 four-byte units.
265
00:13:19,770 --> 00:13:22,860
So in total, it can hold 40 bytes worth of information.
266
00:13:22,860 --> 00:13:26,540
And we are now reading 40 bytes of information from the file,
267
00:13:26,540 --> 00:13:30,330
and we're storing it in arr.
268
00:13:30,330 --> 00:13:35,470
>> Recall from the video on pointers that the name of an array, such as arr,
269
00:13:35,470 --> 00:13:38,370
is really just a pointer to its first element.
270
00:13:38,370 --> 00:13:43,680
So when we pass in arr there, we are, in fact, passing in a pointer.
271
00:13:43,680 --> 00:13:46,120
>> Similarly we can do this-- we don't necessarily
272
00:13:46,120 --> 00:13:51,200
need to save our buffer on the stack.
273
00:13:51,200 --> 00:13:54,990
We could also dynamically allocate a buffer like this, using malloc.
274
00:13:54,990 --> 00:13:57,340
Remember, when we dynamically allocate memory,
275
00:13:57,340 --> 00:14:00,550
we're saving it on the heap, not the stack.
276
00:14:00,550 --> 00:14:02,110
But it's still a buffer.
277
00:14:02,110 --> 00:14:06,810
>> It still, in this case, is holding 640 bytes of information
278
00:14:06,810 --> 00:14:09,230
because a double takes up eight bytes.
279
00:14:09,230 --> 00:14:11,570
And we're asking for 80 of them.
280
00:14:11,570 --> 00:14:13,770
We want to have space to hold 80 doubles.
281
00:14:13,770 --> 00:14:17,210
So 80 times 8 is 640 bytes information.
282
00:14:17,210 --> 00:14:21,880
And that call to fread is collecting 640 bytes of information
283
00:14:21,880 --> 00:14:27,770
from the file pointed to by ptr and storing it now in arr2.
284
00:14:27,770 --> 00:14:32,770
>> Now we can also treat fread just like a call to fgetc.
285
00:14:32,770 --> 00:14:37,140
In this case, we're just trying to get one character from the file.
286
00:14:37,140 --> 00:14:40,070
And we don't need an array to hold a character.
287
00:14:40,070 --> 00:14:43,170
We can just store it in a character variable.
288
00:14:43,170 --> 00:14:46,390
>> The catch, though, is that when we just have a variable,
289
00:14:46,390 --> 00:14:50,290
we need to pass in the address of that variable
290
00:14:50,290 --> 00:14:52,550
because recall that the first argument to fread
291
00:14:52,550 --> 00:14:59,210
is a pointer to the location and memory where we want to store the information.
292
00:14:59,210 --> 00:15:01,550
Again, the name of an array is a pointer.
293
00:15:01,550 --> 00:15:04,200
So we don't need to do ampersand array.
294
00:15:04,200 --> 00:15:07,270
But c, the character c here, is not an array.
295
00:15:07,270 --> 00:15:08,390
It's just a variable.
296
00:15:08,390 --> 00:15:11,840
And so we need to pass an ampersand c to indicate
297
00:15:11,840 --> 00:15:15,350
that that's the address where we want to store this one byte of information,
298
00:15:15,350 --> 00:15:20,479
this one character that we're collecting from ptr.
299
00:15:20,479 --> 00:15:22,270
Fwrite-- I'll go through this a little more
300
00:15:22,270 --> 00:15:25,440
quickly-- is pretty much the exact equivalent of fread
301
00:15:25,440 --> 00:15:27,720
except it's for writing instead of reading, just
302
00:15:27,720 --> 00:15:31,610
like the other-- we've had open and close, get a character,
303
00:15:31,610 --> 00:15:32,530
write a character.
304
00:15:32,530 --> 00:15:35,040
Now it's get arbitrary amount of information,
305
00:15:35,040 --> 00:15:37,170
right arbitrary amount of information.
306
00:15:37,170 --> 00:15:39,790
So just like before, we can have an array of 10 integers
307
00:15:39,790 --> 00:15:43,210
where we already have information stored, perhaps.
308
00:15:43,210 --> 00:15:46,580
>> It was probably some lines of code that should go between these two
309
00:15:46,580 --> 00:15:49,990
where I fill arr with something meaningful.
310
00:15:49,990 --> 00:15:51,880
I fill it with 10 different integers.
311
00:15:51,880 --> 00:15:54,920
And instead, what I'm doing is writing from arr
312
00:15:54,920 --> 00:15:58,600
and collecting the information from arr.
313
00:15:58,600 --> 00:16:02,390
And I'm taking that information and putting it into the file.
314
00:16:02,390 --> 00:16:05,410
>> So instead of it being from the file to the buffer,
315
00:16:05,410 --> 00:16:08,790
we're now going from the buffer to the file.
316
00:16:08,790 --> 00:16:10,580
So it's just the reverse.
317
00:16:10,580 --> 00:16:16,680
So again, just like before, we can also have a heap chunk of memory
318
00:16:16,680 --> 00:16:19,600
that we've dynamically allocated and read from that
319
00:16:19,600 --> 00:16:21,570
and write that to the file.
320
00:16:21,570 --> 00:16:24,900
>> And we also have a single variable capable of holding one byte
321
00:16:24,900 --> 00:16:27,200
of information, such as a character.
322
00:16:27,200 --> 00:16:29,830
But again, we need to pass in the address of that variable
323
00:16:29,830 --> 00:16:31,840
when we want to read from it.
324
00:16:31,840 --> 00:16:35,280
So we can write the information we find at that address
325
00:16:35,280 --> 00:16:39,050
to the file pointer, ptr.
326
00:16:39,050 --> 00:16:41,630
>> There's lots of other great file I/O functions
327
00:16:41,630 --> 00:16:44,650
that do various things besides the ones we've talked about today.
328
00:16:44,650 --> 00:16:46,450
A couple of the ones you might find useful
329
00:16:46,450 --> 00:16:50,840
are fgets and fputs, which are the equivalent
330
00:16:50,840 --> 00:16:56,190
of fgetc and fputc but for reading a single string from a file.
331
00:16:56,190 --> 00:16:59,020
Instead of a single character, it will read an entire string.
332
00:16:59,020 --> 00:17:02,940
fprintf, which basically allows you to use printf to write to file.
333
00:17:02,940 --> 00:17:05,619
So just like you can do the variable substitution using
334
00:17:05,619 --> 00:17:09,900
the placeholders percent i and percent d, and so on, with printf
335
00:17:09,900 --> 00:17:14,690
you can similarly take the printf string and print something
336
00:17:14,690 --> 00:17:16,800
like that to a file.
337
00:17:16,800 --> 00:17:20,720
>> fseek-- if you have a DVD player is the analogy I usually use here--
338
00:17:20,720 --> 00:17:23,109
is sort of like using your rewind and fast forward
339
00:17:23,109 --> 00:17:25,819
buttons to move around the movie.
340
00:17:25,819 --> 00:17:28,369
Similarly, you can move around the file.
341
00:17:28,369 --> 00:17:30,250
One of the things inside that file structure
342
00:17:30,250 --> 00:17:34,270
that c creates for you is an indicator of where you are in the file.
343
00:17:34,270 --> 00:17:36,420
Are you at the very beginning, at byte zero?
344
00:17:36,420 --> 00:17:39,290
Are you at byte 100, byte 1,000, and so on?
345
00:17:39,290 --> 00:17:44,340
You can use fseek to arbitrarily move that indicator forward or backward.
346
00:17:44,340 --> 00:17:46,744
>> And ftell, again similar to a DVD player,
347
00:17:46,744 --> 00:17:49,660
is like a little clock that tells you how many minutes and seconds you
348
00:17:49,660 --> 00:17:52,480
are into a particular movie.
349
00:17:52,480 --> 00:17:56,990
Similarly, ftell tells you how many bytes you are into the file.
350
00:17:56,990 --> 00:18:00,210
feof is a different version of detecting whether you've
351
00:18:00,210 --> 00:18:01,700
reached the end of the file.
352
00:18:01,700 --> 00:18:03,600
And ferror is a function that you can use
353
00:18:03,600 --> 00:18:06,959
to detect whether something has gone wrong working with a file.
354
00:18:06,959 --> 00:18:08,750
Again, this is just scratching the surface.
355
00:18:08,750 --> 00:18:12,730
There's still plenty more file I/O functions in the standard io.h.
356
00:18:12,730 --> 00:18:16,620
But this will probably get you started working with file pointers.
357
00:18:16,620 --> 00:18:17,640
I'm Doug Lloyd.
358
00:18:17,640 --> 00:18:19,750
This is cs50.
359
00:18:19,750 --> 00:18:21,669
30553
Can't find what you're looking for?
Get subtitles in any language from opensubtitles.com, and translate them here.