The computer is an important part of today's world. Software and computer technology continue to grow at an ever-increasing pace. VIAGRAPHICS Corporation is here to help. Now, more than ever, it is important to keep abreast of the changes in our high-tech society. VIAGRAPHICS Studios produce video training tapes that combine the best of traditional learning methods. VIAGRAPHICS is proud to present this video tutorial, Programming in C, with your instructor, Bob Webster. Hello, I'm Bob Webster. I'm going to be telling you about C programming today. When you've looked at this tape, you will not be a C programmer. This tape is an overview of the C programming language. In order for you to learn to program in C, there's only one way to do it, and that's to practice, read the manual and write programs. We will cover several aspects of the C language, starting with simple items, progressing up through some fairly complex features of C. First, let's take a look at a simple C program. This is our C program. If you'll notice at the beginning, there are several include directives. These are to include the C libraries in with the program so that we can make calls to the built-in C functions. Down past those, there is a main statement. This means that this is the main procedure of our program. The bracket, the curly bracket above and the curly bracket or brace below define the statement block that makes up the main procedure of our program. The int statement defines a variable j to be an integer. This statement, assigned 20 to variable j, is a comment. It begins with a slash star and ends with a star slash. In any programming language, it's a very good idea to include comments so you can read your program and so other people can read your program easier. Next we have an assignment statement, j equals 20. This takes the value of 20 and assigns it to the variable j. Then we print the value of j with the printf statement. This is the printf procedure. It's a built-in function with the C language that allows you to print the value of variables on the screen. With the printf function, there is a string, in this case we have backslash n percent i backslash n, and this string contains formatting information. The slash n are used for new lines. Percent i means that we're going to output an integer variable. J is the integer variable we're going to display on the screen. Now let's try running the program. If you look at the screen now, you'll see the variable 20 or the value of 20 printed out above the elapsed time message. This is a result of the printf function. Let's go back to the program now and see. And we can see the program assigned a value of 20 to the variable j and printed it out. If you'll notice, we were using the Microsoft Quick C compiler when we ran that simple program. Throughout this tape, we will be using Quick C. However, everything we do should be compatible with other C compilers, such as Turbo C or Microsoft C. The C language we're using will conform to ANSI C, which is the American National Standards Institute version of C. The advantage of using C this way is that you can move your C program from one system to another with very little or no changes. Let's take a look at another program. We will look at the program control statements for the C language. This program counts from 1 to 10. So very simple, but it gives us an idea of how to use the while statement in C. Again, we have the include statements. These include statements are very important in some program. It's a good idea to include these statements in every program that you write. It can prevent a lot of time-consuming errors. Down in the program, again, we've got the main procedure with the curly brace at the beginning and the end of the statement block for the procedure. We indent two spaces just for readability. In C, you can put any statement anywhere on any line, and you can even divide statements between two lines. But when you program, it's important to make your program easy to read and easy to maintain. So it's a good idea to get in the habit of some uniform spacing conventions. Anyway, back to the program, we've got int j to define j to be an integer. Then we set j equals to 1, and now the while statement. The while is a new statement. It says perform the following statement or statement block while j is less than or equal to 10. We have another set of curly braces here defining a statement block. The printf statement and j equals j plus 1 statement are inside this statement block, and they will be executed repeatedly until j is less than or equal to 10. First time through the loop, j will be 1, will be printed, 1 will be printed. Second time j will be 2, and so forth, until it gets up to 10. Then j will be incremented to 11, and the loop stops. Let's try running the program. Here we see the numbers from 1 to 10. It did exactly what we expected. Now let's go back to the program and try making some modifications. One common error in programming, no matter what the language, is the infinite loop. If we remove the statement j equals j plus 1, this loop is executed until j is, or as long as j is less than or equal to 10. Since there's no way to increase the value of j, the loop goes on forever. Let's try it and see. We will recompile the program. Now when the program runs, number 1 is printed over and over and over until we hit break or otherwise exit the program. Similarly, if we increment j by 2, the program will count by 2's. Let's try this one. Now this is another common error in C. We have j equals j plus 2, but it says j is undefined. In the C programming language, everything is case sensitive. This means that the lowercase j is not the same variable as the uppercase j. So what we need to do is change the uppercase j to lowercase and recompile. We can see here that the program counts 1, 3, 5, 7, 9. The last time through the loop, j is incremented from 9 to 11. It goes back up to the while statement, and 11 is greater than 10, so the loop is exited and the program is finished. The assignment statement when we had j equals 20 takes on the form the variable equals an expression. An expression can be any mathematical expression, no matter how complex or simple. For example, if we wanted to say j equals square root 17 times 4, this is okay. This takes the square root of 17, multiplies it by 4, and takes that value and assigns it to the variable j. This is similar to many other programming languages such as BASIC, PASCAL, and most common languages. This is an arithmetic expression. The valid mathematical operators that can be used in an arithmetic expression are plus, minus, times, divide, and percent sign for mod, which stands for modulus or remainder. Any of these can be used in conjunction with parentheses to develop any mathematical formula, and in addition to that, you can use any of the mathematical functions supported by the PASC language. In our last program, we had a while statement, and in parentheses, we had a relational expression. A relational expression is an expression that can be evaluated to true or false. J is less than or equal to 10 is either true or it's false. In C, a relational expression is an arithmetic expression separated by a relational operator and another arithmetic expression. For example, we can have j is less than 10, we can have j is greater than 10, we can have j is equal to 10. Now this is something very important. When I say j is equal to 10, I put two equal signs in here. If you only put one equal sign in there, the result will always be true, and this is not what you want in your program. Be sure and put two equal signs for equals in a relational expression. If you don't do that, you won't get an error message, but you will get the wrong answer. This will save you possibly hours. In this program, we will look at the if statement. The if statement has the word if with a relational expression, j is greater than 23, and then another statement or block of statements, print f greater than 23. Again, the backslash n's stand for new line. In addition to the if statement, we can have an else immediately following the if. This means if the if statement was not satisfied, then we go to the else. If j greater than 23 is true, then the first print statement is executed. Otherwise, the second if statement is printed. Up here we have the scanf statement. This is a way of inputting a variable from the keyboard in C. Scanf statement has a string which determines the format. The percent d means integer decimal format. In other words, we're going to be reading a value into an integer decimal. We're going to read it into the variable j. The ampersand is necessary to designate the address of the variable j. We will go into this more later. For right now, scanf reads a variable j, and if j is greater than 23, we print the first message. If otherwise, we print the second message. Let's try running the program. Now we compile the program. Now the program is waiting for our input. We will input 25, and the message that is printed is greater than 23. Now let's run the program again. This time we'll enter 15, and it says less than or equal to 23. If we look at the for statement, we say see the word for, then j equals 1 semicolon, j is less than or equal to 10 semicolon, j equals j plus 1. Now there are three statements inside the parentheses following the word for. The first statement is the initialization statement, j equals 1. This performs the initialization for the loop. Then we have the test, j is less than or equal to 10. This is an expression which can be evaluated to true or false that determines when the loop is going to be ended. Then we have the increment statement or statements, j equals j plus 1. This increments the value of j at the end of each loop. What the statement does, it starts j at 1, goes, executes the following statement, print f, and then increments the value of j, and does the same thing again until j is less than or equal to 10. Let's run the program and then go back and look at the for statement and see exactly what happened. We'll compile it. You can see the program printed the numbers from 1 to 10. Now let's go back and look at the program and figure out why. We have j equals 1, j is less than or equal to 10, and j equals j plus 1. When we have j equal j plus 1, it adds 1 to the value of j at the end of every loop iteration. Then we print the value of j each time through the loop, so the first time through the loop it prints 1, the second time through the loop it prints 2, and so forth until we get to 10. Let's try changing this. Let's go up to 30, j is less than or equal to 30, and then here we say j equals j plus 3. When we run the program now, it will count from 1 to 30 by 3s. Here at the bottom of the screen, you can see where it counts 1, 4, 7, 10, on up to 28, and the last time it adds 3 to 28, gets 31, and exits the loop. In programming, it is very common to have the need to execute a statement or a set of statements a certain number of times. The for statement is one of the most powerful and most commonly used program control statements in the C language. In addition to the simple initialization statement, you can have more than one statement here separated by commas. If we needed to assign the variable k a value of 5 here, we could do that. If we needed to increment k at the end of every loop by 5, we could add another statement at the end. At the initialization section of the for statement, you can have more than one assignment statement separated by commas. At the increment part of the assignment statement, you can have more than one statement separated by commas. These statements may or may not be related to the loop itself. Here we have a program similar to the last one, but you'll notice at the end of the for statement, instead of a printf function, we have a curly brace followed by two statements and another curly brace. The curly braces designate a statement block. This statement block will be executed after the for statement in each loop iteration. The for statement is just like we saw before, j equals 1, j is less than or equal to 10, j equals j plus 1. Above the for statement, we initialize the variable k to 0, and inside the loop, we set the, or we add 4 to the value of k each time through the loop. Let's run this program and see what happens. Two numbers are printed out each time through the loop, the value of j and the value of k. Let's look again at the program. In the for statement, it's very, very important to notice at the end we do not have a semicolon. C statements are generally ended with a semicolon. However, if you put a semicolon at the end of the for statement, the following statements are executed only after the loop has finished. Let's see what happens when we put a semicolon here. You'll notice that there will be no error messages generated, but what we had planned will certainly not take place. Here you see the value 11 and 4 have been printed. Let's see why. The for next loop was executed 10 times, but that's all that was executed 10 times. The value of the variable j went from 1 to 10, and it even went up to 11 at the last iteration, and then the loop was exited. After the loop was finished, the value of j was 11, then k, which is still 0, was incremented to 4. So when we got to the print statement, j was 11, k was 4, and that's all that happened. Remember, if you want to execute the statement or statement block following the for statement, leave off the semicolon. That's very important. In the for statement, the initialization statement can be j equals 1 or it can be anything, like we mentioned before. Let's change this to j is less than or equal to 1100, and we'll change this one to j equals j times 2 instead of plus 1. We'll run this program and see what results. This time we went through the loop 11 times. j had a value of 1, 2, 4, 8, and so forth, doubling every iteration through the loop. j was incremented by 4 each time through the loop as it was before. Let's change the for loop back from j equals 1 to 10, back to j equals 1 to 10, incremented by 1 each time through the loop. Where we have j equals j plus 1, we can replace that with j plus plus. This is a shorthand way of incrementing a variable by 1. Use whichever method you prefer. The code generated by the compiler is exactly the same in each case. It's just a shorthand way of accomplishing the same thing. Now in this loop, we will look at a couple of other program control statements. There is a break statement that can be used to exit a for loop, a while loop, or other loops. To do this, we will use the if statement, if j greater than 5, break. With this inside our loop, j will get up to a value of 5, and then the loop will stop. Let's try this. This time j went from 1 to 5, and when the if statement was encountered and j was 6, the loop was exited. Let's look again at the program. The continue statement passes control of the program to the end of the loop, skipping over everything from the continue statement to the end of the loop. For example, if we change our program so that j mod 2 equals 0, this causes the k equal k plus 4 and the print statement to be skipped every time j is an even number. Again let's look at the percent sign. Percent sign is the mod operator in C. This means j divided by 2, and it gives the remainder of that division. For example, every time j is an odd number, this will return 1. Every time j is even, it will be equal to 0, so we will continue every time j is equal to 0 and skip over these two statements. Let's try running this and see. Here you can see the value of j is 1, 3, 5, 7, and 9. The value of k goes from 4 to 8 to 12, the same way it was incremented before. The value of j, since it was incremented inside the for statement, increases each time, even those iterations that were continued and skipped over. The value of k was incremented only every other time through the loop. In C, we have a set of logical operators that are used to combine complex relational and logical expressions. For example, the double ampersand is the AND operator, two vertical lines are the OR operator, and the exclamation point is for not. Now these vertical lines are not the number 11, they are not two lowercase l's. On your keyboard, they look like two split vertical lines. On the screen, they look solid. It's in the upper right-hand corner of your keyboard, but these are used for the OR operator. Let me give you an example, if we have an if statement, if j less than or equal to 10 or k greater than 5, then the statement. This causes the following statement or statements to be executed if j is less than or equal to 10 or if k is greater than 5. Now let's take a look at it in a program. In this program, we have a for loop for j equals 1 to 10 by 1, then an if statement, if j is equal to 4 or if j is equal to 6, then print the value of j. Notice again that in this if statement, we use the double equal sign for equals. We don't use the assignment operator. Let's run the program and see what happens now. You can see that it printed the value 4 and the value 6. As it went through the loop, if j was equal to 4, then it printed j, and if j was equal to 6, then it printed j. This is not very practical, but it does illustrate the use of the OR logical operator. The AND operator can be used in a similar manner. There are several assignment operators in C language. Plus plus, which we used earlier, is used to increment the value of a variable by 1. There's also minus minus, which is used to decrement the value of a variable by 1 or subtract 1 from a variable. There's plus equal, which is used to add something to a variable, minus equal, and so forth. There are several others. You can look in your C manual to see all of them. The most common are the plus plus and the plus equals. Let's take a look at a program using some of these. Here we have the same program we used last time, except in the for next loop, we use j plus plus. This adds 1 to the value of j and makes it easier to write than j equals j plus 1. Now we'll look at another program. In this program, we use several of the assignment variables. We start out with j equal to 10, then we use j plus plus to add 1 to the value of j. Then we use j plus equals 10. This means this is the equivalent of writing j equals j plus 10. You notice I put this statement inside a comment field so it's not actually used by the compiler. Now the j times equals statement is equivalent of putting j equals j times 10. Now let's run this program. We have, remember j started at 10, and then we added 1 to j to get 11. We added 10 to that to get 21, and then we multiplied 21 by 10 to get 210. The assignment operators are a shorthand way of accomplishing the same thing. It may be faster and easier to type it into the program, but the code generated is exactly the same as it is if you don't use this shorthand form. Use whichever way is more convenient for you and easier for you to understand. There are several C data types. A data type is the type of a variable or constant. In the programs we've run so far, we used integer data types, or int. The int data type is a 2 byte variable, and its value can range from negative 32768 to positive 32767. In C there's also the character data type called char, long int, which is a long integer, float, which is floating point, single precision, and double, which is floating point, double precision. Char, int, and long int are all integer type data types. This means that only whole numbers can be represented with these. Float and double are floating point data types. This means that fractions can be represented with these. The character data type is normally used to represent characters or strings. We will go into that in detail later. The most common data types are probably integer and float for normal integers and normal floating point numbers. Floating point numbers are also called real numbers. The character, integer, and long integer, you'll notice, go from negative to positive in each case. Because it's desirable to go to an entirely positive range, for example, 0 to 255 instead of negative 128 to 127. In this case, you can put the word unsigned in front of the data type. For example, unsigned int produces a variable type or a data type that goes from 0 to 65535. An unsigned integer corresponds to the Pascal word data type. The character data type uses one byte, you can see by the one square. Integer data type uses two bytes. The long integer takes four bytes. Floating takes four bytes. And double precision takes eight bytes of storage. Up until now, we've been using the printf statement or printf function, but we haven't said much about it, how it's used and what options there are. With the printf statement, there are two sections. One section is the string which contains the format information. The other section contains one or more variables. Here we have the variable j, an integer, and the variable x, a floating point or a real number. In addition to variables, you can put constants in this area. Let's look at the format section first. We have j and x. This is going to be displayed as a message. Every time there is a percent sign in the printf format section, it designates a format specification. In other words, the percent d means we're going to output a decimal integer. And f means we're going to output a floating point number. After the percent sign and before the format specifier, you can add a length field as shown here. We will have an 8 for the integer, then an 8 for the real number, and then the.2 means to add two digits after the decimal point in the floating point number. Since the integer is always a whole number and has no decimal point, you don't need the .2. Down here, we've changed it to.0 for no digits after the decimal point. Then we have a.4 to specify four digits after the decimal point for the x in the fourth statement. If you'll notice, we have 8.3 for the variable j here. This means that there are going to be three digits displayed, even if some of them are zero. Let's take a look and see. The first time, we have j and x displayed at 10 and 20. 20 has six digits after the decimal point because we didn't specify. There's one space separating the 10 and the 20, just as there was in format specification. The next line has 10 and 20, each one occupying eight spaces on the screen. The 20 has two decimal places, just like we specified. In the third line, we have 10 and 20 with zero decimal places. And on the fourth line, we have zero 10 because we had the.3 after the specifier for the j. Let me show you back on the main program again. We have 8.3 for j, and the.3 meant to use three numbers to display the value of j, regardless of how many were required. Even though we only needed two digits to display the 10, it used three displaying 010. In addition to the d and the f, there are several other format specifications for the printf command. Some for strings, some for characters, some for hexadecimal display, and some for long integers. See your C manual for details on this. One of the most powerful and flexible features of C is the ability to use functions and to define functions. Almost every non-trivial C program is made up of several functions. The first function, of course, is the main function, like we've seen before. In addition to that, though, we can define functions throughout the program to perform a variety of tasks. Let's take a look at a simple function. In this program, we define the function called sub to print out a message. At the beginning, we have the prototype for the function. What this amounts to is a declaration of the function. This is allowed in ANSI standard C but is not required. Good programming practice, though, means that you should always put a prototype at the beginning of the program. The reason for this is that if you use the wrong type or number of variables for a function, it will display an error message. Otherwise, you will not see an error message, but the results will be unpredictable. So you should always use a prototype for your functions. This amounts to the function definition at the top. Now our function name is sub. The void at the beginning is a special word, meaning that the function does not return anything. Then we have two parentheses next to each other. There's nothing inside the parentheses, and this means that there are no parameters for the function. In other words, when the function is called, program execution is transferred to the function, but nothing is passed either direction in the way of values. Let's take a look at this. To call the function, we use the name of the function with the parentheses and any required parameters inside the parentheses. We have a for loop for j equals 1 to 10, and each time in the loop we call the function sub. When we call the function sub, there's a print statement, and it says this is printed in the function sub. Let's run this and see what happens. We get the message this is printed in the function sub 10 times. Each time in the loop, the function was called, and the statement was printed. This is a very simple example of a function. The function returned no value, so we had the void statement at the beginning of the function definition. There were no parameters for the function, so we used two parentheses next to one another to specify this. Now we'll look at another simple function. In this program, we use the function distance to find the distance between two points, two x and y coordinates. The formula for the distance is given in the function distance. At the beginning of the function definition or the prototype, we have the word float. That means the function distance returns a floating point value. Inside the parentheses, we have float x1, float y1, float x2, and float y2. This means that we have four floating point variables as arguments or parameters for the function. When we call the function, again, we just specify the function name, but since the function returns a floating point value, we can assign that to a variable in the main program, in this case, the variable d. Up here, we define all the variables in the program or declare all the variables in the program to be floating point. We assign xA to be 10, yA to be 10, xB and yB both to be 20. You'll notice in the assignment statements above that the yA and xA statements are on the same line. Like we mentioned before, you can have any number of statements on any number of lines in C programming. You can even have one statement that covers more than one line. Now we have the d equals distance statement that takes the value of distance with these parameters and assigns it to the variable d. Then we print the value of d in the printf statement. Let's run the program and try it out. The distance is 14.14. That is the correct answer. We mentioned before that you should always have the include statements in your file. Here we have the include math h. This is the file that declares or contains a prototype for the square root function. If we didn't have this, the square root function would return an integer value for some reason because that's what it defaults to. If we remove this statement from the program and run it again, you'll see we get no error messages, but we do get the wrong answer, 114. It is very, very important to include all prototype definitions in your program. The correct answer here was 14.14, but you can see we got the answer 114 and still didn't generate an error message. Be sure to declare all functions in prototypes, either with the include or with explicit prototypes. In the program, when we called the distance function, we used variables. It's also possible to use constants here. For example, we can use 10, 20, 30, and 40 here instead of the variables. When we run the program now, we get the answer 28.28, which is correct. The distance function itself works like this. It takes the variable dx and assigns it the value of x2 minus x1. And assigns the variable dy the value of y2 minus y1. Now in the main program, we don't have any variables called x2, x1, y2, and y1. What do these refer to then? Their positional parameters. The first parameter in the call to distance is going to be x1. In this case, the 10 will be x1. The 20 will be y1. The 30 will be x2. And the 40 will be y2. Notice here that these constants look like integers. But since we have a prototype up here and declared this to be floating point, the C compiler automatically converted these constants to be floating point constants so we could get the correct answer. If we did not have the prototype, that wouldn't be the case. Variables in a function are local to the function. In other words, in the function distance, we have variables dx and dy declared in the float statement. These variables cannot be used in the main program. For example, if we put an assignment statement up here in the main program, dx equals 17, and compile the program, we get an error message. It says dx is undefined. While dx is, in fact, defined in the function distance, it's not defined in the main program. By the same token, if you have a variable by the same name in a function as you do in the main program, in this case, maybe xA, that variable is not the same variable as the one in the calling program. If we print the value of xA in the main program, and if we change the value of xA in the procedure, we will find that the value of xA in the main program is still its original value, 10. One other thing to be aware of, inside the procedure, if you change the value of a parameter, x1, for example, and up here we'd say xA, x, yA, xB, and yB, if we change the value of x1 to 243, when we print out the value of xA in the main program, it will not change. It is still 10. The reason for that is that the normal parameters are value parameters. The value of xA is passed to the function distance, not the address of the value. If we wanted to pass the address of the value and modify it, we could use the ampersand, which designates an address. And on x1, we could put an asterisk, which designates pointer. Now, we've gone through the program and changed the occurrences of x1 in the distance function to asterisk x1. This means we're referring to the pointer x1 instead of the actual value x1. In the calling statement to distance, we use ampersand xA instead of just plain xA. And in the float statement, we use asterisk x1 in the prototype as we do in the actual function. When we run the program now, you can see the value has changed to 243. Pointer parameters and addresses can be a very complex part of C programming. You may not comprehend all this the first time through the tape or the first time through the manual, but it's very important to go through the tape and manual until you completely understand the use of parameters and functions, as well as pointers. We will cover a little bit more on pointers as we go along. Now, we'll try another test with functions. We have a function called test with one parameter, an integer x. In the function, we assign x the value of 30 and then print it. Before the function, we assign x the value of 20, print it, call the function, and print the value of x again. Let's see what happens. On the first print statement, x is 20. Inside the function, where we have C, x is 30. After the function call, x reverts back to 20. In the program, this x is local to the main program. In the procedure, the value of x is passed rather than the variable itself. If we want to permanently modify x from within the function test, we need to pass the address of x or the pointer of x. To do that, we can change the function. Instead of x1, we will put asterisk x1 on the prototype and on the function definition. I mean x1 or x. It doesn't matter which in the prototype. In the function call itself, we need to use the ampersand to designate the address of x instead of the value of x. And then within the function itself, everywhere we use x, we need to change it to asterisk x, which means the value at the address of x. Within the function test, x represents an address. And we have to use the asterisk to get to the value at the address of x. Let's run the program and see what happens now. Now you can see that the last print statement outputs a 30 instead of 20 because the value of x was changed in the function. Now let's take a look at arrays. An array is a series of variables represented by a single name. Each individual element of an array can be addressed with a subscript. In this program, we have an array called A. It has 10 elements. The elements of the array A are addressed as A0, A1, A2, and so forth up to A9. This is very important to remember. We have A10 in the declaration, but the actual addressing goes from 0 to 9. If you try to address array element 10, you'll address an area outside the array, but it will not generate an error message in C. This can cause disastrous results within your program. You should always be very careful to address an array only within its bounds. Here's an example of how you can use an array. We have in a for loop from 0 to 9. We have 0 and j less than 10 instead of less than or equal to 10, so it only goes up to 9. We assign aj the value of j times 2, so the element 0 will be 0, element 1 will be 2, element 5 will have a value of 10, and so forth up to number 9 having a value of 18. In the next loop, we print out the values of the array A along with j. Now let's look and see what happens when we run the program. We see on the left column the numbers 0 to 9. These are the elements of the array. On the right column, we have 0 to 18, or the element number times 2, which we assign. Arrays are a very important part of programming in any language. With an array, you can assign a large number of variables and use a single name with an index to access these. One of the most common uses for arrays in C programming is to represent strings, character strings. A character string in C is just an array of characters. Here we have an array called string. You notice we have 81 elements in this array. A character string in C consists of an array of characters, and the string is a set of characters ending with a character 0, or a null character. That's why we have 81 here. In order for us to have a character string of length 80, we have to have 81 elements in the array, the 81st element being a 0. In this program, we don't use j and k, but they're there. We copy a, b, c, d, e, f, g, the character string, to the variable string. On the next line, we print this out. The percent s is the printf format for strings. When we run this program, it should print a, b, c, d, e, f, g. Let's see if it does. Above the elapsed time statement, we see a, b, c, d, e, f, g. Program does work. Now, you may be tempted when you program to use a simple assignment statement to assign a value to a string, such as this. This is not possible. Since a string is an array, it's not possible to assign seven elements, in this case, to an array at one time. The string copy function does this for you, but it's not possible to do it this way. Let's try it and see. We get the error message, in this case, the left off brand must be lValue. That seems a little bit cryptic. What this means is that the identifier to the left of the equal sign is not legitimate. In other words, string, the word string without an array is actually an address of the string, and it's not legitimate to be assigned the values a, b, c, d, e, f, and g. When you see this error message, this is the reason or possibly something similar to it. Let's change this back to the way it was with the string copy statement. And in the print statement, instead of the s, we'll use c for the character format. And in string, we can print out a particular element of this string or a particular letter. The third letter will be a three, because the third letter of the string a, b, c, d, e, f, g is c. Let's try that. We have a d. Now, why did we get that? The three here at string does not mean the third element. It actually means the fourth element of the array. We start with 0, 1, 2, and 3 in c. Remember in c, all arrays are character based. If you put a 3 for an array element, you were talking about the fourth element in the array. There is another common problem when you use strings in c. If you define a character string to have a length of, say, 20, and then you assign it a string that has a length of 20, it's invalid. It does not cause an error message, but it does cause a program error. Since every string in the c language ends in a null character, you have to add 1 to the maximum string length when you're declaring the string. This has to be 21. Otherwise, the null character will be written over the variable j in this case. Again, when you do this, you do not get an error message, but you do get improper results in the program. In this program, we input a string from the keyboard using the get s statement. The get s is a c function used to read a string from the keyboard. It's a simple program. We just read the string and print it out. We'll try it. Now I'm typing a message. And after I type the message, this is a string from the keyboard. It was printed from the printf statement. And we can return to the program and see. Now suppose we want to type a number and use it in arithmetic. For example, we want to read a number from the keyboard, multiply it by 10, and then print that number. There are a couple of ways to do this. One way is with the atoi statement or ASCII to integer conversion. This converts a string to a number. We say j equals atoi string. And when we print it, we'll print j times 10 with a decimal format. Notice on the printf statement, I use j times 10 instead of just j. It is possible to use expressions in the printf statement in addition to the actual variables or constants. We'll run the program and enter number 45. 450 is printed out. There's another way to read numbers from the keyboard that we haven't mentioned yet, and that's the scanf statement. We can enter scanf with a format, decimal format, and ampersand j. Then we don't need the conversion statement. Now when we run the program, we should get the same result, and we do. One of the big differences between the scanf statement and the getf statement is that the scanf statement requires formats. If you're going to input a number, you have to have a percent d for every number. And whenever you press a space or a tab character, the input for that variable is terminated. With the gets statement, the string is read until you get to the end of the line in every case. It may be more consistent for you to use gets statements and some of the other conversion functions in your programs. An array is a single variable with several elements. In this case, we have 10 elements in the array A. The first element is designated by A0 with square brackets. Then we have A1, A2, on up to A9. To declare this array, we would say give the data type and the array name, followed by the number of elements in the array. A10 means we can go from A0 to A9. Remember, when you declare an array, you specify the number of elements in the array, not the maximum element. If we declare A10, that means we go from 0 to 9. This means it's zero-based. Arrays in the C language are always zero-based. Now, I'd like to say a couple of words about pointers and addresses. If we declare a variable x as int x, it may have a value of 5. An ampersand x may have a value of 37,423 or some arbitrary address. The ampersand means that we're talking about the address of x. And if we go into the computer's memory at this location, we'll find the value of 5. If we declare x to be asterisk x, that means we declare x to be a pointer or an address. To keep this straight, remember this. A pointer is an address. A pointer is an address. That's all you need to remember. We declare x to be a pointer. That means x is an address. Whenever we want to find out what is at that address, we put the asterisk in front of x. So asterisk x may give us a value of 10, whatever the value happens to be at this location in memory. It's very important when you use pointers and addresses to keep them straight. As you can see here, an address is probably a pretty useless number. What you want is the actual value, whether it is the address or whether it is the value pointed to by a pointer or if it's the actual value of a variable. Review this in your C manual. And if you don't understand it, read it again until you do. Here we have a program that opens a file, saves a line to disk, closes a file, opens it again, and reads the same line from disk. Disk file IO is common. Almost every non-trivial program reads and writes data to and from the disk. Let's take a look at this program in detail. First, we declare a file. Notice that this is in capital letters. If you'll remember at the beginning of the tape, we said that in C, every identifier is case sensitive. The word file has to be in capital letters. Then we have a pointer variable. In this case, we're calling it f1. The asterisk means that it's a pointer variable. And then f1 is what we're going to refer to the file with. We have three strings, as, bs, and f1s. We're using the underscore s here to designate strings, but that's an arbitrary idea. We have a print statement, enter the file name, then a get statement to read the string f1s. This statement, the fopen statement, is the one that opens the file. We call the fopen function with the string containing the file name and then string with w, meaning to open the file for writing. f1 contains the file handle or the file reference number. If it's equal to null, then the file name is equal to null, then the open statement failed and we must have had a bad file name. We print a message. Remember the if statement. If f1 is equal to null, then we execute the statements in the block represented by the curly braces. Then we use the string copy statement to copy this as a line for the file into the variable bs. We use the fputs statement to output the variable bs to f1. Now, there is an easier way we can do this. We could put the constant in the fputs statement, but in most cases, you will be outputting a variable to a file. So for now, we will leave it like this, even though it may not be the most efficient way to do it. After we have output the line, we close the file, then we open it again with the same fopen function, except this time, we use r to open it for reading. We use fgetas statement, which reads a line from the file. 81 is the maximum length of the string to be read. If you'll notice up above, we declare the variables to be 81 in length. So we read 81 maximum, file f1, and the variable we're reading it into is bs. Then we print out the value of bs to make sure it was the same thing we saved on the file. We'll run the program now and see if it works. It says enter the file name. We'll use file name of x, and it prints this is a line for the file. And if we go back to the program, we printed bs, which was read from the file and which was saved at the file here. But just to make sure, let's exit the C program and list out the file name x. And sure enough, inside that file name, it says this is a line for the file that we saved. So our program does work. Let's go back to the program and review the statements we used to open and write to the file. To open a file, first we need to declare a file variable. In this case, it's called f1. Then we need to have a name for the DOS file name. In this case, we read that name using the getAs statement. That reads a string from the keyboard. After we have the file name f1s, we call the fopen function and pass a w for writing. Let me mention here, if we used a constant here, that's acceptable, or C backslash test. This means on the main directory, we have a file test. However, when you use a string constant in the C language, if you want to use a backslash in that constant, you have to put two of them there. Remember that. Otherwise, you will get a DOS error message most likely. At the minimum, the program won't do what you want it to. The reason for that is if we happen to have an N here for the first letter of our file name, it would cause a new line. The backslash N is what you use for a new line in C. If you use a backslash T, like we had before, that stands for the tab character. It would insert a tab character in our DOS file name. If a backslash, backslash is the only way to get a backslash in a C constant. This is true in the fopen function, in the printf function, or in any C constant. Let's go back to the way we were. If f1 equals null, we exit. Whenever you call a C built-in function, you should always check the return code to see if there was an error. Otherwise, your program may do almost anything upon an error. Your program should always handle errors in a decent way. Now we use a string copy statement to copy a string constant into a string variable. We use the f put s statement to output this string variable to the file. f put s is similar to the put s statement, except it outputs it to a file. If we change this to put s and took away the file variable, this would just output the string to the screen. We'll change it back to where it was. Now we close the file. Before you can reopen a file in a different mode, you have to close it. We use the f close statement to do that. Then we open it for reading, which is what the R stands for, and use the f get s statement to read a line from the file. Up here, we used to get s to read a line from the keyboard. The f get s statement is the same thing. It reads a line from the file until you get to a carriage return and then stops reading. Print f statement, you should know using the percent s means string, and it outputs the variable of bs to the screen. If we wanted to make this simpler, we could use put s and get rid of the format information. It would do the same thing. Now we'll look at a more practical program for C, just as an example. We have gotten a bunch of quotes from CompuServe for stock prices, and we want to read this data into CapTool investment software. However, the formats are not compatible. We want to write a program to convert the format of the file to a format more acceptable by CapTool. Here are the file formats. The input file has a stock name, price, change, the date, and the volume. The output file should have the date first, and the date on the input file doesn't have the year. We need to add the year to this date. Then the stock name, the letter s, a volume, which we have here, except we need to divide the volume by 100. And then the price, which is the same. The data needs to be reorganized, and two fields, the date and the volume, need to be modified. Not every field will be converted. For example, we don't need the change. Let's take a look at the input data file now. This is the input file. You can see we have the file name, then the price, the change, a couple of words on that we will ignore, the date, the volume, followed by the word sheriff, which we will ignore. The output file will look like this. You can see we have the date first, then the name, the letter s, followed by the volume, three commas, and then the price. Now let's look at the program to do this and go through it step by step to see what is involved. This is the program used to do the file conversion. First, we have the include statements. Remember, always put these at the top of your program. Then we have the prototype for the function called substring. It's a character function, and it returns a character pointer. And these are the parameters. We'll talk about this in detail shortly. Then we have the main function. First, we declare two file variables, f1 and f2. These variables represent the input and the output file name. We have a number of strings. f1s and f2s are the input and output file names. In this statement, we print the message that says enter the input file name, and then we get the file name from the keyboard. We ask for the output file name, and then we get it from the keyboard. We open the two files. And if the open was not successful, in other words, if the f1 and f2 variables are equal to null, it means there was an error when we tried to open the files. So we print an error message and exit, which terminates the program. Then we have a while loop, while not feof f1. We will execute everything in this statement block. Now, the feof function tells us when we are at the end of the file. In other words, we are reading from the file f1. And when we have come to the end of the file, the function feof will become true. While the feof function is not true, it means that there's more data to be read in the file. We use the fget s statement to read the string as from the file f1, or our input file. This statement checks as sub 32, which is the 33rd position in the string as, to see if it's a slash. There should be a date at this position in the file. And there should be a slash there separating the day and the month. This is one way of telling us that this line has valid data on it. If this slash is not there, or if this string is less than 32 characters in length, then we want to continue and read the next line in the file. This continue statements means that we will skip all the way down from here to here and go back up to the get s statement to read the next line. Now, there's one new function here that we haven't talked about, the string length function. strlen gives us the length of the string as. Now, we have the string copy statement. And we copy substring of as 35 into bs. Bs is the target string. And what we are copying is a portion of the string as, beginning at character 30 and continuing for five characters. In other words, we want to take the five letters at position 30 in the string as and copy that to string bs. Then we have the string concatenate function. This adds something to the end of the string. For example, in this case, we add slash 90 onto the date that's already in bs. Now, we add the portion of as, beginning at the first character and going for seven characters. And we add that to bs. This is the name of the stock. Then we add the letter s. And at this point, we have the date, the name of the stock, and the letter s in the string bs. Now, we're going to take the volume from string as, which is a character 39 and goes for seven characters. We will take the substring to get that volume. Then we use the atol function, or ascii to long integer function, to change the volume in the string into a number. So from the substring, we take the volume in the string into a number. So from this point to this point, we have the volume as a long integer. We divide this value by 100 and assign it to the variable h1. So we have taken the volume from the input string, divided it by 100, and saved it in variable h1. Now, we convert h1 to a string, a1s, and add that to bs. So after the letter s in string bs, we have added the volume. Next, we add three commas. We add the substring as at eight for eight characters. And this is the price. And we add a new line character. The reason we add the new line character is that the fputs function does not add a new line character when you output a string. This is important. If we did not add this character, all the data we output to this file would be in a single line, not terminated by an end of line character. After we've done this, we go back up and read the next line if there's one available. If there's not one available, then this will become true and not feof will be false, and we'll exit the loop and exit the program. Now, let's look at the substring procedure. We'll go up to the top of the file, look at substring and how it was declared. It's a character with a pointer at the function name. This means it returns a pointer to a character variable. The first variable is a pointer, which is source or the source string. Then we have an integer for the position and an integer for the length. Now, let's go down to the function and go through it. We have a similar declaration here, except remember, do not put a semicolon at the end of the true function declaration. Then our curly braces define the statement block that's going to make up the function from here to here. And we define static character target 81. This is the same as defining a character of length 81, except we use the word static here because we are going to return a pointer to this variable. I'll talk a little bit more about that in a minute. We have integers i, j, and n. And to do the substring function, we set n equals to the length. And here, we make sure that n is not too long. If n goes beyond the end of either string, we shorten it. First of all, if n is greater than 80, we know that that's too much for the target string, so we cut it back to 80. Now, if n plus the position minus 1 is bigger than the source string, we can see that n that we will go beyond the end of the source string. This is not good. So we'll cut n back to the length of the source string minus the position plus 1, which is the maximum legitimate value for n relative to the source string. This is the actual part in which we assign the variables or assign the letters from the source string to the target string. Remember, in the for statement, you can have more than one initialization statement. Here, we set the variable i to ipos, which we're going to use in the source string. We set j to 0, which we're going to use in the target string. We want to continue while j is less than the length. And each iteration through the loop, we want to increment j by 1, and we want to increment i by 1. Again, we have two statements here to be used at the end of the loop. The loop itself consists only of target j is equal to source i. This takes the letter in the i-th position of source and assigns it to the j-th position of target. When we're finished, we set the last or the next character of the target string to 0 to signal the end of the string, and then we return target. Notice when we return target, there are no subscripts with the target variable. This means that we are actually returning a pointer. This is something that's significant in the C language. Whenever you leave off the subscript of an array, you are actually referring to a pointer to the first element of the array. The word target here is exactly the same as if we used the address of the first element of the array target. But we will go ahead and do it this way since that is more conventional. And this gives us another reason or brings up the reason. We use the word static up here. When we return, we are returning the address of the variable target. In a C function, variables are normally allocated whenever the function is called. In other words, before this function is called and after the function returns, the variables i, j, and n do not exist. They're merely part of the free memory that the operating system or the C heap or stack has. So i, j, and n do not exist. If we returned a pointer to one of these dynamic variables, as soon as we exited the function, that variable would no longer exist. And we would have a pointer to an invalid variable. So we declare the variable to be static. And this means that the variable hangs around or stays whenever we exit the function. And it means it is already there before we call the function. That way, when we return the pointer target to the target string, when we go back up into the main program and use the substring, we have a legitimate value here for the substring. This covers the program. And if we want to try it out and see if it works, we will compile it. And it automatically runs. It asks for the input file name. We have one called tmp already made up. The output file name is tmp1. And it runs OK, or it seems to. Let's exit the program. And it runs OK, or it seems to, let's exit quick see and look at the destination file name. We'll list the destination file name. We call tmp1. And it looks correct. The program we just looked at is not a trivial program. Just glancing over it, you may not understand everything that's in it. What you should do, though, is get a copy of the program from the disk that's enclosed with your tape and play with it. Make modifications to it. See how it works. Hello, I'm Kurt Gortney with VIA Graphics Corporation. Bob has shown you how to program in C. This training tape is designed to familiarize you with C programming. But as with any skill, the more you practice, the better you become. We at VIA Graphics would like to thank you for choosing our company for your computer training needs. Remember, if you plan to program in C or learn any other software, there is no better way than video training. Thank you. Thank you. Thanks for watching!