 All righty, welcome back to 105 light today. All right, so today will be fun. We will write a useful program and I will show you how we can use files so we don't have to type in like a thousand numbers every time and we will develop a fun program. This lecture will pretty much tie everything we learned together in the course and we can go ahead and make a useful program. So most files, or most programs, they use files for input. Any program you've used, you've probably never really typed input in the terminal in order to use it. Files will not be on the exam, they will not be testable. However, aside from opening files, it's pretty much our string review lecture so the rest will be the same. So we saw another way to get input like typing a command, but generally that you don't type that much when you type a command. So today we're going to write a program that uses files and it will be lots of fun. So you can open files and then you close them once you're done with them. So the API to open a file you can use is called fopen. It takes two arguments, the first being a path name so that is a string, so it's a normal C string that represents the file name you want to access. The second argument is the mode which is a string representing what you want to use the file for. So today we will use the mode as just the lowercase r which means we want to read the file, we want to get data from the file instead of getting it from the terminal. So that's what we'll use today and fopen returns a pointer to a file so similar to malloc it will return null if it is not a valid file and it has a failure. And then similarly to malloc, whenever we malloc something after we're done with it we're supposed to free it. Same thing with files as soon as we are done with the file we should close it and to do that we use the fclose function and it takes a pointer we got from the fopen function. So stream just the pointer returned from fopen so we have to remember to close it. So how to access all the data within the file? Well, we can use the get line function we saw when we were trying to get string input from the terminal. So previously we saw a get line it took a pointer to a pointer to a char so it can go ahead and do the malloc for you and it'll take a pointer to the size so it sets the size as well. And then the last argument I told you not to worry about I said that you could just set it to std in and that represents the terminal but now well we can open files so we can use the file pointer for get line instead of just making it the terminal. And if we remember what it is so again this is where it's good to have a review it returns the actual length of the string that it actually read in. So again if you initialize that buffer pointer the value of that buffer pointer to null then this mallocs for you otherwise if it's already allocated it will realloc for you you just have to make sure that the size p is accurate so you can reuse it over and over again if you want to and what it does it matches the entire line including white space and the ending new line character which is backslash n and then it returns the number of characters written to that buffer excluding the null byte so up to that ending new line terminator and like I said the last argument is stream it's a pointer to a file and we can actually use the pointer return by f open. So if we want to read every single line of a file called grades.txt how that would work is we could f open grades.txt open for reading we get a file pointer back we can check if it's null if it's null something went wrong so there's an error somewhere there's a failure so we can just exit our program and not bother continuing. After that I set up a pointer to a char and for string so that get line can go ahead and modify it I initialize it to null I set the size, initialize it to zero and then the length and initialize it to zero then I can call get line I give it the address of the string address of size so it can modify them just like scan f and then I give it the file argument I got from f open so now it's reading from that grades.txt file and then length will tell me the actual length of the string not including the null byte and I can just check if the length is less than or equal to zero that means I'm done with the file so I can just break out of this while true loop so I'm reading every single line of the file then after that get line mallocks for you so we had to remember to free our string and then we remember to close our file so any questions about this? Pretty much just given to you be the same as if you got every input string from the terminal except we wouldn't have the f open, the f close we would just use standard int so we've seen this before all right so let's develop something cooler today so we'll develop a grade calculator so I've done this, you've done this and you probably use like Excel or something like that but we'll go ahead and try it so I assume most of you have done like hey, what grade do I need to get on the final to get like a 75 or 85 or whatever, everyone's done that all right, did you write your own program to do it for you or would you use to do it? Would you use to do it like Excel or something like that or you calculated it? Yep, yeah you, yeah is Google the website? All right, well we can create stuff we know enough we could create our own in C so let's write a program so it will read that file called grades.txt is input because right now if you were to write this program right it would be scan F every time and it'd be really tedious to enter all your grades manually especially if we're developing this and testing it don't want to enter a billion things every time we test it like you did with your Sudoku solver that was probably a pain for you and you probably figured out some other way to do that not Sudoku, the crossword thing so we're going to expect nine lab grades, one midterm grade we're going to calculate our current course grade using the weights for this course so we can define the weights and everything and do all the calculations next we will determine what like our minimum grade in the course is going to be and maybe our current grade in the course and then the maximum grade we could get and then we'll finish off by like calculating what mark we need to get on the final for some target exam grades so rest of this is just going to be fun coding whoops, fun coding and we can fun coding, interrupt me at any time and we can ask questions and go through this so here is my grades.txt file so remember your lab grades are all out of 10 right so here I just made up some so I got 10 on lab one, nine on lab two 10 on lab three, four on lab, sorry nine on lab four, da da da, so on I didn't do that well on lab eight and I put a negative one for lab nine to represent, I don't know, maybe I petitioned it or something like that, that represents the weight of the lab goes to the final so that's probably what happens if you have a petition so I'll take care of that and then the last line there is my grade on the midterm which is out of 75 so we'll use that to calculate everything so here is our program so we're going to open that grades.txt file and then we can use get line and we can go through every single line so if I wanted to get my grades and convert it to like a double so I can actually calculate it well anyone remember what that function is called? A2F, so A2F takes a string, gives us back a double so every time I read a line it gets populated in that string pointer I can go ahead and use it I can use A2F to give me my grade so now it's that string gets converted to a double now it is a double and I can use it for calculations so I probably want to read in all my grades, right so what it makes, I could like I know I kind of have to count because I need to know, you know the first one is lab one, second one's lab two third one's lab three so maybe I create an int called i that is keeping track of like what grade this is in reference to so maybe I write like if i is zero well okay now I have to keep track of my like lab one grade, my lab two grade so I can set that equal to lab one grade equals grade and then else if i is one then that is my lab two grade is this smart, should I do this for all nine labs? Probably not, what should I do instead? Whoops, an array, right so I should probably use an array so maybe I decide to do double lab grades oh I need to know the length, okay well maybe I want to use it in other functions too so let's, I already started main a little bit to have the length of the lab so it's nine and then well I'll put just all the reading of the grades in that read grades function so maybe I create my array here so double what's it, lab grades and the length of that is going to be equal to labs length and don't really have to initialize it or anything like that because I'm going to set all the values in this read grades function so in read grades I probably want to give it lab grades and lab length just to be general just in case, you know I want to use it for another course that has a different number of labs so if I change that in read grades I have to remember to actually take the array which will decay to a pointer but I don't care and the length of the labs so I'll do something like that so I can have it as an argument so I can go ahead and change them so everyone okay with that so I'm going to actually populate this array here so I had a good idea before but I'm going to have it just change an array instead and index zero will be my lab one grade so there'll be zero indexed so I can just check if I is less than the labs length then the lab grade for I is equal to the grade right so that should populate the first nine grades right so that should be the nine grades in the file I can double check so I can just make sure I'm sane so we can just write some code just to check it for us so let's make sure that we read using our format specifier we read the lab grades properly so we can compile that don't have any errors so that's good run our program and we can see that hey we did read all of our grades right so everything is fine we populated that big array so last thing I need to do is read the midterm grade because that was the last thing right so maybe I want to go ahead and change and like define my variable in main so maybe I'll call it double midterm grade and don't have to initialize it because I'm going to set it in this read grades function so if I want to change the value just like scan F I have to give it the address of the midterm grade right so I give it the address of the midterm grade and then in this read grades function I have to do double pointer to midterm grade and then so yeah yeah so right now so the comment was right now after I read in all the lab grades I keep on reading more contents of the file so maybe I don't want to do that maybe I want to end early and break out of the loop or something like that yeah yeah so for this I'm not going to bother error checking so much I'm just assuming that nine lab grades and then my midterm grade at the end so I can just do else so if we're done all the lab grades the next one could be to set the midterm grade so I have to dereference it since it's given by a pointer and I could set it to grade like that and then that sets all of my grades now but you're right if I wanted to be more general I might want to add error checking because right now if I add more stuff to the file you'll just read it and well in this case it would update midterm grade over and over again so maybe I just have a sanity check here so like I read everything if I does not equal to it should be 10 right I read 10 grades maybe I have some error checking so exit failure maybe I do something like that so I just make sure that I read 10 lines all the time otherwise I'll give an error and then that way if I do something silly like I don't know I put in like hamburger I don't know why that's in my mind right now but if I put in hamburger and run it it says unexpected file format because I read too much right so that could be one check I have the other check I won't put in yet but like if you only have like one grade in your file it should probably say hey well actually this would also do the same thing and give you an expected file format so in real programs I probably want to error check things but since I'm providing input right now I won't bother so now this fills all of my grades right so now this array is filled and my midterm grade is filled so any questions about that all right so now we can just do the fun part well fun part ish and do the calculations so other things we need to know the weights for everything right so like we probably want like lab weights so we have the lab weights and we could initialize them too so for in i equals zero i is less than labs length plus plus i and then for the weight of the lab so if i is less than three then the weight of the lab is was it 2% right and then else if the next three labs the weight was 3% and then for the last three labs the weight was 5% right so that initializes its weight and then what else I might be thinking it's like oh well maybe I have to know what every lab is out of right so it's like double lab totals labs length so if you see something like that yeah those three things are all related right and like they all represent a lab but if you wanna calculate the like actual grade for the lab you have to make sure that's the same index for all of them because you know you've spread the data out across three arrays but they're all related to it so we should probably create a struct that probably has your grade the weight and what it's out of so maybe I want to change my code so this is something you do just to make it easier to read and it will also help us when we write some functions and in this case it'll just save us one line but maybe we want to make a struct for that so I can say type def struct I'll call it assessment maybe as a general name and it will have a weight it will have a grade and it will have a total out of and maybe I wanna call it assessment T so that look more or less okay all right well now this is the part of coding so generally whatever you write your program the first time you figure out how to do it and then you throw it away and you write it better the second time so this I decided to use a struct so now I have to rewrite this function again because now it's not gonna use an array because now I have a struct so instead of that I can have an assessment an array of assessments called labs and it's labs length instead of having all these different things but now I'm gonna then I get errors so now I have to change my code right so I have to change labs I oops and in this case I would just use dot weight because it is not a pointer so I could do this so now that's the weight of all the labs right all right so now I have to change this so for my read grades it has to take a lab oh and I need to do the midterm too so I need to create an assessment called a midterm so this is going so I'm going to rewrite the arguments for that but I know I should just give it the argument address of midterm because I want it to change it and then the array labs so let's go back up here and change everything so instead of being doubles now we have an array of assessments called labs and then we have instead of a double midterm grade we have a pointer to an assessment called the midterm all right so now the only thing we have to change here now is instead of changing lab grades we have to change labs I dot grade and then for the midterm we'd have to dereference in everything it's an assessment pointer so I could write it like this so I could dereference the midterm to get the assessment and then do dot grade but we know that that's ugly and we can use the arrow thing instead so instead of doing that I can do that boom all right so we're good so now I changed everything to structs and I set all of the grades there okay cool so now I have weights for all the labs I can delete this and then maybe I also want to set the weight for the midterm so the midterm dot weight the midterm was worth 30 right pretty sure it was worth 30 you can double check I'm like 99% sure it was worth 30% so that is all of the weights maybe for the midterm I want to also set it's total here so the midterm was out of 75 and then all of the labs were out of 10 so maybe here I set labs dot total equal to 10 all right all right so now we have all of the weights for all the labs and the midterm all of the totals for all of them and then all the grades that we read in from the final or from the file right so now we're ready to calculate so if I want to calculate my course grade course grade let's start it off as zero so how you generally develop this is like okay well I probably need to like figure out what I got on the lab and what percent of that contributes to the grade so for I equals zero I is less than labs length plus plus I so I do course grade plus equals to like the labs the weight times the times my grade divided by whatever I got on that lab right total so for instance if the labs were 2% I want to calculate like what of that 2% did I get so this is the grade divided by total is like the proportion of the grade I got and then I times it by weight so if I got 10 out of 10 well this would be one and if the weight if it was worth 2% well then the weights two I got all of it and it contributes 2% to my course grade right and then if I wanted to like get my midterm contribution to my mark I'd have to write out that whole thing again right but this is where it's nice that I actually wrote a I actually have a struct so I could write a little helper function this it'll save me one line of code but whatever so I could just calculate my course grade compute course grade for an assessment right so I could try and generalize it a little bit whoa that's a lot of text okay that was on my clipboard for whatever reason so instead of doing this for a specific lab I can do it for an assessment instead so instead of having labs I labs I come on so instead of having labs I I could have was it assessment P do that so I could just go ahead and compute whatever the assessment goes toward my grade instead of an individual lab and then I can reuse that so I can just compute the midterm with that this is probably over engineered but whatever so I could do course grade plus equals compute course grade for the midterm and then I could change this a little bit so I compute course grade for the address of labs I instead of that so now it looks a bit better right maybe all right so any questions about that so that's our course grade that is our course grade right now yeah yeah so yeah so at that point I could just have an array of all assessments and then I have one for loop so I could do that instead and then maybe I add to the struct if I actually cared which is which I add a name to the struct so I get the name lots of possibilities yeah yeah so the question is is there a dictionary built in dictionary in C like there is in Python the answer is no so yeah so C you get nothing so if you want a list in C it's link list it's all on you other little thing I could do is I also have to check if the labs I grade so maybe this is where it's important so if remember we if we set the grade to be like negative that means that we're shifting our grade to the final so if the lab grade is less than one then I want to actually shift it to the final otherwise I actually want it to contribute to my course grade so I need another variable called the final weight and by default it is 40% so if I missed a lab and it was properly petitioned then the weight of my final just goes up by that labs weight okay so that is my current course grade right yeah so we set up all the lab weights up there yeah yeah so if we petitioned like lab if we petitioned lab nine then that 5% gets shifted to the final yeah so that lab weight technically becomes zero but here since we go in the else branch we don't compute or we go in the if branch we don't compute it yeah yeah so if we wanted to we could see if we skipped it says weight to zero and just go over all them lots of different ways to tackle it okay so that's our course grade so we can see what our current grade is current grade so remember our format specifiers so if I want to print off the value of a double I could use that so this is my current like grade in the course but that's technically like the lowest I can get if I want to like put it as a percent then it is my course grade and that's out of 100 minus whatever the weight of my final is so that's like cumulatively everything else and then to get that into a percent it is just 100 times that so let's build this and run it so now my current grade in the course I know I have a 76.4 right anyone remember oh that's a percent right anyone remember what I have to do if I want to print an actual percent character so like backslash percent no right because percent's like a special format specifier so like we have to escape characters so like backslash n is to get a new line character that's like any c thing percent only means something in like print f because it's a format specifier so if we want to print a literal a literal percent character we have to just say percent percent so two percent that gets us a literal percent so now if we build it it should look a bit better so it says now our current grade is 76.4 percent all right we're good all right so maybe I want some other info so the lowest grade I can possibly get in the course if I don't even write the final and you should still show up to the final but you know we're just doing this lowest possible grade would be let's do that again percent percent so lowest possible grade would be like my current course grade right that's like what I have out of everything and then let's do our highest if we got a hundred percent on the exam so our highest is just the course grade plus the weight of the final so let's see how we are with this so our lowest possible grade is 42 so we should probably show up to the exam and then our highest is probably 87 so we can't get any higher than that even if we get a hundred on the exam I guess minus bonus marks but I don't think there is so maybe we want to calculate sorry yeah so let's calculate a whole bunch of targets so let's just define an array called targets and this is going to be like our target grade in the course so some good targets so minimum to pass is 50 pass alright 60 or C's get degrees that's like a 60 what are the targets do we want let's see like a 75 yeah 85 alright and any other targets or does that look alright that's good alright so that's good so let's have targets length so that would be array length of targets alright so for i equals zero let's compute what we need for every target targets length plus i so uh let's print so if our target is let's say our target if we want to print it lf and then targets i so we're going to compute our current target grade right and i know that i'm just going to print different messages depending on the target so so to figure out what i need to get for the target grade so i need to know what i like the final weighted grade needs to be right so that is whatever my target my current target is minus whatever i have currently in the grade is like the contribution i need from the final to get that mark right so that is the contribution i need to from the final to get that mark so in order to figure out how like what i actually need to get on the final is just simply anyone want to tell me yeah so that's like the weighted i need to get on the final and then just divide that by the final weight and then times a hundred right so i need to get let's see percent so that would just be 100 times the final weighted divided by the final weight right so if i build that i run that hey seems to work so my highest possible grade is 84 to get a 50 percent i need to get a 17.8 on the final to get a 60 i need a 40 to get a 75 i need a 73 to get an 85 i need a 95 uh yeah we could write some other things so like i don't know let's say my target was 40 we might want to test our program a little bit so if my target's 40 and it's lower than the possible grade it says i need to get a negative 4 percent so that's a bit weird so maybe i want to change this to like if the final weighted is less than or equal to zero i want to print you already got that or uh don't do that whoops so compile that so now it says to get a 40 i stay home yeah yeah so let's go the other extreme so they're trying to aim for 100 or even slightly higher than their highest possible grade so if i was aiming for like an 87.1 that's technically impossible right because right now if i run that it'll probably say i need 102 percent to get it so maybe i just say uh else if the final weighted is actually greater than the weight of the final then just tell them um no they have to show i'll just say uh impossible so now that should cover all the cases so now it says that's impossible right and if i said it was if i wanted to get like the highest possible grade i could in the course it should say i just need to get a hundred percent boom and then if i want to get even 87.1 it says it's impossible all right any other questions about this it's a useful program right we wrote our first useful program we don't have to type and scan f all the time isn't it great it's a bit of a pain in C but hey we can do it all right any questions at all or anything regarding the course or anything do you want me to definitely touch on Friday we're going to wrap up the course on Friday last lecture yay yeah where i'd want to like read from a file instead of the terminal any common things um how many programs have you run where you run them through the terminal probably zero right most of the files or most programs use files so like pretty much a hundred percent of the programs will use files like your web browser that you that opens a lot of files um anything that reads data uses files pretty much literally everything uses files so this is going to be way more common than scan f will ever be um like in order to teach this course i had to remember how to use scan f so i have not used scan f i've used files uh any other questions nope so this would not be but like the only things we learned today that didn't really matter was like f open and f close so don't have to worry about those but everything else we did today we we learned in the course we should know how to do so yeah won't ask anything about f open or f close but i mean this is how programs actually work like 99.9 percent of programs use files instead of scan f yeah so the question is can i show what the file structure is so um this sorry where did it go so this file pointer so um it is technically you don't get to know that the struct so in this it will might tell me so it says it's a struct i o file but it's not actually defined anywhere because the actual contents of that struct will change depending on if i'm running this on windows if i'm running it on mac if i'm running it on linux so they intentionally do not let you look at that struct because it's going to change depending on what operating system you have but if they give it to you as a pointer right they just give you an address it doesn't matter so that's why they do it like that yep so yeah so the question is why do i have to close the file after i open it so the operating system when you open a file the operating system is going to know you have that file open like you're using it and closing it just like with memory just says i'm done with it so it's just good practice like it's good practice to free when you're done with it if my if my program like exits it'll close all the files for you but like it'll also free everything for you so just the same idea as with mallocking after you're done with it just free it same thing with files after you're done with it just close it yeah yeah so for files like why do i have to open it so it will kind of eventually read memory that you'll have to wait till the operating system forced but like the open i have to tell it what file i want to open so like if i malloc i don't have to tell it a name or anything right it's just allocating memory but in the case of files there's tons of files on my machine right like i could create as many files as i want i have to tell it what file to open so if i tell it what file it's accessing the operating system is going to have to keep track of what file i'm accessing and keep track of things like that like how far i've read into the file and then close just means operating system i'm done with it don't you don't have to track anything anymore so all right any other fun things we can do although this was kind of fun it's our first actual program i feel better about this program or if you want you can come play with it and figure out what your grades will be without having to rewrite it if you really want because if i want let's see i could play with my grades right i wrote it generally all i have to do is change the file and then my output's going to change so let's say i did like horrible in the midterm i got a 45 hopefully it changed it it should change my input because i'm just reading from this file right i don't have to write anything don't have to rewrite it and now yeah suddenly i'm going to have to work a lot harder to get 75 and 85 is now out of the realm of possibility if i've messed up the midterm yeah so yeah edge case if everything goes to the final yeah i think i saved it so if everything goes to the final that means the final would be worth okay and this actually wouldn't happen by the way that means the final would be worth what 70% so yeah so it's worth 70% because that's a jump here so it seems to work i got a 60% on the midterm but it doesn't matter i can make it all up on the final because it's worth 70% of my grade hopefully this is not um not the case for you all right any other questions or other fun stuff we can do i mean this was ripping all right so i'll just hang around then if you want to for some reason figure out your own grade feel free uh but just remember pulling for you we're all in this together