There is no easy way to initialise a list so we'll just set it from the strings array.
// append adds items on to the end of a list for (unsigned int i1 = 0; i1 < sizeof(strings) /sizeof(strings[0]); i1++) slist.append(strings[i1]); // add item to start of list slist.prepend("dove"); // find pointer to "eagle", add "hawk" before it, and then add sparrow // after "hawk" for (p = slist.head(); p != 0; p = next(p)) if (slist(p) == "eagle") { p = slist.insert_before(p,"hawk"); p = slist.insert_after(p,"sparrow"); } |
A dummy pointer of type \Ref{EST_Litem} is used to iterate through a list. This acts somewhat like the index in an array in that it is used to access an item, in the list but does not contain a value itself. Iteration is usually done in a for loop. Initialisation involves setting the pointer to the head() function. Increments are done by the next() function. At the end of the list, the pointer will be set to null, and this can be used to check for the end. Items in the list are accessed by passing the pointer is as the argument to the function operator(), as in the following example.
cout << "[ List Accessed by LItem\n"; // print out contents of array. for (p = slist.head(); p != 0; p = next(p)) cout << " " << slist(p) << "\n"; cout << "]\n"; // items can also be accessed by their position in the list by using the // nth() function. The length() function returns the number of items // in a list. cout << "\n[ List Accessed by integer index\n"; for (int i2 = 0; i2 < slist.length(); ++i2) cout << " " << slist.nth(i2) << "\n"; cout << "]\n"; |
The normal way to access an item is to use the \Ref{EST_Litem} in conjunction with the () operator. Other functions also exist, eg. first(), last() and nth(). Const and non-const version of each access function exist, allowing both reading and writing.
// Capital;ise all 'e's in all strings for (p = slist.head(); p != 0; p = next(p)) slist(p).gsub("e", "E"); // print out last item in list p = slist.tail(); cout << "Last item: " << slist(p) << endl; // but a more direct method is cout << "Last item: " << slist.last() << endl; // likewise with the head of the list: cout << "First item: " << slist.first() << endl; // print out the 4th item: cout << "4th item: " << slist.nth(4) << endl; // All these can be used for overwriting existing members in the list. // To add new members use append(), prepend(), insert_before() or // insert_after() as shown in \Ref{Addition} slist.first() = "Swallow"; slist.last() = "TurkEy"; slist.nth(2) = "SEagull"; |
Removing items from lists is done by having the EST_Litem point to a particular item, and then passing this pointer to the remove function. This can be tricky as this leaves the EST_Litem pointer pointing to a non-existant item. To get round this, the remove() function returns a pointer to the previous item in the list.
In the following example, the item "eagle" is removed and a pointer to the previous item is returned. The for loop then points this to the next item in the loop, giving the appearance of seamless iteration.
for (p = slist.head(); p != 0; p = next(p)) if (slist(p) == "EaglE") p = slist.remove(p); |
A number of sort routines for lists are defined. The most useful are probably sort (a simple bubble sort, quick for small lists) and qsort (quick-sort, faster for long lists). If the default collation order is not what you want you can pass a comparison operator to the sort routine.
Sort into alphbetical order */ //@{ code sort(slist); //@} code cout << "\n[ Sorted\n"; for(p=slist.head(); p ; p=next(p)) cout << " " << slist(p) << "\n"; cout << "]\n"; /** Sort by second character
qsort(slist,&second_char_gt ); |
EST_TMatrix<float> m(10, 5); |
Access to values in the matrix is via the a() member function. This returns a reference, so you can assign values to matrix cells. As is usually the case in C++, column and row indecies start from 0.
for(int i=0; i<m.num_rows(); i++) for(int j=0; j<m.num_columns(); j++) m.a(i,j) = i+j/100.0; // Just something easy to recognise |
A simple output method is supplied, it just outputs a row at a time, tab separated to a named file. A filename of "-" means standard output.
cout << "Initial Matrix\n"; m.save("-"); cout << "\n"; |
Resize to 20 rows by 10 columns This fills the new area with def_val, which is 0.0 for floats.
m.resize(20,10); |
Whole rows or columns can be extracted into a buffer, or can be filled with data from a buffer. The buffer must be pre-declared, and it is up to you to ensure it is big enough.
Data can be extracted into a buffer in one operation
float *buf = new float[max(m.num_rows(),m.num_columns())]; m.copy_row(5, buf); |
And data can be inserted in a similar manner.
m.set_column(5,buf); |
A sub-vector or sub-matrix is a window onto a matrix. If you obtain a sub vector representing a row, for instance, you can treat it a normal vector, any changes you make affecting the underlying matrix.
Here is how we can create new variables which refer to the 11th row, 4th column and a 5X3 rectnagle with top left hand corner (8,2). (since the first column or row is numbered 0, the numbers may be one less than you expect).
EST_TVector<float> row; EST_TVector<float> column; EST_TMatrix<float> rectangle; m.row(row, 10); m.column(column, 3); m.sub_matrix(rectangle, 8, 5, 2, 3); |
If we update the sub-vector, the main matrix changes.
// 10th row becomes squares of the index for(int i2=0; i2<row.n(); i2++) row[i2] = i2*i2; // 3rd column becomes cubes of the index for(int i3=0; i3<column.n(); i3++) column[i3] = i3*i3*i3; // Central rectangle filled with -1 for(int i4=0; i4<rectangle.num_rows(); i4++) for(int j4=0; j4<rectangle.num_columns(); j4++) rectangle.a(i4, j4) = -1; |
We can even extract rows and columns from a sub-matrix as follows.
EST_TVector<float> rrow; EST_TVector<float> rcolumn; // 3rd row of sub-matrix, part of 12th row of main matrix rectangle.row(rrow, 2); // 2nd column of sub-matrix, part of 8th column of main matrix rectangle.column(rcolumn, 1); |
Some C++ compilers requre explicit guidance about which types of Matrix will be used. For many common types, including float, this guidance is included in the speech tools libraries. However, if you need to use matrecies of your own types, you will need to include declarations similar to the following.
Declare_TMatrix(MyType) #if defined(INSTANTIATE_TEMPLATES) #include "../base_class/EST_TMatrix.cc" Instantiate_TMatrix(MyType) #endif |
By using this form of declaration, you should ensure that your code will compile anywhere where the speech tools libraries will.