我正在使用我的C ++类中的自动摘要系统,并且对我正在进行的ASCII比较之一有疑问。这是代码:
char ch;
string sentence;
pair<char, char> sentenceCheck;
int counter = 0;
while (!ifs2.eof())
{
ch = ifs2.get();
ch = tolower(ch);
if (ch == 13)
ch = ifs2.get();
if (ch != 10 && ch != '?' && ch != '!' && ch != '.')
sentence += ch;
sentenceCheck.first = sentenceCheck.second;
sentenceCheck.second = ch;
cout << sentenceCheck.first << "-" << (int)sentenceCheck.first << " ---- " << sentenceCheck.second << "-" << (int)sentenceCheck.second << endl;
if(sentenceCheck.second == ' ' || sentenceCheck.second == 10 || sentenceCheck.second == -1)
{
if(sentenceCheck.first == '?' || sentenceCheck.first == '!' || sentenceCheck.first == '.')
{
istringstream s(sentence);
while(s >> wordInSentence)
{
sentenceWordMap.insert(pair<string, int>(wordInSentence, 0));
}
//sentenceList.push_back(pair<string, int>(sentence, 0));
sentence.clear();
}
}
}
这里所做的(使用两个if语句)正在检查是否已在稍后要分析和处理的文本中开始新句子。条件工作,但只是因为我们发现我们必须检查-1。任何想法代表什么?
答案 0 :(得分:6)
-1不表示ASCII中的任何内容。所有ASCII码都在[0,127]范围内。 C ++甚至不保证-1
是char
的有效值。
问题是您没有检查ifs2.get()
的返回值,该值返回int
(不是char
!),结尾可能是-1
的文件。检查这个的正确方法是
int ch = ifs2.get();
if (!ifs2)
// break the loop
因为EOF值不能保证为-1
(实际上是std::char_traits<char>::eof()
)。
(顺便说一句,你不应该把ASCII代码写成幻数;使用\n
代替换行,\r
代表回车。)
答案 1 :(得分:2)
while
结构不正确:您需要在eof()
之后立即检查get()
:
for (;;)
{
ch = ifs2.get();
if (ifs2.eof()) break;
ch = tolower(ch);
if (ch == 13)
{
ch = ifs2.get();
if (ifs2.eof()) break;
}
...
}
-1
可能是EOF指标。
注意(正如已经说明的那样)get()
会返回int
,而不是char
。
答案 2 :(得分:1)
答案 3 :(得分:1)
作为ASCII字符-1不代表任何东西(也就是说-1不是有效的ASCII值)。作为get()的返回值,这意味着读取操作失败 - 很可能是由于文件结束了。
请注意,如果下一次调用get将因为文件结束而失败,则eof()函数不会返回true - 如果上一次调用失败,则返回true到达文件的结尾。
答案 4 :(得分:0)
检查-1工作的事实是一个意外,并没有任何结果
使用ASCII值(仅使用0
到127
)。您的代码将失败
如果普通字符是无符号的(使用VC ++编译/J
,我认为),
或者EOF
不是-1(很少见,但所有保证的都是它
负)。如果输入正好,您的代码也将失败
Latin-1,它包含'ÿ'
。
您的代码中的基本问题是您没有检查结束
文件正确。将测试置于循环顶部不起作用;
在使用之前,您需要在输入之后测试失败(不是eof()
)
读取的值。有几种方法可以做到这一点;在你的情况下,
最简单的可能是使用:
if ( !ifs2.get(ch) ) {
// Input failed...
}
或者,您可以将ch
设为int
,然后执行:
ch = ifs2.get();
if ( ch == EOF ) {
// Input failed...
}
这样做的好处是不再需要对tolower
进行以下调用
未定义的行为(tolower
接受一个int,它必须在范围内
[0...UCHAR_MAX]
或EOF
- 如果简单char
已签署,则不是
保证这一点)。另一方面,它不允许链接,即
你不能写相当于:
while ( ifs2.get( sentenceCheck.first )
&& ifs2.get( sentenceCheck.second ) ) {
// ...
}
(在某些情况下可能有用)。
FWIW:您正在使用的技术称为滑动窗口 流入一个流,值得把它推到一个单独的类中 处理保持窗口填充和更新的逻辑。 或者,可以使用简单的状态机来解决您的问题。
我肯定会避免使用魔术常数:如果你想检查
回车,与'\r'
比较。同样,换行符为'\n'
,
在外if
,看起来你想要检查空格
(isspace( static_cast<unsigned char>( sentenceCheck.second ) )
),
而不是比较价值。
我可能还会补充一点,你的代码无法正确处理那些句子
以引用结束,如This is the "text in your input."
;它也是
没有像Mr. Jones is here.
这样的缩写。但那些问题
可能超出了您的任务范围。 (缩写一个是
可能无法完全解决:有时"etc."
是一个结束
句子,有时它不是。)