文章作者:sudami
信息来源:邪恶八进制信息安全团队(www.eviloctal.com)
刚上经常逛的另一个论坛,收到一个求助者的短信,让我帮他做这个题目:
--------------------------------------------------------------------------------------------------------引用:
动词过去式还原程序:
1.内容
设计程序, 输入一组过去式程序,输出相应的动词原型
2. 要求
程序具有不规则动词表输入功能.
不规则动词以文件形式存储,可以从文件读入 存入安字母排序的结构体数组
对于不是动词过去式的输入应给予提示!
大致做了,实现了以下功能:
1.过滤不是字母的字符. 比如输入:2%read#ed,会得到:read
2.具有添加不规则动词的功能,但我发现一个bug:
我用CFile::modeCreate | CFile::modeNoTruncate来保证打开存在的文件时仅仅是打开而不是截去,但运行时总是把文件截断为0,很是不解.
----------------------------(这个问题已经解决,原来问题不是出在这里,是在 wt 这个上)---------------代码:// 打开文件
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 应该改成 at+, 即以读写形式打开文件代码:if ((fp = fopen (szBuffer, "wt")) == NULL)
{
::MessageBox (NULL, "Can not open it!", "sudami", MB_OK);
exit (1);
}
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;
}
有兴趣的大牛能否丢个更简练高效的代码出来小弟借鉴一下啊~