CPS 125 Alexander Ferworn Week 8 Strings and Multidimensional Arrays What we will cover this week o Strings o Multidimesional Arrays Strings -------- o In C, a string is an array of characters terminated with a null character. o The null character is \0 (back-slash zero). o A string constant (or literal) is any series of characters enclosed in double quotes. o Each character in a string takes up one byte. o The compiler automatically puts the null character on the end of the characters for you o Null characters are treated as false (zero) in expressions. Initializing Strings --------------------- Example char str[]="some text"; o Compiler would assign str[] to be one element larger than the string literal. o This is the same as; char str[10]="some text"; o You must declare enough space to hold the null character. o You can also do it with a string pointer; char *ptr = "more text"; Problems you will face ------------------------ /* a problematic example */ /* note a string is not te same as a character */ void main() { char array[10]; char *ptr1 = "10 spaces"; char *ptr2; array = "not ok"; /* cannot assign to an address */ array[5] = 'A'; /* OK */ ptr1[5] = 'B'; /* OK */ *ptr2 = "not ok"; /* type mismatch */ ptr2 = "ok"; /* ptr2 now points to ok */ *ptr2 = 'a'; /* ok */ ptr2 = 'a'; /* not ok */ *ptr2 = "a"; /* nope a is a string */ } Reading and Writing Strings ---------------------------- o To read and write strings use the %s format specifier Example /* read a string into the char array str[] and output it*/ ... char str[80]; scanf("%s",str); printf("%s",str); ... The String Length Function --------------------------- o There is no magic in a string...it's just an array o Here is a function to return the length of a string int strlen(char str[]) { int j=0; while(str[j]) j++; return j; } /* slightly different */ int strlen(char str[]) { int j; for(j=0;str[j];j++); return j } /* a pointer version */ int strlen(char *str) { int j; for(j=0;*str++;j++); return j; } o *str++ both * and ++ have the same precedence so they are right to left associative The String Copy Function -------------------------- o To copy a string you must move one element of the array at a time. void strcpy(char s1[],char s2[]) { int j; for(j=0;s1[j];j++) s2[j] = s1[j]; s2[++j] = '\0'; /* ++j evaluates first then the address of s2 is determined */ } /* using pointers */ void strcpy(char *s1, char *s2) { int j; for(j=0; *(s1+j); j++) *(s2+i) = *(s1+j); s2[++j] = '\0'; } /* the screamer but hard to understand code */ void strcpy(char *s1, char *s2) { while(*s2++ = *s1++); } Some More Useful String Functions ---------------------------------- o strcat(s1,s2) -- appends a copy of string s2 onto the end of string s1 /*EXAMPLE strcat() use */ #include <stdio.h> #include <string.h> void main() { char s1[25] = "hello "; char *s2 = "world"; printf( "Before strcat(): s1 = \"%s\"\n", s1 ); strcat( s1, s2 ); printf( "After strcat(): s1 = \"%s\"\n", s1 ); } produces Before strcat(): s1 = "hello " After strcat(): s1 = "hello world" o strchr(s1,c) -- look for character c in string s1 return pointer to this character /* EXAMPLE strchr() use */ #include <stdio.h> #include <string.h> void main() { char s[20] = "Alex Ferworn"; char c = 'F'; printf( "s = \"%s\"\n", s ); printf( "c = '%c'\n", c ); printf( "strchr(s,c) = \"%s\"\n", strchr(s,c) ); } produces s = "Alex Ferworn" c = 'F' strchr(s,c) = "Ferworn" o strstr() -- finds the first occurrence of one string in another /* EXAMPLE strstr() */ #include <stdio.h> #include <string.h> void main() { char *string = "scatter"; char *substring = "tt"; char *result; result = strstr( string, substring ); printf( "strstr(\"%s\",\"%s\") == \"%s\"\n", string, substring, result ); } produces; strstr("scatter","tt") == "tter" o strcmp() -- compares two strings see the example at the end of these notes Multidimensional Arrays, The Basics ------------------------------------ o An array of arrays is a multidimensional array. o C supports as many dimesions as you can think of. Example: The magic square 17 24 1 8 15 23 5 7 14 16 4 6 13 20 22 10 12 19 21 3 11 18 25 2 9 static int magic [5][5] = { {17,24,1,8,15}, {23,5,7,14,16}, {4,6,13,20,22}, {10,12,19,21,3}, {11,18,25,2,9} }; o To access an element in a multidimensional array, you specify as many subscripts as necessary. o Stored in row-major order, means the last subscript varies the fastest. For exampe, let's store the magic square. o When initializing a multidimensional array, you may enclose each row in braces. o If there are too few intializers, the extra elements in the row are initialized to zero. loc 000 001 002 003 004 005 006 007 008 009 010 011 012 013 ... val 17 24 1 8 15 23 5 7 14 16 ... Making it messy with pointers ------------------------------- o Suppose we had the following declaration; long array[2][3] = {{0,1,2},{3,4,5}}; o The array reference array[1][2] is the same as *(array[1] + 2) is the same as *(*(ar+1)+2) ... neat trick eh? Avoiding a problem with syntax o Watch out for the following; array[1][2] not array[1,2] even though both are legal, the first is an array reference and the second uses the comma operator and probably doesn't do what you want. Passing Multidimensional Arrays as Arguments --------------------------------------------- Here is an example of how to do it; ... void main() { float array[5][6][7]; func0(array); func1(array,5,6,7); } func0(float received_arg[][6][7]) /* the compiler interprets this as float (*received_arg)[6][7]; */ { ... } func1(float ***receive_arg, int row, int col, int plane) /* welcome to the world of pointer math */ { ... } o Exercise (which I suggest you do!!!) ----------------------------------------- Write a C function which takes as arguments 3 matrices. The first will have dimensions n rows by m columns and the second will have dimensions m rows by n columns and the third will have n rows and n columns. Muliply the first by the second and store the result in the third array. o An example using both 2D arrays and strings /* Example: a program to sort a file of at most MAX_NUM words into ascending order and output each unique word. First the file is echoed to stdout */ #include <string.h> #include <stdio.h> #define MAX_SIZE 81 #define MAX_NUM 1000 void main() { char words[MAX_NUM][MAX_SIZE]; /* array to hold strings (words) */ char *wordptr[MAX_NUM]; /* array to point at contents of previous array */ int counter=0,i,sorted=0; char *temp; while(scanf("%s",words[counter]) != EOF) /* read words until EOF */ { printf("%s ",words[counter]); /* echo the file to stdout */ wordptr[counter] = words[counter]; /* set up the pointer */ counter++; } while(!sorted) /* bubble sort the pointers */ { sorted = 1; for(i=0;i<counter-1;i++) if(strcmp(wordptr[i],wordptr[i+1]) > 0) /* strcmp(s1,s2) compares the strings s1 and s2, if s1 is bigger it returns a positive integer, if the same it returns zero and if smaller it returns a negative integer */ { sorted = 0; temp = wordptr[i]; wordptr[i] = wordptr[i+1]; wordptr[i+1] = temp; } } printf("\n\n"); temp = "E4Mna1@"; /* set temp to something that won't be in the file */ for(i=0;i<counter;i++) /* go through list */ if(strcmp(temp,wordptr[i])) /* if this is not the same as last word print it */ { printf("%s\n",wordptr[i]); strcpy(temp,wordptr[i]); /* change temp to be current word */ } } o Exercise: Improve the program by making the part that sorts into a function