文章作者:sudami
信息来源:邪恶八进制信息安全团队(www.eviloctal.com

 刚上经常逛的另一个论坛,收到一个求助者的短信,让我帮他做这个题目:

引用:

                       动词过去式还原程序: 
1.内容
设计程序, 输入一组过去式程序,输出相应的动词原型

2. 要求
 程序具有不规则动词表输入功能. 
 不规则动词以文件形式存储,可以从文件读入 存入安字母排序的结构体数组
  对于不是动词过去式的输入应给予提示!

--------------------------------------------------------------------------------------------------------
大致做了,实现了以下功能:

1.过滤不是字母的字符. 比如输入:2%read#ed,会得到:read
2.具有添加不规则动词的功能,但我发现一个bug:
 我用CFile::modeCreate | CFile::modeNoTruncate来保证打开存在的文件时仅仅是打开而不是截去,但运行时总是把文件截断为0,很是不解.
代码:

// 打开文件
        CStdioFile   fText;  
        CFileException FileExc;
        UINT nOpenFlags;
        CString str;
        
        nOpenFlags = CFile::modeReadWrite | CFile::modeCreate | CFile::modeNoTruncate;
        if (!fText.Open(szBuffer, nOpenFlags, &FileExc))
        {
            FileExc.ReportError ();
            return 0;
        }

----------------------------(这个问题已经解决,原来问题不是出在这里,是在 wt 这个上)---------------
代码:

if ((fp = fopen (szBuffer, "wt")) == NULL)
    {
        ::MessageBox (NULL, "Can not open it!", "sudami", MB_OK);
        exit (1);
    }

这里的wt  应该改成 at+, 即以读写形式打开文件


3."对于不是动词过去式的输入应给予提示!"
这个功能我想了半天都不知道如何实现,怎么能判断一个不规则的词是动词过去式还是其他的呢~~

4.
*******代码优化...*******
代码:

          
             if (temp[i-3] == temp[i-4])
            {
                i = i - 3;
                j = i - 1;
                cout << "---->Result:" ;
                while (i--)
                {
                    cout << temp[j-i];
                }
                cout << endl;
                
                cout << "Input:";
                cin.getline (g_buffer, MAX_PATH);
                Convert (g_buffer);    
            } 

            else
            {
                cout << "---->Result:" ;
                i = i - 2;
                j = i - 1;
                while (i--)
                {
                    cout << temp[j-i];
                }
                cout << endl;
                cout << "Input:";
                cin.getline (g_buffer, MAX_PATH);
                Convert (g_buffer);    
            } // if

          
这里if和else里的内容差不多,累赘.,应该改成:

代码:

i=(temp[i-3]==temp[i-4])?(i-3):(i-2);
                j = i - 1;
                cout << "---->Result:" ;
                while (i--)
                {
                    cout << temp[j-i];
                }
                cout << endl;
                
                cout << "Input:";
                cin.getline (g_buffer, MAX_PATH);
                Convert (g_buffer);    

          

********算法问题***********
代码:

          
if (temp[i-1] == 'd')
       {
        if (temp[i-2] == 'e')                //注意:下面没有else与这个if对应
        {
            if (temp[i-3] == temp[i-4])
            {
             .....
            } 

            else
            {
             ....
            }
        } 
    } 
    
    else
    {
    ....//处理倒数第2个字母不是e的情况
    }

        

由于第二个if没有else对应....程序会忽略很多这种最后一个字母是d而倒数第二个字母不是e的不规则动词..
譬如:did,could,should,read....

其实,...这里的算法本身就有问题...没有考虑很多不规则动词的情况...
根据算法...
fled------->fl(应该为fleed)
bled------>bl(应该为bleed)
led-------->l(应该为lead)
added---->ad(应该为add)
loved----->lov(应该为love)
married--->marri(应该为marry)
......
还有很多例子...

由于写这个的时候把这些遗忘了,故补充进来供有兴趣的深入~
  
--------------------------------------------
程序运行截个图:
http://www.qudoo.net/p?id=4028808e13...13afb365fa7e47
http://www.qudoo.net/p?id=4028808e13...003d&qudoo.jpg

-----------------------------------------------------------------------------------------------------------

程序代码如下:
代码:

/******************************************************
* FileName   :   1.cpp
* Author     :   sudami
* FinishTime :   2007/07/10
* Comment    :   converse a verb to
******************************************************/

#include <iostream.h>
#include <string.h>
#include <afx.h>
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
#include <fstream.h>

char g_buffer[MAX_PATH];     // globle array in order to preserve strings
TCHAR szBuffer[MAX_PATH+1];  // current directory
HANDLE hFile;


////////////////////////////////////////////////////////////////////////////

int ShowMessage ();        // 显示提示信息
int Convert (char *str);   // 负责动词的查找、添加和显示
int Dispart (char *s);     // 将数据写入文件

////////////////////////////////////////////////////////////////////////////

int main ()
{
    ShowMessage ();
    Convert (g_buffer);
    
    return 0;
}

/***********************************************************************
*                                                                      *
*           Module: Convert ()                                         *
*           Function : convert some vertb past tense to Prototype      *              
*                                                                      *
************************************************************************/

int Convert (char *s)
{
    int i = 0;
    int j = 0;
    int k = 0;
    char temp[MAX_PATH]; // array intend to preserve letters
    
    // filters the character string,only left with letters 
    do
    {
        while (*s >= 'A' && *s <= 'Z' || *s >= 'a' && *s <= 'z')
        {
            temp[i] = *s;
            ++i;
            ++s;
        }
    }while (*s++);
    
    // check if it iterminates with 'd'(ignore the '\0' character)
    if (temp[i-1] == 'd')
    {
        if (temp[i-2] == 'e')
        {
            if (temp[i-3] == temp[i-4])
            {
                i = i - 3;
                j = i - 1;
                cout << "---->Result:" ;
                while (i--)
                {
                    cout << temp[j-i];
                }
                cout << endl;
                
                cout << "Input:";
                cin.getline (g_buffer, MAX_PATH);
                Convert (g_buffer);    
            } 

            else
            {
                cout << "---->Result:" ;
                i = i - 2;
                j = i - 1;
                while (i--)
                {
                    cout << temp[j-i];
                }
                cout << endl;
                cout << "Input:";
                cin.getline (g_buffer, MAX_PATH);
                Convert (g_buffer);    
            } // if
        } 
    } 

    /*********************************************************************
    **** 下面的else是判断的重点,如果是不规则动词就按照下面的方式处理 ****
    *********************************************************************/
    
    else
    {
        cout << "this is not a regular verb,if it is not find int test.txt,you could build it." << endl;
        
        // 取得当前目录
        ::GetCurrentDirectory (MAX_PATH + 1, szBuffer);
        if (szBuffer[lstrlen(szBuffer) - 1] != '\\')
            lstrcat (szBuffer, TEXT("\\"));
        
        lstrcat (szBuffer, "text.txt");
        
        // 打开文件
        CStdioFile   fText;  
        CFileException FileExc;
        UINT nOpenFlags;
        CString str;
        
        nOpenFlags = CFile::modeReadWrite | CFile::modeCreate | CFile::modeNoTruncate;
        if (!fText.Open(szBuffer, nOpenFlags, &FileExc))
        {
            FileExc.ReportError ();
            return 0;
        }
        DWORD dwBytes = fText.GetLength ();
        fText.Close ();  
        
        // 判断文件是否为空
        if (dwBytes == 0)  // 是空文件
        {
            char choice;
            cout << "There are no characters macth the current string,do you want to create it? y/n" <<endl;
            choice = getchar ();
            if (choice == 'y')
            {
                char szBuild[1024];
                cout << "\t* [+] Usage: intput 'broke@break' *\n"
                     << "\t* [-] Example:  broke@break *\n"
                     << "\t* [-] Result: Your input is now preserved in test.txt *\n"
                     << endl;
                cout << "Build:";
                cin.getline (szBuild, 1024);
            
                // 写到文件中
                Dispart (szBuild);
                cout << "Your input is now preserved in " << szBuffer <<endl;
                
                cout << "Input:";
                cin.getline (g_buffer, MAX_PATH);
                Convert (g_buffer);
            }

            else
            {
                cout << "Input:";
                cin.getline (g_buffer, MAX_PATH);
                Convert (g_buffer);
            } // if
        }
        
        else  // 非空文件
        {
            // 打开文件
            CStdioFile   Text;  
            CFileException FileExc;
            UINT nOpenFlags;
            CString str;
            
            nOpenFlags = CFile::modeReadWrite | CFile::modeCreate | CFile::modeNoTruncate;
            
            if (!Text.Open(szBuffer, nOpenFlags, &FileExc))
            {
                MessageBox(NULL, "不能打开非空文件", "sudami", MB_OK);//显示出来
                FileExc.ReportError ();
                return 0;
            }
            
            BOOL bCheck = FALSE;
            CString szstr;
            
            // 一行一行的读取文件中的内容
            while (Text.ReadString (szstr))
            { 
                //  MessageBox(NULL, szstr, "sudami", MB_OK);//显示出来
                UINT t = szstr.Find("@");
                UINT n = szstr.GetLength ();
                int l = n - t - 1;
                CString szLeft = szstr.Left (t);
                
                
                // 如果此行中@前面的值与用户输入的匹配,则输出@后面的值
                if (strcmp (g_buffer, szLeft) == 0)
                {
                    bCheck = TRUE;
                    CString szRight = szstr.Right (l);
                    cout << "---->Result:" << szRight <<endl;
                //    cout << "Input:";
                //    cin.getline (g_buffer, MAX_PATH);
                //    Convert (g_buffer);
                //    break;
                }    
            }
            Text.Close ();

            if (!bCheck) // 在文件中没有找到可以匹配的, 新建
            {
                cout << "There are no characters macth the current string,do you want to create it? y/n" <<endl;
            
                char szBuild[1024];
                cout << "\t* [+] Usage: intput 'broke@break' *\n"
                    << "\t* [-] Example:  broke@break *\n"
                    << "\t* [-] Result: Your input is now preserved in test.txt *\n"
                    << endl;
                cout << "Build:";
                cin.getline (szBuild, 1024);
                
                // 写入文件
                Dispart (szBuild);
                cout << "Your input is now preserved in " << szBuffer <<endl;
                
                cout << "Input:";
                cin.getline (g_buffer, MAX_PATH);
                Convert (g_buffer);
            }
            
        } // if
        
    } // if
    
    return 0;
}

/***********************************************************************
*                                                                      *
*        Module: Dispart ()                                            *
*        Function: Read data from test.txt,dispart into two characters *              
*                                                                      *
************************************************************************/

int Dispart (char *s)
{
    int i = 0;
    int j = 0;
    int k = 0;
    int r = 0;
    char szBuildBuffer1[20];
    char szBuildBuffer2[20];
    
    /************************************************************
    * 获取用户输入的对应字符串,将其分开分别保存在2个数组中
    * eg:用户输入---> broke@break,则szBuildBuffer1[1024]保存broke
    * szBuildBuffer2[1024]保存break 
    ************************************************************/
    do
    {
        if (*s == '@')
        {
            char szBuild[1024];
            cout << "Error,please input again!\n";
            cout << "Build:";
            cin.getline (szBuild, 1024);
            Dispart (szBuild);
        }
        
        while (*s >= '@' && *s <= 'Z' || *s >= 'a' && *s <= 'z')
        {
            if (*s == '@')
            {
                s++;
                do
                {
                    
                    while (*s >= 'A' && *s <= 'Z' || *s >= 'a' && *s <= 'z')
                    {
                        szBuildBuffer2[j] = *s; 
                        j++;
                        s++;
                    }
                }while (*s++);
            }
            
            else
            {
                if (*s == '\0')
                    break;
                
                szBuildBuffer1[i] = *s;
                i++;
                s++;
            }
        }
    }while (*s++);
    
    /*******************************************************************
    * 将所得到的2个数组内容写入到test.txt文件中
    * 用到fstream库中的函数 fputc
    *******************************************************************/
    
    char a = '@';
    char b = '\n';
    FILE *fp;
    if ((fp = fopen (szBuffer, "at+")) == NULL)
    {
        ::MessageBox (NULL, "Can not open it!", "sudami", MB_OK);
        exit (1);
    }
    
    k = i - 1;
    while (--i)
    {
        fputc (szBuildBuffer1[k - i], fp);
    }
    
    fputc (a,fp);
    r = j - 1;
    while (j--)
    {
        fputc (szBuildBuffer2[r - j], fp);
    }
    fputc (b,fp);
    fclose (fp);
    return 0;
}

/***********************************************************************
*                                                                      *
*           Module: ShowMessage ()                                     *
*           Function : Display some Information to the user            *              
*                                                                      *
************************************************************************/

int ShowMessage ()
{
    system ("color F");
    system ("title sudami");
    cout << "--- a little subject made by sudami ---\n"
        << "--- You may contact with me through the mail: <xiao_rui_119@163.com> ---\n\n"
        << "\t* Please input some verb past tense here... *\n"
        << "\t* [+] Usage: intput '1r+%e3a@4d5e6d',return 'read' *\n"
        << "\t* [-] Example:  1r+%e3a@4d5e6d *\n"
        << "\t* [-] ---->Result: read *\n"
        << endl;
    cout << "Input:";
    cin.getline (g_buffer, MAX_PATH);
    
    return 0;
}

代码写的很垃圾, 请批评指正,
有兴趣的大牛能否丢个更简练高效的代码出来小弟借鉴一下啊~