C style Arrays and  C strings

Chapter 11 Weiss

Chapter 7 Lafore

C strings

•      C strings are arrays of characters, terminated by a null ‘\0’

–   They may also be called char* strings because they can be represented as pointers to type char

•      Strings can be either a variable or a constant

–   If they are constant, they cannot be changed

 

Reading C strings

•      The >> operator works with cin just as it did for string objects

–    It reads until it hits a white space

•      To read C strings with embedded blanks

–    Use a member function of the istream class get( )

–    It is used with the object cin, which is an object of the istream class:  cin.get(strName, num)

•    Num is the number of spaces in the strName char array.

•      cin.get( ) takes three arguments, the default for the third is ‘\n’

•      If you want to read multiple lines, then enter the third argument.  It should be the delimiter you want to indicate the end of input.

 

Example using cin.get( )

•      #include <iostream>
using namespace std;

•     
int main( )
   {
   const int MAX = 80;        //max characters in string
   char str[MAX];                //string variable str

   cout << "\nEnter a string: ";
   cin.get(str, MAX);               //put string in str
   cout << "You entered: " << str << endl;
   return 0;
   }

 

Manipulating C strings

•      The string-handling library has several useful functions

strcpy(str1, const str2) copies str2 into str1; returns str1

strncpy(str1, const str2, n) copies at most n characters from str2 into str1; returns str1

strcat(str1, const str2) appends str2 to str1; returns str1; the ‘\n’ in str1 is overwritten

strcmp(const str1, const str2) returns an int; 0 if strings equal, neg if str1<str2, positive if str1>str2

strtok(str1, const str2) a series of calls to strtok breaks  the string into tokens; the second arg is the delimiter

 

Example using strtok( )

•      #include <iostream>  #include <cstring>  
using namespace std;

•      int main( )
{  char cstring[ ] = "This is a sentence with 7 tokens";
    char *tokenPtr;

   cout << "The string to be tokenized is:\n" << cstring
        << "\n\nThe tokens are:\n";

   tokenPtr = strtok( cstring, " " );  // note the second arg

•         while ( tokenPtr != NULL )    {
          cout << tokenPtr << '\n';
          tokenPtr = strtok( NULL, " " );    }
   return 0;
  }

 

How strtok( ) works

•      The first call to strtok: tokenPtr = strtok( cstring, " " );

–   contains two arguments,

•    a string to be tokenized and

•   a delimiter (a string, not a character)

–    It then finds the next delimiting character and replaces it with a null to terminate the first token

–    It returns a pointer to the current token (to tokenPtr)

–    It saves a pointer to the next character following the token (the null)

•      The second (and subsequent) calls to strtok

–    Start with the pointer pointing to the null that it inserted, and looks for the next delimiter

 

 

How arrays are different than vectors

•      Arrays don’t know how big they are

–    Vectors have a member function size( ) to keep track of how many items in the vector

•      Arrays must be copied item by item in a loop

–    Vectors have overloaded the assignment statement so vect1 = vect2 does an item by item copy (deep copy)

•      The size of a static array must be know at compile time

–    Vectors are dynamically allocated

 

Static allocation of arrays

•      The array is stored on the stack

•      You do not have to worry about memory leaks

•      The memory is reclaimed automatically when the array goes out of scope

–   An array goes out of scope when the block in which it was declared is exited.

•   If it is declared in main, it says in scope for the entire life of the program

•   If it is declared in a function, it is in scope only while the function executes.

•      If main calls a function that statically creates an array,

–   when the function returns, the memory that the array was using is automatically returned to the OS

–   i.e. the array no longer exists, and cannot be returned

 

Dynamic allocation of arrays

•      The memory used is on the heap, and must be managed by the programmer

–    The name of the array is still on the stack, so stays in scope as long as its block is in scope

•      Memory for the array is allocated with the new operator

•      The memory is given back to the OS using the delete operator

•      Declaring an array dynamically:
   
int *aRay = new int[size]

•      size can be a variable whose value is unknown at compile time.

 

Deallocating dynamic arrays

•      When you declare an array  with the statement int *aRay = new int[size]
     
you deallocate with delete[ ] aRay

–   If you do not use the [ ], it is possible only the first element of the array’s memory will be deallocated.

•      Suppose main calls a function that declares a dynamic array,

–   then the pointer to the array is returned to main

–   It would up to main to delete the array, even though it has not created it.

 

Code to dynamically enlarge an array

•      This code starts out with an array of size 1

–    Starting with an array so small is not practical, but we do it here to watch the array size increase

•      Any number of integers are read into the array, until a -1 is entered

•      When the array becomes full, its size is roughly doubled

•      Look at the while loop and if statement

–   When does the while loop terminate?

–   When do you go through the if statement?

            scanf("%lf", &x[i]);