08-00-Strings of characters - Intro Defining a string How to define a variable to hold names of people with a maximum size name of 10 A string of characters is really an array of single characters. That means you need to define an array to hold 10 individual characters the same way as you would define an array that holds 10 individual integers or floats. char name [10] -- accept this for now …we will fix it later on page 3 This means 10 character size locations (4 bytes) are set up to store this information. The 10 elements of the character array as follows: If we store a name like MOLIBDENUM it would appear as follows M O L I B D E N U M If the next time we store only 4 letters, the character array would “theoretically” look like this T A R R B D E N U M When we printed out the name, we would expect to print TARR but it came out as TARRBDENUM The simple reason for that is there is no character that tells the printf where to stop printing. Document1 – rt 14 March 2012 1 08-01.c - Try this program cut and paste it and run it. This program demonstrates a 10 character string #include <stdio.h> /* 08-01.c - demonstrate getting and printing a string of characters */ main () { char name [10]; printf("\n\n\n"); printf("Enter a 10 character name : "); scanf ("%s", name); printf("\nYou entered [%s]\n", name); } // END OF MAIN Do the following: 1 Run the same program, but enter only 5 characters. 2 Run the program but enter 12 characters What happened? The 10 worked ok, the 5 worked AND so did the 12 character entry. We defined the length of the array as 10, but it still handled 12. *** When you entered 5, 10 or 12 characters you also pressed the enter key. That means you actually entered 6, 11 or 13 characters. 0 m 1 L 1 o 2 o 2 l 3 n Document1 – rt 3 i 4 g 4 b 5 n 5 d \0 a 6 e e m 14 March 2012 7 n n e 8 u u O 9 m m f 10 11 12 13 \0 1st entry into memory \0 2nd entry in same memory location m o r \0 3rd sample of long data 2 How does printf know when to stop on printout? The printf function looks for an ending character to tell it when to stop. That character is known as a NULL character to end the string of characters. NULL means the absence of any value. It does NOT mean zero. Zero has a value of zero. You can’t have a bit pattern that has nothing in it so the bit pattern is as follows: The bit pattern for 0 is 0010 1000 or DEC 48 or HEX 30 The bit pattern for 1 is 0010 1001 or DEC 49 or HEX 31 The bit pattern for NUL is 0000 0000 or DEC 0 or HEX 00 <== note the character is called NUL but in English it is written as NULL This means IF the maximum input can be 10 meaningful characters then you must leave an extra space for the NULL or ‘\0’ character. Therefore, we should define the variable as follows: char name [11] remember on page 1, I said I would fix it The array above would then look as follows M O L I B D E N U M \0 N U M \0 Whenyou next insert a new value the \0 is added at the end T A R R \0 D E Notice that the previous characters are still there but the second printf will stop at the first \0 Document1 – rt 14 March 2012 3 Demonstrate the NULL effect OR How to demonstrate what it holds in the array #include <stdio.h> /* Program does 1 Demonstrate getting and printing a string of characters and the effect of the NULL character 2 Print out what is in the locations using a for loop*/ void pause (void); int main () { char name [11]; // allow 10 plus null int x; printf("\n\n\n"); printf("Enter a 10 character name : "); scanf ("%s", name); printf("\nYou entered these 10 characters [%s]\n", name); pause(); printf("\nEnter a 5 character name : "); scanf ("%s", name); printf("\nYou entered these 5 characters [%s]\n", name); for (x=0; x<11;x++) // this will print out every position printf (“\nIn position %d is … %c ”, x, name[x]); printf(“\n\nLook at the NON-printable character in position 5\n\n”); return 0; } void pause (void){ // this function allows me to pause on the screen while (getchar() != '\n'); // clears the buffer looks for ENTER key printf ("\n\n\nPause .... hit any key\n\n\n"); while (getchar() != '\n'); // clears the buffer } Document1 – rt 14 March 2012 4 How to load data into an array of characters Hard coded int main () { char name [11]= “Molibdenum”; this is one way of hard coding it OR .. just like you load integer arrays you do it 1 value at a time with SINGLE quotes int main () { char name [11]= {‘M’,’o’,’l’, … ‘m’}; another with scanf() Notice the scanf scanf ("%s", name); %s – a new placeholder to define a string input of any length name– Notice that there is not an & in front of the variable name. This is because scanf is looking for an address and the name of an array is the beginning address of an array I also found that the &name will work just as well since it is also the start of the array To get the start of one of the parts of an array you need to do &name[3] Document1 – rt 14 March 2012 5 How to limit input to the variable scanf (“%5s”, name) This will only insert 5 of the letters into the variable name. If you typed in 15 characters, only the first 5 will go into the array leaving the remainder in the buffer. Note, this may cause problems when a later scanf is executed as it will take what is still in the buffer How do we printout only some of the string? Left and Right Justify Run this program and see what you understand. #include <stdio.h> /* 08-05.c display only some of the string void */ pause (void){ /* this function allows me to pause on the screen */ char waits; while (getchar() != '\n'); printf ("\n\n\nPause .... hit any key\n\n\n"); scanf("%c", &waits); while (getchar() != '\n'); } int main () { char name1 [11]="1234567890"; // load 10 characters into name1 printf("\n\n\n"); printf("\nDisplay value in name1 printf("\nDisplay 3 values using 3s [ %s ]", name1); [ %3s ]", name1); printf("\n\n NOTICE that 3s did not control the printout, the null does"); printf("\n\nDisplay 3 values using .3s pause(); [ %.3s ]", name1); printf("\n\nDisplay 3 values using 10.3s [ %10.3s ]", name1); printf("\nDisplay 3 values using -10.3s [ %-10.3s ]", name1); printf("\n\nNotice what worked and how to do left and right justified\n"); pause(); printf("\nDisplay 3 values using 5.3s [ %5.3s ]", name1); printf("\nDisplay 3 values using -5.3s [ %-5.3s ]", name1); printf("\n\nNotice left and right justified are a smaller size of field\n\n\n"); return 0; } Document1 – rt 14 March 2012 6 How to output a string One character at a time 1 for (ctr = 0; a_string[ctr] ; ctr++) { printf(“%c”, a_string[ctr]); } NOTE:strange termination statement a_string[0] or any index value points to a location with content any content will result in the statement evaluated as TRUE except the null character stored at the end of the string evaluates to FALSE How to output the whole string 2 printf(a_string); The first argument to printf is a string How to do it the way we have in the past 3 printf(“\n %s” , a_string); Document1 – rt 14 March 2012 7 String Functions you need to know strcpy() strcat() All require the string.h strcmp() strlen() strcpy() Copies one string to another, therefore, needs 2 arguments Caution on the order of the arguments strcpy( to , char TO .... FROM from ); a_string[20], b_string[20]; strcpy(a_string, “hello”); to A -- from a string in quotes strcpy(b_string , a_string); to B -- from A NOTE: Document1 – rt Again no bounds check, so receiver should be the same or bigger than the from string 14 March 2012 8 /*08-strcpy.c demonstrates strcpy */ #include <stdio.h> #include <string.h> void pause (void){ // this function allows me to pause on the screen printf ("\n\n\nPause .... hit any key\n\n\n"); while (getchar() != '\n'); // clears the buffer } main() { char a_string[6]; /* holds 5 maximum plus null */ printf ("\n\nThe array called a_string has no initial value %s ", a_string); pause(); strcpy(a_string, "hello"); printf("\n\n\nThe strcpy function copied hello to a_string\n\n"); printf(a_string); printf("\n\n\n"); pause(); } Document1 – rt 14 March 2012 9 strcat() It adds the contents of the FROM to the contents of the TO CAUTION: The TO must be large enough to hold its current contents and the appending or concatenating contents of FROM char x_string [80]; strcpy (x_string, “First I learn by reading”); strcat (x_string, “ and then by trying ALL the programs”); printf (x_string); /*08-strcat.c*/ #include <stdio.h> #include <string.h> // don't forget this header main() { char x_string[80]; } Note the space before the first word so the result looks good Used copy first then concatenate strcpy(x_string, "First I learn by reading"); strcat (x_string, " and then by trying ALL the programs"); printf ("\n\n\n"); printf (x_string); printf ("\n\n\n"); Notice how printf is done Document1 – rt 14 March 2012 10 strcmp() Compares 2 strings strcmp(s1, s2); If the strings are the same If s1 is greater than s2 If s1 is less than s2 returns 0 returns greater than 0 returns less than zero The comparison is NOT based on length The comparison is done lexicographically -- dictionary order a is less than b in the alphabet - see ASCII codes therefore a is lowest and z is highest example: all is less than none printf(“%d”, strcmp(“one”, “one”) ); -- what is printed NOTE: If you were compare two letters a and b the difference is 1. The difference between a and c is a difference of 2 etc. Try this program. #include <stdio.h> #include <string.h> /* 08-strcmp.c display only some of the string */ main () { char name1 [5]="aaaa", name2[5]="aaaa", name3[5]="xxxx"; int x; printf("\n\n\n"); printf("\nDisplay value in name1 [ %s ]", name1); printf("\nDisplay value in name2 [ %s ]", name2); printf("\nDisplay value in name3 [ %s ]", name3); printf("\n\n\n"); x = strcmp(name1,name2); printf("\n\nComparing name1 to name2 gets the answer %d", x); x = strcmp(name1,name3); printf("\n\nComparing name1 to name3 gets the answer %d\n\n",x); x = strcmp(name3,name1); printf("\n\nComparing name3 to name1 gets the answer %d\n\n",x); } Document1 – rt 14 March 2012 11 strlen() Returns the length of the string NOT including the null terminator strlen(x_string); #include <stdio.h> #include <string.h> /* strlen.c main () { char int x; printf printf printf printf printf display the length of the string */ name1[5]="aa", name2[5]="aaa", name3[5]="xxxx"; ("\n\n\n"); ("\nDisplay value in name1 ("\nDisplay value in name2 ("\nDisplay value in name3 ("\n\n\n"); [ %s ]", name1); [ %s ]", name2); [ %s ]", name3); x = strlen (name1); printf("\n\nLength of string name1 %d\n\n", x); // NOTE: the different way of burying a function in a function printf ("Length of each is %d %d %d \n\n", strlen(name1), strlen(name2), strlen(name3)); } Document1 – rt 14 March 2012 12 Arrays (numeric) with functions Here is a program that has a hard coded array, calls a function to make changes. Cut and paste it and make other changes to get practice // change data in an array inside a function // demonstrates passing data back and forth void add_2_array (int score []); main() { int score [5]={1,2,3,4,5}, ctr; for ( ctr = 0 ; ctr < 5 ; ctr ++ ) { printf("\nDisplay scores loaded in main to start ==> the score[%d] %d",ctr, score[ctr]); } add_2_array (score); for ( ctr = 0 ; ctr < 5 ; ctr ++ ) { printf("\nMain AFTER changed by function==> the score[%d] score[ctr]); } getchar(); getchar(); %d",ctr, }/* END OF MAIN */ void add_2_array (int score []) { int x; for (x=0;x<5;x++) { printf ("\n in function BEFORE change %d", score[x]); } for (x=0;x<5;x++) { score[x] = score [x] +12; printf ("\n in function %d", score[x]); } } Document1 – rt 14 March 2012 13 Do the same for character arrays Changed in a function You can use the following code to start with or you can write your own. int main() { int name [5] = {“abcde”}, ctr; for ( ctr = 0 ; ctr < 5 ; ctr ++ ) { printf("\nCharacters before function=> the name[%d] } %d",ctr, name[ctr]); Change_name (name); for ( ctr = 0 ; ctr < 5 ; ctr ++ ) { printf("\nInn main AFTER changed by function==> the name[%d] name[ctr]); } getchar(); getchar(); %d",ctr, return 0; } Document1 – rt 14 March 2012 14