Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
C++ Timesaving Techniques (2005) [eng].pdf
Скачиваний:
65
Добавлен:
16.08.2013
Размер:
8.35 Mб
Скачать

 

 

Testing the String Reader

277

{

 

 

 

// First, see if we have this id.

 

 

 

vector< StringIndex >::const_iterator iter;

 

 

for (iter = _indices.begin(); iter != _indices.end(); ++iter )

 

if ( (*iter).getID() == id )

 

 

 

return _loadString( (*iter) );

 

 

 

return string(“”);

 

 

 

}

 

 

 

};

 

 

 

 

 

 

3. Save the source code as a file in your editor

1.

In the code editor of your choice, reopen

and close the editor application.

 

the source file to hold the code for your test

program.

Testing the String Reader

After you create a class, you should create a test driver that not only ensures that your code is correct, but also shows people how to use your code.

The following steps show you how to create a test driver that illustrates how to read a language file, and shows how the class is intended to be used:

In this example, I named the test program ch46a.cpp.

2. Type the code from Listing 46-3 into your file.

Better yet, copy the code from the source file on this book’s companion Web site.

LISTING 46-3: THE STRINGREADER TEST DRIVER

int main(int argc, char **argv)

{

if ( argc < 3 )

{

printf(“Usage:

ch6_1 string-file-name id1 [id2, ..]\n”);

printf(“Where:

string-file-name

is the name of the compressed string file to use\n”);

printf(“

id1..etc are the

ids to display\n”);

return -1;

 

 

}

StringReader sReader(argv[1]);

for ( int i=2; i<argc; ++i )

{

int id = atoi(argv[i]);

string s = sReader.getString( id ); printf(“String %d: [%s]\n”, id, s.c_str() );

}

return 0;

}

278 Technique 46: Creating an Internationalization Class

3. Save the source-code file in the code editor.

4. Compile and run the source file with your favorite compiler on your favorite operating system.

If you have done everything right, running the application with the arguments shown should produce the following result on your console window:

$ ./a.exe my.eng 2 3 5 9 String 2: [Goodbye] String 3: [Why me?] String 5: [French] String 9: []

You will also see the diagnostics, which are not shown, for the application. If you do not wish to

view the diagnostics, comment out the dump method call shown at line 6 in Listing 46-2.

By looking at the output above, we can see that when we read data back in from the language file, using the indices we have defined in the program, we get back the same strings that we put there in the original language text file. This shows that the program is working properly and that we are getting the language data directly from the file — not from strings embedded in the application.

47 Hashing Out

Translations

Technique

Save Time By

Understanding hash tables

Creating a translation application with hash tables

Creating a translationtext file

Testing your application

The hash table is one of the most valuable constructs in the Standard Template Library. Hash tables are data structures that contain two types of values, usually key-value pairs. A hash table is

used anytime you want to either replace one value with another, or map a given key to a given value. (As you may imagine, it’s a commonly used encryption tool.)

One of the most useful things that you can do with a hash table is to store and look up existing values and replace them with new ones. For example, in a translation application, it would be nice to be able to build a dictionary of words and their resulting translations. The ability to retrieve information based on a key-value pair can save a lot of time in an application. For example, a search and replace feature could use this functionality. Alternatively, you could use this functionality to implement a command parser, with a mapping of strings to integer values. Using hash tables can save you a lot of time in translating one type of input to another in your applications. In this technique, we will look at that exact problem and how to solve it in your application code.

Creating a Translator Class

We will use the hash table function to create a class that “translates” text by replacing certain keywords in the text with other words. Imagine that we want to replace all occurrences of the word computer with the word pc, for example. This type of conversion is commonly referred to as a filter, because it takes input and filters it to a new output format. In this section we will create the Translator class, which will store the text we wish to replace, along with the text we wish to insert in the place of the original.

280 Technique 47: Hashing Out Translations

1. In the code editor of your choice, create a new file to hold the code for the source file of the technique.

In this example, the file is named ch47, although you can use whatever you choose.

2. Type the following code from Listing 47-1 into your file.

Better yet, copy the code from the source file on this book’s companion Web site.

LISTING 47-1: THE TRANSLATOR CLASS

#include <stdio.h> #include <string> #include <map> #include <fstream> #include <iostream>

using namespace std;

class Translator

 

 

 

{

 

 

 

 

private:

 

 

 

 

string

_fileName;

 

 

2

map<string,string>

_dictionary;

 

protected:

 

 

 

void Clear()

 

 

 

{

 

 

 

 

_dictionary.erase(

 

 

 

_dictionary.begin(), _dictionary.end() );

}

 

 

 

1

bool Load( const char *fileName )

 

{

 

 

 

ifstream in(fileName); if ( in.fail() )

return false;

// Just read in pairs of values.

while ( !in.eof() )

{

string word;

string replacement; in >> word;

if ( word.length() )

{

in >> replacement; _dictionary[word] = replace-

ment;

}

}

return true;

}

public:

Translator( void )

{

}

Translator( const char *fileName )

{

Clear();

setFileName( fileName );

}

Translator( const Translator& aCopy )

{

Clear();

setFileName( aCopy.getFileName() );

}

Translator operator=( const Translator& aCopy )

{

Clear();

setFileName( aCopy.getFileName() );

}

 

 

void setFileName( const string&

 

 

sFileName )

 

 

{

 

 

_fileName = sFileName;

 

 

Load(_fileName.c_str());

 

 

}

 

 

string getFileName( void ) const

 

 

{

 

 

return _fileName;

 

 

}

 

3

string replace( string in )

 

{

 

map<string,string>::iterator iter;

iter = _dictionary.find( in );

if ( iter != _dictionary.end() )

{

return iter->second;

}

return in;

}

};