370 likes | 380 Views
Test:. write a function which takes an integer N as input, dynamically allocates an array of N integers, and initializes the array (see the following examples) and returns the pointer to this array. N = 10:. N = 11:. A Simple Solution:. int * f(int n){ int *p, *sp, *ep;
E N D
Test: • write a function which takes an integer N as input, dynamically allocates an array of N integers, and initializes the array (see the following examples) and returns the pointer to this array. N = 10: N = 11: Strings, Structures
A Simple Solution: int * f(int n){ int *p, *sp, *ep; if ((sp = p = malloc(int(n))) != NULL){ ep = sp + n – 1; n = 1; while (sp <= ep) { *sp++ = *ep-- = n++; } } return p; } Strings, Structures
Strings: • A string is an array of characters, terminated with a trailing null character, ‘\0’. char *s = “CIS 2650”; char *q; q = “Enter YES or NO: ”; q Strings, Structures
String Variables: • A string variable is created by allocating an array of characters: char s[5] = {‘s’, ‘t’, ‘o’, ‘p’, ‘\0’}; char t[3]; t[0] = ‘N’; t[1] = ‘O’; t[2] = ‘\0’; // must explicitly provide the space // for trailing null. Strings, Structures
Example: #include <stdio.h> #include <ctype.h> #define MAXSTRING 100 int main(void){ char c, name[MAXSTRING]; int i, sum = 0; printf(“\nHi! What is your name?”); for (i = 0; (c = getchar()) != ‘\n’; ++i){ name[i] = c; if (isalpha(c)) sum += c; } name[i] = ‘\0’; printf(“\n%s%s\n%s%d”, “Nice to meet you ”, name, “The letters in your name sum to ”, sum); } Strings, Structures
Assignment Operator: • Assignment in C is an operator: a = (b = 2) + (c = 3); a = b = c = 0; (c = getchar()) != ‘\n’ c = getchar() != ‘\n’ // are they same? Strings, Structures
Problem Solving: Counting Words: #include <ctype.h> int word_cnt(const char *s){ int cnt = 0; while (*s != ‘\0’){ while (isspace(*s)) ++s; if (*s != ‘\0’){ ++cnt; while(!isspace(*s) && *s != ‘\0’) ++s; } } return cnt; } Strings, Structures
Standard String Functions: • Commonly used standard string functions: string.h char *strcat(s1, s2) //cancatenate s2 to s1, return s1 char *strcpy(s1, s2) // copy s2 to s1, return s1 int strcmp(s1, s2) // compares s1 and s2 (-, 0, +) size_t strlen(s) // return num of chars (not ‘\0’) char* strchr(s, c) // return a pointer to the first c in s char* strstr(s1, s2) // return a ptr to the first s2 in s1 char* strspn(s1, s2) // return length of prefix of s1 // consisting of characters in s2 // and more … Strings, Structures
Example: p q char* bp; if ((bp = strchr(p, ‘ ’)) == NULL) error(…); // print error msg strcpy(q, bp + 1); // make the last name first strcat(q, “, ”); // append a comma *bp = ‘\0’; // terminate p at the end of first name strcat(q, p); // put first name last Strings, Structures
Additional String Functions: • stdio library provides two functions, extensions to printf and scanf, allow I/O from/to a string: sprintf and sscanf. char* bp; if ((bp = strchr(p, ‘ ’)) == NULL) error(…); // print error msg strcpy(q, bp + 1); // make the last name first strcat(q, “, ”); // append a comma *bp = ‘\0’; // terminate p at the end of first name strcat(q, p); // more compact with sprintf *bp = ‘\0’; sprintf(q, “%s, %s”, bp + 1, p); Strings, Structures
Example: strcpy // version 1: char* strcpy(char* s1, char* s2){ int i; for (i = 0; (s1[i] = s2[i]) != ‘\0’; i++); return s1; } // version 2: char* strcpy(char* s1, char* s2){ char* tp = s1; while(*tp++ = *s2++); return s1; } Strings, Structures
Pointer version vs. Array version: #include <stdio.h> int getline1(char line[]; int max){ // array version int c, i = 0; while ((c = getchar()) != ‘\n’ && c != EOF) if (i < max) line[i++] = c; line[i] = ‘\0’; return (c==EOF) ? –1 : i; } Int getline2(char *p, int max){ // pointer version int c; char *sp = p, *ep = p + max; while ((c = getchar()) != ‘\n’ && c != EOF) if (p < ep) *p++ = c; *p = ‘\0’; return (c==EOF) ? –1 : p – sp; } Strings, Structures
// Simple calculator (use getline) #include <stdio.h> #include <stdlib.h> #define MAXLEN 80 int main(){ double op1, op2, result; char operator, input[MAXLEN + 1]; while (getline(input, MAXLEN) != -1) if (sscanf(input, “%lf%c%lf”, &op1, &operator, &op2) != 3) printf(“Input line in error.\n”); else { switch (operator){ case ‘+’: result = op1 + op2; break; case ‘-’: result = op1 – op2; break; case ‘*’: result = op1 * op2; break; case ‘/’: result = op2 != 0.0 ? op1/op2 : 0.0; break; default: printf(“Unknown operator: %c\n”, operator); continue; } printf(“%f\n”, result); } } Strings, Structures
Prototypes for useful string functions: • Standard library provides a set of useful string functions, but they tend to be difficult to use and hard to remember. • You might redefine these utilities by your own package on top of the standard library. • These prototypes might be less general but significantly clearer and easier to understand than code that directly uses library functions. Strings, Structures
Example: // A package header file (sutils.h) #include <string.h> char *firstNonBlank(char* s); char *lastNonBlank(char* s); void stringLower(char *s); void stripBlanks(char* s); int emptyString(char* s); int stringEqual(char* s1, char*s2); Strings, Structures
// An implementation (sutils.c) #include “sutils.h” static const char *Spaces = “ \t”; int stringEqual(char* s1, char* s2){ return strcmp(s1, s2) == 0;} int emptyString(char* s){ return *s == ‘\0’; } char* firstNonBlank(char* s){ return s + strspn(s, Spaces);} void stringLower(char* s){ // lowercase string for ( ; *s; s++) *s = tolower(*s); } Strings, Structures
char* lastNonBlank(char* s){ // return ptr to just past last non-blank int len = strlen(s), i = len; while (--i > 0) if (s[i] !=‘ ’ && s[i] != ‘\t’) return &s[i+1]; return s + len; } void stripBlanks(char* s){ // remove leading/trailing blanks *(lastNonblank(s)) = ‘\0’; strcpy(s, firstNonBlank(s)); } Strings, Structures
Structures: • The structure type allows the programmer to aggregate components into a single, named variable. • A structure has components (called members or fields) that are individually named. • Members of a structure can be various types. Strings, Structures
Structure Definition: • Key word struct with the name of the structure type (called the structure tag) and declarations for each member it contains. For example struct employee { long number; char name[MAXNAME]; char phone[MAXDIGITS]; int age; }; Strings, Structures
More Examples: struct card { int value; char suit; }; struct vegetable { int name[15]; int calories; }; Strings, Structures
Declaring Structure Variables: • There are two ways to declare structure variables: 1). Separate type definition and variable declaration, or 2). Create a type and declare variables at the same time. struct card c1, c2, deck[52]; struct student { // structure tag is optional unless… char lastname[20]; int sid; char grade; } s1, s2, s3; Strings, Structures
Define A New Type: • Recall that typedef allows us to define synonyms for existing types. We can use it to define new structured types. typedef struct { int month, day, year;} Date; typedef struct {int value; char suit;} Card; Date d1, birthday; Card c1, deck[52]; Strings, Structures
Accessing Structure Fields: • To access a field (member), we follow the structure variable name with the field selection operator ‘.’, and the name of the desired field. c1.value = 10; // c1 is a Card c1.suit = ‘h’; strcpy(s1.name, “Smith”); // s1 is a Student s1.sid = 200300001; Strings, Structures
Another Example: struct employee { long number; char name[MAXNAME]; char phone[MAXDIGITS]; int age; } emp; emp.number = 1001; emp.age = 29; strcpy(emp.name, “Franklin, Tammy”); strcpy(emp.phone, “714-888-8888”); Strings, Structures
Nested Structures: • The fields within a structure can have any legal type, which means they themselves can be structures. // declaration struct person { Date birthday; char name[MAXNAME]; } p1; // accessing p1.birthday.month = 10; p1.birthday.day = 21; Strings, Structures
Structure Initialization: • A structure variable is initialized by a list containing values for each of its fields (these values must be evaluable at compile time). struct student s1 = { “Smith”, // name 20030001, // sid 0 }; // grade Strings, Structures
Structures As Arguments: • Structures can be passed to functions as arguments. • Structure arguments are passed by value (a copy of the structure is assigned to the corresponding parameter). • When the structure is changed inside a function, the original structure has no effect. • If you do want to change a structure by calling a function, then you have to pass its pointer to the function. Strings, Structures
Example: // pass by value (using field selection operator . to access fields) void writeEmp1(struct employee e){ printf(“Employee: %li\n”, e.number); printf(“Name: %s\n”, e.name); printf(“Age: %i\n”, e.age); } // pass by pointer (using structure pointer operator -> to access fields) void writeEmp2(struct employee *ep){ printf(“Employee: %li\n”, ep->number); printf(“Name: %s\n”, ep->name); printf(“Age: %i\n”, ep->age); } Strings, Structures
Relationship of -> and . : struct employee emp = {1001, “Franklin, Tammy”, “714-888-8888”, 29}; struct employee *ep = &emp; ep -> age = 30; emp.age = 30; (*ep).age = 30; (&emp) -> age = 30; Strings, Structures
Structures and Operators: • sizeof operator determines the number of bytes used by a structure. sizeof(emp) // using a variable sizeof(struct employee) // or using a type • Don’t assume the size of a structure is the sum of the size of its fields. sizeof(emp.number) + sizeof(emp.name) + sizeof(emp.phone) + sizeof(emp.age) sizeof(emp) Strings, Structures
Structures and Operators: • Assignment operator = applies to structures which copies the contents of one structure into another. struct employee newemp = emp; • No operators for comparing structures. (newemp == emp) // wrong Strings, Structures
Arrays of Structures: // built a student record struct student stab[SIZE]; stab[0].sid = 20030001; stab[0].grade = 88; strcpy(stab[0].name, “Smith”); … // initialize the array at declaration struct student stab[] = { {“Smith”, 20030001, 88}, {“Perl”, 20030002, 78}, {…}, … }; Strings, Structures
Accessing a structure array: void printStudents(struct student *sp, int n){ struct student *ep = sp + n; while (sp < ep){ printf(“Name: %s\n, SID: %li\n, Grade: %s\n”, sp->name, sp->sid, sp->grade); sp++; // advance to the next record } } // suppose we have a stab initialized with 5 records printStudents(stab, 5); Strings, Structures
Unions: • A Union may contain one of many different types of values, but can store only one value at a time. • A Union type is defined by a keyword union with an optional union tag and the alternative names and types it may hold. // a union which may contain either a char, an integer or a double union number { char c; int n; double d; }; union number x1, x2, x3; Strings, Structures
Union variables: • Union variables are declared the same as structure variables. We also use the dot operator to access a union’s individual fields. Note: don’t assign to one field of a union and then access another. x1.c = ‘A’; x2.n = 123; x3.d = 99.87; if (x1.d == 56.2){ // wrong, x1 holds a char now } x1.d = 55.3; // change to another alternative if (x1.d == 56.2) { // OK } Strings, Structures
Enumerated Types: • Enumerated type is used to specify a small range of possible values. • A enumerated type is defined by giving the keyword enum followed by an optional type designator and a brace-enclosed list of identifiers. enum color {BLUE, RED, WHITE, BLACK}; enum myType { STRING = 2, INTEGER = 0, REAL}; • The list of ids represent a list of constants equal to their position in the list; or user may assign special values to ids in the list. The default value for item is 1 more than the item preceding it. Strings, Structures
Enumerated Types: • Use enumerated type whenever a variable will hold only a small set of integer values. typedef enum color Color; Color currentColor = BLUE, oldColor; if (oldColor == RED) { … } Strings, Structures