User Tools

Site Tools


haas:summer2017:cprog:projects:sfa0

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Next revision
Previous revision
haas:summer2017:cprog:projects:sfa0 [2017/07/20 14:29] – created wedgehaas:summer2017:cprog:projects:sfa0 [2017/07/26 15:59] (current) – [Methods of file access] wedge
Line 58: Line 58:
     * int my_array[4];     * int my_array[4];
   * but we cannot just have an "array":   * but we cannot just have an "array":
-    * my_array[4]; // an array of WHAT? The compiler will yell.+    * my_array[4]; ... an array of WHAT? The compiler will yell.
  
 Same thing with structures, only structures (or the **struct** keyword) let us pack in any combination of types (including arrays and structs). Same thing with structures, only structures (or the **struct** keyword) let us pack in any combination of types (including arrays and structs).
Line 132: Line 132:
 </code> </code>
  
-The structure pointer just makes the code look cleaner, so it is the recommended way of accessing elements (when the structured variable has been declared as a pointer).+The structure pointer just makes the code look cleaner, so it is the recommended way of accessing elements (when the structured variable has been declared as a pointer, that is).
  
-=====What is a function?===== +====Files==== 
-In a wayfunctions are like evolved variables - they have a data (return) typethey are given a symbolic name, and they contain information.+While information is unique down to bitsand the computer accesses data in units of bytes, information is often packaged and made available to us in containers known as **files**.
  
-Functions are like sub-programs - small subroutines that perform some specific task that is relevant to the larger program (or other functions).+Like a structure, there is no stipulation on what sort of data goes in a generic file; although like an array, a file can be accessed as a sequence of bytes, from a starting index or offset.
  
-Soinstead of storing some numeric value like variables do, functions contain a group of instructions which can give way to a final numeric value (or values).+C and other production-oriented programming languages provide file I/O functionality, which can greatly increase the usability of the programs we write.
  
-That group of functionswhich performs a taskis given a name. That will allow your function to be called from wherever it is neededand can be used to prevent the needless duplication of code to do some common task a number of times.+From reading in external data sets to loading/storing pertinent data in specific patterns (ie formats)file accesslike pointers and memory accesscontribute to the power and influence of C (and its derivatives).
  
-The data type assigned to the function correlates to the //return value// - the data which is returned from a function as a result of its actions.+====Point of access: pointer or descriptor==== 
 +C provides two streamlined ways of accessing a file, and various groups of C library functions to access in conformance with the access method:
  
-====Why should I use functions?==== +  FILE pointers (**<nowiki>FILE *</nowiki>**) 
-As I've said, the absolute minimal number of functions required in a C program is 1: **main()**+  file descriptors (**int**)
  
-**main()** is regular ordinary function with one notable difference-- it is the one function the system looks for to start executing your program. Aside from that, it is as real and normal regular function as any other you create.+FILE pointers are just that: pointer to a special type of struct, which provides an interface to the file's contents.
  
-Why can't I just put everything in **main()**?+File descriptors are perhaps slightly more polished, abstracting away more of the low-level details of file access, instead creating an interface around a unique numeric value (somewhat like a "take a number" approach to service).
  
-Nothing is preventing you from exclusively using **main()**. However, your program may become unnecessarily long and difficult to debug should there be problems. Functions allow you to modularize your code- so you can break it up into little pieces. Not only can this lead to increased efficiency from less duplicated codebut your code will be significantly more organized.+For the purposes of this project and this coursewe will be focusing on file access via the use of FILE pointers. Just be aware that there are corresponding functions that make use of the file descriptor concept.
  
-For this courseI will expect you to use functions from this point on.+====Methods of file access==== 
 +To interact with a filewe must do so in accordance with a fixed set of actions (which are woven into the various C library file functions), some common ones of which are:
  
-====Where do I put functions in my program?==== +  * create 
-There are two aspects to functions, which are concepts shared with that of variables:+  * open 
 +  * read 
 +  * write 
 +  * append 
 +  * execute 
 +  * remove 
 +  * close
  
-  * declaration / prototyping +We'll be specifically focusing on opening, reading, writing, and closing files for this project.
-  * definition / initialization+
  
-In order to avoid compiler errors, and allow your code to work seamlessly with your functionsANY functions must be **declared** prior to any other function that makes use of them.+A point of distinction on "write" vs. "append": when you open a file for writingyou start from its beginning, overwriting and existing content; when you open for appendingyou start at its end, adding to (appending) existing content.
  
-Once the function is declared, the definition could then immediately take place (just as is the case with variables where we can initialize them), or you can defer definition to later.+====Declaring a FILE pointer==== 
 +To access a file, we must first have an instance of the file access interface to interact with. As indicated abovethis comes in the form of a FILE pointer, which for us will take the form of a variable:
  
-====When do I use functions?==== +<code c> 
-Programming is more of an art, so there is no clear-cut answer to this. However, here are a couple of guidelines you should keep in mind as good indications for needing a function:+FILE *fp  NULL; 
 +</code>
  
-  * you find yourself duplicating section of code two or more times. +There's nothing magical about the name; you may find "fp" being common variable name used for file pointers (fp = file pointer), but in the case of multiple file access, even seeing names like **in**, **out**, **inp**, **outp** is not uncommon. Again, the idea is to make your variable names descriptive enough so as to be a form of documentation in and of themselves.
-  your program solves a problem that can be broken up into independent stepsor operations. +
-  * the task or subtask you are implementing is longer than you have lines for on your terminal (this one comes with practice).+
  
-Some thoughts to consider when implementing functions:+====Opening a file==== 
 +To gain access to a file, we must formally OPEN it. The C library provides us with the **fopen()** function, which takes 2 arguments: 
 +  - PATH and name of the file (location) 
 +  - means of access (mode)
  
-  * a function typically performs a single task (such as taking input from the keyboard, OR processing something, OR displaying output). Don't try to do all of this in a single function, else you may end up defeating the purpose of using a function in the first placeSometimes you will want to mix things togetherbut at this stage, the aim is to develop good programming habits and an aesthetic for effective function use. +If no extensive path information is given, the program knows to look in the current working directoryFor portabilityany program seeing wider usage should be referencing an absolute path to reduce potential access complications.
-  * if you have similar, but not exactly identical, tasks to implement, see if your resulting function can't somehow be created to accommodate some number of them.+
  
-====How do I implement a funtion?==== +As for modes, there are 3 main modes we will be focusing on (there are other combinations, but generally are utilized in more advanced usage; just stick with these for now):
-A function consists of the following:+
  
-  * **__return type__**this can be any valid data type available to you in C, with the addition of **void**.+  * read: "r" 
 +  write: "w" 
 +  append"a"
  
-  * **__function name__**: the identifier for the function. Just as you've given names to your variables in order to access themthe function name allows you to identify the function and to call it from within your program.+Both the location and mode of the parameters are strings (arrays of charwith a terminating NULL terminator).
  
-  * **__parameters__**: these are pieces of information that are sent into your function for processing. Parameters are like local copies of variables you send in. And like variables of local scopethey don't exist outside their particular block of code.+If we wanted to open the file "output.txt" for writingwe would say:
  
-  * **__function body__**: the bulk of the function. This is the code you implement that accomplishes a particular task.+<code c> 
 +    fopen("output.txt", "w"); 
 +</code>
  
-====Function vs. Procedure====+**fopen()** returns a FILE pointer, so in order to make use of it, we need to connect its return value with our FILE pointer, as follows:
  
-Technically, a function returns exactly 1 value (corresponding to the return statement that is placed at the end)A procedure can "return2 or more values. I say "return", because you are only allowed the use of one return statement per function body, and it must be at the end of the program flow of that subroutine.+<code c> 
 +    fp = fopen("output.txt""w"); 
 +</code>
  
-But what if we want to return nothing? Well, even though it is possible with the use of the **void** data type, it is generally not good practice. If you are not returning meaningful value, you should at least return an exiting value signifying success or failure.+If there was a problem opening the file by the requested mode, **fopen()** returns **NULL** (great thing to check for to ensure if we were successful or not).
  
-For example:+====Writing to a file====
  
-  * If your function was successfulyou should return a 0. +At this pointwe can write (or outputto this "output.txt" file, via our **fp** variable.
-  * If your function was unsuccessful, you should return a non-zero value, such as 1. (You can setup different non-zero values to signify different levels of error within your program).+
  
-Ok, so if we're allowed only one return statementhow can we return more than one value? The simple answer is- we cheat. By employing the use of pointers, we can perform what is called passing parameter by reference or address; instead of making a local copy, we actually obtain direct access to the memory location of that parameter, so when we make modifications, the changes remain even outside the function.+Output can be done with a familiar function we've been using all along: **fprintf()**, the first argument of which is a **FILE pointer**.
  
-So, by using pointers in our function's parameter list, we can simulate the notion of //procedures//+This would write "helloworld!\n" to our output file:
- +
-====Pass by value / Pass by address==== +
-In many programming text books, you will see reference to "pass by value" and "pass by reference". As it turns outin C, instead of pass by "reference", we have "pass by address"+
- +
-===Pass by value=== +
-When we pass by value, a copy of a variable is made, and is entirely independent (aside from the initial value of the data) of the source data. +
- +
-Any changes made to that variable within the function remain within the function-- no changes are reflected back in the original variable (unless otherwise manipulated). +
- +
-Passing by value is easy, we just declare variables within the parenthesis as normal:+
  
 <code c> <code c>
-int funcname(int var1int var2) +    fprintf(fp"hello, world!\n");
-{+
 </code> </code>
  
-In this case, the function **funcname** has 2 parameters, both of type **int**: var1 and var2+This is why I've been having us use **fprintf()** all along (instead of the **printf()** shortcut), so that the interface would already be familiar to you, and for you to conceptually see that outputting to the screen and outputting to a file are indistinguishable (because they are the same thing to the operating system: EVERYTHING is a file). 
 + 
 +====Reading from a file==== 
 +If we had instead opened our file for reading, we could read from it the same way we obtain keyboard input: **fscanf()**
  
-So, to **call** our function //funcname//:+For examplethis will read an unsigned short integer from the file pointed to by our FILE pointer (but ONLY if we opened it for reading):
  
 <code c> <code c>
-result = funcname(value1value2);+    fscanf(fp"%hu", &value);
 </code> </code>
  
-In this case**value1** gets sent in as the first parameter (and **var1** is declared and set equal to **value1**). Similar case for **value2**/**var2**.+====When the data ends: End of File checking==== 
 +When you are reading from a file and have exhausted its contents, the last character read from the file should be a special EOF symbol, and various other status bits are likely flipped in our FILE pointered struct to indicate that the end of file has been reached.
  
-===Pass by address=== +A good function to use is **feof()**, which takes a FILE pointer to check, and it will return a nonzero value if the end of file has been reached (great for using in selection statements or loops as combined check and termination combo!)
-When we pass by address, we use pointers to connect the function parameters to the actual memory space of a variable outside the function.+
  
-We do this by using the <nowiki>*</nowiki> and <nowiki>&</nowiki> pointer operators.+====Responsible file access==== 
 +Doing any digging you will see that it is entirely within our ability to open files for reading AND writing; I would caution you against this, because there are issues of data corruption and/or data loss at stake if we're not careful. For now, just focus on ONE action, the current intended action. If you need to switch back and forth, **close** the file and open it in the new desired mode. That will maintain the integrity of your data, especially when first learning (as we are now). In time when the complexity/demands of your programs calls for it, you can start to dabble and experiment with such functionality.
  
-A sample function declaration:+====closing a file==== 
 +Just as you are the highly responsible and respectful individual when returning rented VHS tapes to the rental store, or loaned cassettes or 8-tracks from the library (WHAT?), you have been kind and put the media in a state where it is no longer connected to your processing environment (you ejected it).
  
-<code c> +In the case of file access in C, that means remembering to **CLOSE** the file when we are done with itand that can be done with the **fclose()** function:
-int funcname(int *val1int *val2) +
-+
-</code> +
- +
-And then, to call this function, we do as follows:+
  
 <code c> <code c>
-result = funcname(&in1, &in2);+    fclose(fp);
 </code> </code>
 +
 +Having a file open allocates additional resources. Forgetting to close the file when done keeps those resources in use. Granted, while they will be deallocated on program exit (and our programs are all quick to execute at this point), it is a good habit to perform proper file management by closing files when we are done with them, so when our programs are more complex, that won't be a bug that needs tracking down.
  
 =====Program===== =====Program=====
-Using functions, we are going to implement the classic "Fox, Chicken, Corn" game.+For this projectmixing together all the skills we've previously learned and just learned is in order.
  
-====Rules==== +In **/var/public/cprog/sfa0/** is a file called **datafile.db**, which contains several records of the following format:
-The premise of this game involves a farmer with the above-mentioned items that needs to transport them across a stream in a boat.+
  
-The boat, unfortunately, is large enough only for the farmer and one item.+<code> 
 +NAME     # 1S 1T 2S 2T 3S 3T ... #S #T 
 +</code>
  
-There exists the following relationship with the items:+Where:
  
-  * The fox, left alone with the chicken, will eat the chicken. +  * the first 8 characters correspond to an ALL UPPERCASE name of an individual (name doesn't have to occupy all 8 charactersbut will not exceed 8 characters) 
-  * The chickenleft alone with the corn, will eat the corn.+  * the # refers to the number of score pairs associated with that individual (will not exceed 127) 
 +  * then a set of number pairs (labeled S and Tfor Score and Total)that are associated with that individual (individual numbers will not exceed 65535)
  
-So one needs to craft careful means of transporting all these items without losing any of them.+It will be your task to write program that: 
 +  * opens that file: 
 +    * via its absolute path 
 +    * for reading 
 +  * load the data for each line into a custom struct you've made that contains the following elements: 
 +    * place to store the person's name 
 +      * store the person's name with a leading Uppercase, but all other characters represented in lowercase; for example: MOANA becomes Moana 
 +    * array to store the person's scores 
 +    * array to store the corresponding totals for each score 
 +    * array to store the average of each score:total pair  
 +    * element to store the tally of all the scores 
 +    * element to store the tally of all the totals 
 +    * element to store the average of the averages 
 +    * element to store the average of the tallied scores:tallied totals 
 +  * opens the local file: **sfa0.out** for **writing** 
 +  * stores the processed results you have in memory (in your structs), in the following format:
  
-====Programming Considerations====+<code> 
 +Name:#:scoreTally:scoreTotal:avgofAverages:averageofTallies:#s,#t;...;2s,2t;1s,1t 
 +</code>
  
-  * Your program should display the current scene (using textual characters) +Of particular note:
-    * visualize the location of the farmer, fox, chicken, corn, river, and boat +
-  * Do not worry about "clearing the screen"; just redraw the scene after each round +
-  * At the start of the game, prompt the user for a display of the game rules and instructions +
-  * At the conclusion of the game: +
-    * display the total number of turns taken before the game reached its end (successful or otherwise) state +
-    * prompt the user if they would like to play again +
-  * Create, populate, and use the following functions: +
-    * **intro();** - a function to display the instructions for the game +
-    * **display();** - a function to display the current playing field +
-    * **chkmove();** - a function called after each turn to determine if the game is over (user chooses poorly), or if the game is still in session +
-  * There are to be **NO** global variables used in your program. Pass any needed variables by value or address between functions +
-  * Of your variables and functions, you are to pass **at least** one variable by address and manipulate it within the called function (so the changed value is reflected outside the called function as well). +
-  * You are also to pass **at least** one variable by value and utilize it with the called function. +
-  * Implement your code in a single .c file- **fcc0.c**+
  
-=====Programming Assumptions===== +  * Name of individual is that changed Uppercase lead-in letter followed by all lowercase 
-A couple things to keep in mind:+  * category fields are separated by colons ':' 
 +  * averages should be truncated 2 places after the decimal point 
 +    * if rounding occurs, so be it; if not, don't worry about it 
 +  * the written out score pairs are done so in reverse order (last to first, although score still precedes total) 
 +    * the score is separated from the tally by a comma ',' 
 +    * the field separators in the score pairs field are semi-colons ';'
  
-  * be creative in your design and implementation of this game. +For exampleif the source data was:
-  * consistently indent your code so that it is readable! +
-  * document your code so I know you know what you're doing +
-    * andweeks from now, so will you. +
-  * Polish your output so it appears consistent to the end user+
  
-=====Contemplations===== +<code> 
-Perhaps things that could be incorporated into your weekly journal entry...+KRIS    2 13 17 9 18 
 +</code>
  
-  Provide a code snippet that will successfully call the **powf(3)** function and display the result of a sample operation (this is a real function, part of the math library). +The corresponding line written out to **sfa0.out** would be:
-  **result()** function returns an **int** but you want to store it in a **float**, show me how you'd do this. +
-  * Show me the code that calls the following function**int sample(int *, int);**+
  
 +<code>
 +Kris:2:22:35:63.25:62.86:9,18;13,17
 +</code> 
 +
 +Additional constraints:
 +  * use FILE pointers and FILE pointer-oriented C library functions (fopen(), fprintf(), fscanf(), fclose())
 +  * close all open files when done
 +  * you must have and use 2 FILE pointers
 =====Review of Compiling/Executing===== =====Review of Compiling/Executing=====
 Just to review the compilation/execution process for working with your source code, if we had a file, **hello.c**, that we wished to compile to a binary called **hello**, we'd first want to compile the code, as follows: Just to review the compilation/execution process for working with your source code, if we had a file, **hello.c**, that we wished to compile to a binary called **hello**, we'd first want to compile the code, as follows:
Line 340: Line 357:
  
 <cli> <cli>
-$ submit cprog fcc0 fcc0.c +$ submit cprog sfa0 sfa0.c sfa0.out 
-Submitting cprog project "fcc0": +Submitting cprog project "sfa0": 
-    -> fcc0.c(OK)+    -> sfa0.c(OK) 
 +    -> sfa0.out(OK)
  
 SUCCESSFULLY SUBMITTED SUCCESSFULLY SUBMITTED
Line 348: Line 366:
  
 You should get some sort of confirmation indicating successful submission if all went according to plan. If not, check for typos and or locational mismatches. You should get some sort of confirmation indicating successful submission if all went according to plan. If not, check for typos and or locational mismatches.
- 
-What I'll be looking for: 
- 
-<code> 
-78:fcc0:final tally of results (78/78) 
-*:fcc0:project submitted [6/6] 
-*:fcc0:FCC game adequately implemented [6/6] 
-*:fcc0:consistent and relevant commenting [6/6] 
-*:fcc0:consistent indentation [6/6] 
-*:fcc0:output consistent with project specifications [6/6] 
-*:fcc0:compiles with no messages generated [6/6] 
-*:fcc0:correct operation (run 1/4) [6/6] 
-*:fcc0:correct operation (run 2/4) [6/6] 
-*:fcc0:correct operation (run 3/4) [6/6] 
-*:fcc0:correct operation (run 4/4) [6/6] 
-*:fcc0:intro function works and used [6/6] 
-*:fcc0:display function works and used [6/6] 
-*:fcc0:chkmove function works and used [6/6] 
-</code> 
haas/summer2017/cprog/projects/sfa0.1500560953.txt.gz · Last modified: by wedge