User Tools

Site Tools


Sidebar

projects

  • cci0 (due 20170607)
  • sof0 (due 20170614)
  • dow0 (due 20170621)
  • mbe0 (due 20170628)
  • pnc0 (due 20170705)
  • pnc1 (due 20170712)
  • mbe1 (due 20170719) iOR
  • pnc2 (due 20170719) (or do both, 1 as bonus)
  • fcc0 (due 20170726)
  • sfa0 (due 20170802)
  • oop0 (due 20170809)
  • EoCE – bottom of your journal (due 20170819)
haas:summer2017:cprog:projects:sfa0

This is an old revision of the document!


Corning Community College

CSCS1320 C/C++ Programming

~~TOC~~

Project: STRUCTURES and FILE ACCESS (sfa0)

Objective

To begin the exploration of structures, and to explore file access functionality.

References

Some notable references:

  • Chapter 6 (“Structures”) in The C Book for additional information on structures (and derived types).
  • Chapter 9 (“Libraries”):
    • Chapter 9.10 (“Input and Output”) in The C Book for information on I/O functionality.
    • Chapter 9.11 (“Formatted I/O”) in The C Book for information on using fprintf()/fscanf().

Background

This project will deal with two independent concepts:

  • structures (and derived types)
  • file access

Please note, the two are not related, although as with many things, may often be used together (file access is extremely useful, and will often find pairings with all our covered topics- variables, selection statements, loops, pointers, arrays, and now structures too).

I've held off on really covering it until we've gotten more of the basics down, so that you can better understand the power it offers to your programming toolkit.

But first things first, the structure.

structures

In some respects, there are 2 classifications of variables:

  • scalar: it is (and can only be) precisely one thing. Things like char, int, and float fit this classification. They can only interact with their defined type, and they can only hold one such value of that type.
  • composite: composed of potentially many things. We actually have two main composite types in C:
    • arrays: composed of 1 or more of the same type (like 5 ints all packed together)
    • structures: composed of 1 or more of any type (like a char, 2 ints, an array of float, pointers, even additional structures)

Both arrays and structures need to be given substance: they are nothing on their own.

The same goes for pointers, of which all arrays are a type of (all arrays are pointers, but NOT all pointers are arrays, unless you consider them an array of 1).

In that respect they are sort of like adjectives (descriptor attributes), they describe a property of a noun (or thing where attributes can be applied). For example:

  • The green frog ate the cricket.

The adjective “green” DESCRIBES an attribute of the frog. “green” by itself does not make sense in that context:

  • The green ate the cricket.

See what I mean? The green WHAT??

Same goes with arrays and structures. They both enhance things, but cannot be singular entities by themselves:

  • an array of int allows us to have 1 or more consecutive integers:
    • int my_array[4];
  • but we cannot just have an “array”:
    • 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). Just for clarification, you can also have “arrays of arrays” (argv, the second main() function argument, is one in fact) and “arrays of structs”. But an array specifically focuses on duplicating ONE THING, whatever that thing is… a struct encapsulates a collection of potentially disparate things. ====struct definition syntax==== Declaring a struct may appear similar to declaring a function, in that there are braces and things inside those braces. For instance: <code c> struct stuff { int value; char code; short int range[999]; char *name; }; </code> Here we have a struct (specifically, a “stuff struct”– that is the type, as structs are nothing on their own) that contains 4 entities, of varying types: * a scalar int * a scalar char * an array (composite) of short int * a pointer (to be used as a string, or array of char) to char Note one important distinguishing syntactical detail of structures: you MUST terminate them with a semi-colon (they are a variable, and variables are terminated with semi-colons). ====declaring a structure==== To declare a struct, we pretty much do the same as when declaring a variable. In our case, if we have a “stuff struct” as defined above, we'd need to declare an instance of it in order to make use of it. Let's make a “stuff struct” variable by the name of thing: <code c> struct stuff thing; </code> Bam! Please take note of how precisely like any other variable this declaration is… in our case, thing is of the “type” struct stuff. ====accessing array elements==== In C (and by extension, C++), there are two structure access operators, depending on whether or not the structure is a pointer (yes, we can even have pointers to structs). ===non-pointer structure access=== If we are dealing with a non-pointer struct, we use the '.' (dot) operator to access the structure member (so, using our thing variable declared above to assign information to its members): <code c> thing.value = 37; thing.code = 'C'; thing.range[59] = 1337; </code> Especially with arrays and pointers (especially if used as something like a string), we'll probably be routinely combining them with loops, as we cannot access ALL elements in ONE statement. ===pointered structure access=== If the struct we are dealing with has been declared as a pointer (which is the common approach in regular usage, especially as used and interacted with in the C library functions): <code c> struct stuff *something; </code> There are actually two ways of accessing it, using the pointer dereferencing operator, or using the structure pointer operator. Both arrive at the same ends (the structure pointer operator is a shortcut to make our code look nicer). ==pointer dereferencing (note the parenthesis)== <code c> (*something).value = 64; </code> ==structure pointer access== <code c> something → value = 64; </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). =====What is a function?===== In a way, functions are like evolved variables - they have a data (return) type, they are given a symbolic name, and they contain information. Functions are like sub-programs - small subroutines that perform some specific task that is relevant to the larger program (or other functions). So, instead 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). That group of functions, which performs a task, is given a name. That will allow your function to be called from wherever it is needed, and can be used to prevent the needless duplication of code to do some common task a number of times. 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. ====Why should I use functions?==== As I've said, the absolute minimal number of functions required in a C program is 1: main() main() is a 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 a regular function as any other you create. Why can't I just put everything in main()? 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 code, but your code will be significantly more organized. For this course, I will expect you to use functions from this point on. ====Where do I put functions in my program?==== There are two aspects to functions, which are concepts shared with that of variables: * declaration / prototyping * definition / initialization In order to avoid compiler errors, and allow your code to work seamlessly with your functions, ANY functions must be declared prior to any other function that makes use of them. 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. ====When do I use functions?==== 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: * you find yourself duplicating a section of code two or more times. * your program solves a problem that can be broken up into independent steps, or 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: * 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 place. Sometimes you will want to mix things together, but at this stage, the aim is to develop good programming habits and an aesthetic for effective function use. * 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?==== 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. * function name: the identifier for the function. Just as you've given names to your variables in order to access them, the function name allows you to identify the function and to call it from within your program. * 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 scope, they don't exist outside their particular block of code. * function body: the bulk of the function. This is the code you implement that accomplishes a particular task. ====Function vs. Procedure==== Technically, a function returns exactly 1 value (corresponding to the return statement that is placed at the end). A procedure can “return” 2 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. 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 a meaningful value, you should at least return an exiting value signifying success or failure. For example: * If your function was successful, you should return a 0. * 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 statement, how 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 a 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. So, by using pointers in our function's parameter list, we can simulate the notion of procedures. ====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 out, in 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> int funcname(int var1, int var2) { </code> In this case, the function funcname has 2 parameters, both of type int: var1 and var2 So, to call our function funcname: <code c> result = funcname(value1, value2); </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. ===Pass by address=== 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 * and & pointer operators. A sample function declaration: <code c> int funcname(int *val1, int *val2) { </code> And then, to call this function, we do as follows: <code c> result = funcname(&in1, &in2); </code> =====Program===== Using functions, we are going to implement the classic “Fox, Chicken, Corn” game. ====Rules==== 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. There exists the following relationship with the items: * The fox, left alone with the chicken, will eat the chicken. * The chicken, left alone with the corn, will eat the corn. So one needs to craft a careful means of transporting all these items without losing any of them. ====Programming Considerations==== * Your program should display the current scene (using textual characters) * 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===== A couple things to keep in mind: * be creative in your design and implementation of this game. * consistently indent your code so that it is readable! * document your code so I know you know what you're doing * and, weeks from now, so will you. * Polish your output so it appears consistent to the end user =====Contemplations===== Perhaps things that could be incorporated into your weekly journal entry… * 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). * A 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); =====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: <cli> lab46:~/src/cprog$ gcc -Wall –std=c99 -o hello hello.c lab46:~/src/cprog$ </cli> Assuming there are no syntax errors or warnings, and everything compiled correctly, you should just get your prompt back. In the event of problems, the compiler will be sure to tell you about them. Conceptually, the arrangement is as follows: <code> gcc -Wall –std=c99 -o BINARY_FILE SOURCE_FILE </code> The BINARY_FILE comes immediately after the -o, NOT the SOURCE_FILE (it must never immediately follow a -o). It can precede, and such is perfectly valid (especially if you feel that way more intuitive). The -Wall (treat all warnings as errors, increase general verbosity about warnings) and –std=c99 (switch compiler to use the C99 standard of the C language) are options given to the compiler. To execute your binary, we need to specify a path to it, so we use ./, which basically references the current directory: <cli> lab46:~/src/cprog$ ./hello Hello, World! lab46:~/src/cprog$ </cli> =====Submission===== To successfully complete this project, the following criteria must be met: * Code must compile cleanly (no warnings or errors) * Use the -Wall and –std=c99 flags when compiling. * Output must be correct, and resemble the form given in the sample output above. * Code must be nicely and consistently indented (you may use the indent tool) * Code must utilize the algorithm presented above * Code must establish and utilize the functions described above * Code must be commented (and those comments relevant) * Track/version the source code in a repository * Submit a copy of your source code to me using the submit tool. To submit this program to me using the submit tool, run the following command at your lab46 prompt: <cli> $ submit cprog fcc0 fcc0.c Submitting cprog project “fcc0”: → fcc0.c(OK) SUCCESSFULLY SUBMITTED </cli> 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