clark cs1713 syllabus lecture notes programming assignments Another complete program example. In this example, instead of reading the data from a file, we only get the average of grades entered directly on the command line. int main() Within your program, there should be exactly one int main(). This is the function that begins execution. It is passed an array of pointers to strings and a count of the number of items in the array. It returns an integer. By convention, 0 is returned for normal return. The contents of argv includes the command name and the command line arguments to this program. Example: average program Suppose the program average is passed a list of integers and returns the average. In unix, we would invoke it by keying $ ./average 10 20 40 30 25.00000 If the average program is passed this $ ./average 90 100 argc will be 3: argv[0] -> "average" argv[1] -> "90" argv[2] -> "100" homework set up #include <stdio.h> int main(int argc, char *argv[]) { double dSum = 0.0; int i; int iScanfCount; // count of the successful // conversions in sscanf int iNum; // number from the command line /* check for no arguments */ if (argc < 2) { fprintf(stderr, "Error: must pass values to average"); return 0; } for (i = 1; i < argc; i++) { // convert command argument to int iScanfCount = sscanf(argv[i], "%ld", &iNum); // sscanf returns the number of successful formats if (iScanfCount < 1) { fprintf(stderr, "Invalid command argument: %s" , argv[i]); return -1; } dSum += iNum; } printf("%lf", dSum / (argc - 1)); return 0; } variables dataType variableName = initialValue; int iStudentCount; The intialization is optional. int iStudentCount = 0; Some of the data types: int iOrderQuantity = 0; int - integer (could be 2 or 4 bytes depending on implementation) double dAverage = 0.0; long - on most 32-bit machines, 4 bytes; on most 64-bit machines, 8 bytes char cLetterGrade = 'F'; float - 4 byte floating point int bEOFEncountered = 0; // 0 is false, non-zero // is true. double - 8 byte floating point char - single character; one byte To declare an array: dataType variableName[numberOfElments]; dataType variableName[] = {initialValueList}; Note that subscripts in C begin with 0. (Some languages have subscripts that begin with 1 such as COBOL and FORTRAN. PL/I by default begins with 1, but can be changed to any integer.) double dExamWeightingM[3] = {200.0, 200.0, 300.}; To declare a string of characters (note strings end with a zero byte terminator): char variableName[sizePlus1]; char variableName[] = initialValue; A zero byte is the constant '\0'. A literal character string surrounded in double quotes is automatically terminated with a zero byte. char szFirstName[21]; Note that arrays of characters do not have to be zero byte terminated, but if they aren't, several C functions do not work properly. We try to be clear in coding for whether the string is zero-terminated or not. Our convention: szName- string terminated by zero byte sbName - string not terminated by zero byte. It might contain binary data. #define NUMBER_OF_EXAMS 3 double dExamWeightingM[NUMBER_OF_EXAMS] = {200.0, 200.0, 300.}; double dExamWeightingM[] = {200.0, 200.0, 300.}; // max of 20 characters // plus zero byte char szFileName[] = "myInput.txt"; char szABC[] = {'A', 'B', 'C', '\0'}; char szABC[] = "ABC"; // automatically zero // byte terminated A B C \0 char sbDelims[] = {',', ' ', '\t', '\n'}; int iDelimCount = sizeof(sbDelims); printf("number of delims = %d\n", iDelimCount); if statement The if statement is the most important statement for flow control (as it is in most languages). Syntax options: if (conditionalExpression) truePart; if (conditionalExpression) truePart; else falsePart; Comparison operators: == equal to != not equal to > greater than < less than >= greater than or equal to <= less than or equal to Logical operators: && and || or ! not Warning! Warning! Warning ! == is the equivalence test operator. = is an assignment operator and must not be used for an equivalence test. && is the logical and. || is the logical or. A single & is a bitwise and. A single | is a bitwise or. Warning! Warning! Warning! comparing strings The equivalence operator (==) cannot be used to compare strings. The compiler would think it is comparing addresses. while statement The while statement continues to loop while the condition is true (not zero). if (cLetterGrade == 'W') { printf("last day to drop is %s\n", szDropDate); dCourseGradePoints = 0.0; dCourseCredits = 0.0; } if (dExamScore == 0) iScoreCount += 1; if (strcmp(szCommand,"DEPOSIT") == 0) dBalance += dAmount; else if (strcmp(szCommand, "WITHDRAWAL") == 0) { if (dBalance < dAmount) { printf("overdrawn\n"); return(ERROR_OVERDRAWN); } else dBalance -= dAmount; } Example of a common mistake: if (iCount = 3) That conditional is always true since an assignment returns its value (3) and 3 is not zero. Since some other programming languages (e.g., PL/I, SQL) use = for equivalence tests, this is a common mistake for people using multiple languages. if (szCommand == "DEPOSIT") would check to see if the address of szCommand is the same as the address for the literal "DEPOSIT". Use strcmp() or strncmp() for string comparisons. // read the student data until EOF (fgets returns null pointer) while (fgets(szInputBuffer, 100, pfileStudentData)!= NULL) { Syntax: while (conditionalExpr) whileBody; for statement The for statement is the iterative loop in C. Unlike Java, you cannot declare a variable in the (). for (initializationStmts; conditionalExpr; incrementStmts) forBody; When the for statement is encountered, the initalizationStmts are executed. The for loop continues while the conditionalExpr is non-zero. At the bottom of each iteration, the incrementStmts are executed. assigning values The = operator is used for assigning values. Strings cannot be assigned using the = operator in C. variableReference = valueExpr; Numeric operators: + plus minus * multiplication / division ++ increment by 1 unit -decrement by 1 unit % modulous (returns remainder) printf(%s\n", szInputBuffer); } // Print the names of students earning an A for (i = 0; i < iStudentCount; i++) { if (studentM[i].dGradeAvrage >= 90) printf("%s\n", studentM[i].szName); } double dAverage; dAverage = dSum / iCount; int iVal1 = 10; int iVal2 = 4; double dVal; dCircumference = 2.0 * PI * dRadius; if (iCount % 5 == 0) // look for a count that is a // multiple of 5 dVal = iVal1 / iVal2; Also, there are shortcuts for summing or subtracting values: variableReference += valueExpr; variableReference -= valueExpr; dBalance += dAmount; dBalance -= dAmount; // // // // This is an integer divide which is 10 / 4 with a truncated result (2). dVal is then 2.0 // deposit // withdrawal string assignments Strings are assigned values using strcpy(target, source); assigns a null terminated string to the target strncpy(target, source, length); assigns length characters from source to target. If the actual length of source is > length, the result in target won't be null terminated. If a null byte is encountered before length, no other characters are copied from source. char szWinnerFullName[15] = "Anita Break"; char szContestantFullName[15] = "Bob Wire"; strcpy(szWinnerFullName, szContestantFullName); Value of szWinnerFullName is B o b W i r e \0 a memcpy(target, source, length); assigns exactly length characters from source to target. Warning! Warning! Warning! string assignments can overwrite memory One of the most common and frustrating bugs in C is overwriting memory. char szName[10]; char szSpouse[] = "Anita Break"; strcpy(szName, szSpouse); k \0 ? ? ? sizeof and strlen sizeof ( thing ) is a compile-time function which returns the compile-time (not runtime) size of the thing. strlen ( variable ) returns the length of a null-terminated string. int iCount = 0; double dPrice = 10.5; char szNickName[21] = "champ"; struct Account { char szAccountNr[15]; double dBalance; } account = { "123456789", 100.20 }; printf("%-20s %-10s %-10s\n", "Thing", "sizeof", "strlen"); printf("%-20s %-10d %-10s\n", "iCount", sizeof(iCount), "n/a"); printf("%-20s %-10d %-10s\n", "dPrice", sizeof(dPrice), "n/a"); printf("%-20s %-10d %-10d\n", "szNickName", sizeof(szNickName) , strlen(szNickName)); printf("%-20s %-10d %-10d\n", "szAccountNr" , sizeof(account.szAccountNr), strlen(account.szAccountNr)); printf("%-20s %-10d %-10s\n", "dBalance" , sizeof(account.dBalance), "n/a"); printf("%-20s %-10d %-10s\n", "account", sizeof(account) , "n/a"); Output: Thing iCount dPrice szNickName szAccountNr dBalance account Exercise: Given a name, store the reverse of the name in another array. char szName[21] = "Perry Scope"; char szReversedName[21]; sizeof 4 8 21 15 8 24 strlen n/a n/a 5 9 n/a n/a switch statement The switch statement is used when there are options of what should be done that are dependent on the value of a variable. switch (variableReference) { case value: … // possibly many case value: statements; break; case value: … // possibly many case value: statements; break; default: statements; } Notes: There may be multiple case value clauses followed by statements. A break statement is necessary to specify branching to immediately after the switch statement. default statements are optional. If present, the default will execute if none of the case values match the value of the variableReference. switch (cLetterGrade) { case 'A': case 'B': printf("Better than Average\n"); printf("You are exempt from the exam\n"); break; case 'C': printf("About Average\n"); break; case 'D': case 'F': prinf("Below Average\n"); } break statement in for or while The break statement can also be used to exit a for or while statement. Unfortunately, if you have multiple nested looping statements, you can't specify which one to break out of. It always assumes the immediatley surrounding switch, while or for. // keep looping until a player wins while (TRUE) { iResult = takeTurnForPlayer(player1); if (iResult == PLAYER1_WINNER) break; iResult = takeTurnForPlayer(player2); if (iResult == PLAYER2_WINNER) break; // another example switch (cLetterGrade) { case 'A': case 'B': case 'C': case 'D': printf("You passed\n"); break; case 'F': printf("You failed\n"); break; default: fprintf(stderr, "unknown grade %c\n" ,cLetterGrade); } continue statement in for or while The continue statement allows you to skip the rest of the code in a loop and continue with the increment/test. It always assumes the immediatley surrounding while or for. } // keep looping until there is only one player left while (iNumActivePlayers > 1) { // get the next player iCurrentPlayer++; if (iCurrentPlayer > iNumPlayers) iCurrentPlayer = 0; // if player cannot move, skip him if (cannotMove(iCurrentPlayer, game) == TRUE) continue; // skip this player startTimer(iCurrentPlayer, game); iResult = takeTurn(iCurrentPlayer, game); if (iResult == WINNER_DETERMINED) break; prepareForNextPlayer(iCurrentPlayer, game); }