使用strchr的家庭作业问题给了我意外的输出



我必须编写一个C程序,输出文本的字数,并在下一行输出以元音或辅音开头和结尾的单词。

例如:

input
La bacalaureat la proba de Informatica a fost un subiect cu un sir de caractere
output
15     
bacalaureat Informatica a fost subiect sir

这是我的程序:

#include <iostream>
#include <string.h>
using namespace std;
int main()
{
int c = 0;
char sir[100], copie[100];
cin.get(sir, 100);
strcpy(copie, sir);
char* pch = strtok(sir, " ");
while (pch != NULL)
{
c++;
pch = strtok(NULL, " ");
}
cout << c << endl;
char* pch2 = strtok(copie, " ");
while (pch2 != NULL)
{
if ((strchr("aeiouAEIOU", pch2[0]) && strchr("aeiouAEIOU", pch2[strlen(pch2)-1])) || (strchr("aeiouAEIOU", pch2[0] == NULL) && strchr("aeiouAEIOU", pch2[strlen(pch2)-1] == NULL)))
{
cout << pch2<<" ";
}
pch2 = strtok(NULL, " ");
}
}

但它给了我意想不到的输出。我得到:

15
La bacalaureat la proba de Informatica a fost un subiect cu un sir de caractere

我不明白为什么。这显然是因为如果,但在我看来还可以。

你能帮我修一下程序吗?我不明白发生了什么事。谢谢

if语句中使用的此子表达式

strchr("aeiouAEIOU", pch2[0] == NULL) && strchr("aeiouAEIOU", pch2[strlen(pch2)-1] == NULL)

是错误的。

必须有

strchr("aeiouAEIOU", pch2[0]  ) == NULL && strchr("aeiouAEIOU", pch2[strlen(pch2)-1] ) == NULL

你可以用下面的方式编写更简单的if语句

if ( ( strchr( "aeiouAEIOU", pch2[0] ) == NULL ) == 
( strchr( "aeiouAEIOU", pch2[strlen(pch2)-1] ) == NULL ) )

但在任何情况下,创建源字符串的副本并使用strtok都不是一个好方法。

最好使用标准的C函数strspnstrcspn来提取字符串中的单词而不更改它

可以将满足条件的单词存储在向量中。

这是一个示范节目。

#include <iostream>
#include <utility>
#include <vector>
#include <cstring>
#include <cctype>
int main() 
{
const char *s = "La bacalaureat la proba de Informatica "
"a fost un subiect cu un sir de caractere";
const char *vowels = "aeiou";
const char *delim = " t";
std::vector<std::pair<const char *, const char *>> v;
size_t n = 0;
for ( const char *p = s; *p != ''; )
{
p += std::strspn( p, delim );
const char *q = p;
if ( *q )
{
++n;
p += std::strcspn( p, delim );
char c1 = std::tolower( ( unsigned char )q[0] );
char c2 = std::tolower( ( unsigned char )p[-1] );
if ( ( std::strchr( vowels, c1 ) == nullptr ) == 
( std::strchr( vowels, c2 ) == NULL ) )
v.emplace_back( q, p );              
}
}
std::cout << n << 'n';
for ( const auto &p : v ) std::cout.write( p.first, p.second - p.first ) << ' ';
std::cout << 'n';
return 0;
}

其输出为

15
bacalaureat Informatica a fost subiect sir 

以下是使用strchr但使用std::istringstream分解单词的程序版本:

#include <iostream>
#include <string>
#include <cstring>
#include <sstream>
#include <vector>
bool isvowel(char ch)
{
return strchr("aeiouAEIOU",ch)?true:false;
}
bool isconsonant(char ch)
{
return !isvowel(ch);
}
int main()
{
std::vector<std::string> sVect;
int word_count = 0;
std::string test = "La bacalaureat la proba de Informatica a fost un subiect cu un sir de caractere";
std::istringstream strm(test);
std::string word;
while (strm >> word)
{
++word_count;
if ( (isvowel(word.front()) && isvowel(word.back())) ||
(isconsonant(word.front()) && isconsonant(word.back())))
sVect.push_back(word);     
}
std::cout << word_count << "n";
for (auto& s : sVect)
std::cout << s << " ";
}

输出:

15
bacalaureat Informatica a fost subiect sir 

注意,元音或辅音的测试被放在不同的函数中,这样比较更容易。

还要注意使用std::string类的front()back()可以轻松地获得每个单词的第一个和最后一个字符,而不是在比较中重复调用strlen

最新更新