显示具有最小给定元音数量的文件中的单词

时间:2018-07-27 12:12:56

标签: c++ algorithm counting

我正在尝试解决问题,但我不知道如何解决。 问题是,给定一个输入文件,该文件的第一行有一个数字k,第二行有一些单词,K是需要在控制台中打印一个单词的最小元音数量。

Example:
Input: test.in
cars
are...great and awesome

Output:
If k is 2 the result should be:
are
great
awesome
And also it should not take into account spaces or other characters like .,!,? and so on.

我到目前为止所拥有的:

 int main(){

    ifstream fin("dataTest.in");
    char s[250];
    int k;
    fin>>k;
    int nrVowels=0;

    while(fin>>s) {

         int n = strlen(s);

            for(int i=0; i < n; i++)

            {
                    if (s[i] == 'a' ||  s[i] == 'e' ||  s[i] == 'o' ||  s[i] == 'i' || s[i] == 'u'){
                        nrVowels++;
                        if(nrVowels == k){
                            cout<<"Here i guess i should print the word?";
                        }
                    }
            }
    }

}

从代码中可以看到,我的问题是我不确定我应该如何打印单词以及如何知道单词的结尾,因为我不想只打印单词的一部分。 你们对我应该怎么做有任何想法吗?

4 个答案:

答案 0 :(得分:3)

std::ifstream file("Read.txt");
int number;
file>>number;
std::string str; 
auto vowels = [](char c){return c == 'a' ||  c == 'e' ||  c  == 'o' ||  c  == 'i' || c  == 'u';};
while (std::getline(file, str))
{
    if(std::count_if(str.cbegin(), str.cend(), vowels) >= number){
        std::cout<<str<<'\n';
    }
}

答案 1 :(得分:1)

您的要求声明“ K是必须在控制台中打印一个单词的最小元音数量” ,这将转换为更大或等于条件

if (nrVowels >= k) { /* print word */ }

但是,您的代码会在找到k元音后立即打印单词,因此您可以保持原状。但是一旦达到所需数量,您就应该打破内部循环。

此外,正如已经提到的,您需要为检查的每个单词重置nrVowels计数器。更妙的是:在您的while循环体内将nrVowels设为局部作用域变量。

关于您的代码的一些提示对于解决该问题并非严格必要:

  • 使用std::string代替char数组。
  • 使用包含所有元音的单个变量
  • 不算元音,只需确保单词中至少有两个

代码:

ifstream fin("dataTest.in");
std::string s;
const char* vowels = "aeiou";
int k;
fin>>k;

while(fin>>s)
{
    // If the string contains at least two vowels, the find results will differ
    if (s.find_first_of(vowels) != s.find_last_of(vowels))
    {
        std::cout << s << std::endl;
    }
}

答案 2 :(得分:1)

首先解决明显的问题

 int main(){
   ifstream fin("dataTest.in");
   char s[250];
   int k;
   fin>>k;

  while(fin>>s) {
    int nrVowels=0; // moved
    int n = strlen(s);

    for(int i=0; i < n; i++) {
      if (s[i] == 'a' ||  s[i] == 'e' ||  s[i] == 'o' ||  s[i] == 'i' || s[i] == 'u') {
        nrVowels++;

        if(nrVowels == k) {
          cout<< s;;
          break; // inner for
        }
      }
    }
  }    
}

你有

char s[250];

结合

fin>>s

是潜在的缓冲区溢出。将s更改为

std::string s;

现在你知道了

    int n = strlen(s);

免费。

if (s[i] == 'a' ||  s[i] == 'e' ||  s[i] == 'o' ||  s[i] == 'i' || s[i] == 'u')

相当长,最好说

if (IsVowel(s[i]) {

通过制作(如Kaldrr所建议的那样)

auto IsVowel = [](const char c){return c == 'a' ||  c == 'e' ||  c  == 'o' ||  c  == 'i' || c  == 'u';};

这给

int main(){
  ifstream fin("dataTest.in");
  std::string s;
  int k;
  fin>>k;

  auto IsVowel = [](const char c){return c == 'a' ||  c == 'e' ||  c  == 'o' ||  c  == 'i' || c  == 'u';};

  while(fin>>s) {
    int nrVowels=0; // moved

    for(int i=0; i < n; i++) {
      if (IsVowel(s[i]) {
        nrVowels++;

        if(nrVowels == k) {
          cout<< s;;
          break; // inner for
        }
      }
    }
  }    
}

但是仍然存在测试每个单词而不是每个字符串的问题。

int main(){
  ifstream fin("dataTest.in");
  std::string s;
  int k;
  fin>>k;

  auto IsVowel = [](const char c) { return c == 'a' ||  c == 'e' ||  c  == 'o' ||  c  == 'i' || c  == 'u'; };
  auto IsSplit = [](const char c) { return isspace(s[i]) || ispunct(s[i]); };

  while(fin>>s) {
    int nrVowels=0; // moved

    for(int i=0; i < s.length; i++) {
      if (IsVowel(s[i]) {
        nrVowels++;

        if(nrVowels == k) {
          cout << s; // wrong writes all the string and not the word
          break; // inner for
        }
      } else {
        if (IsSplit(s[i]) {
          nrVowels = 0; // restart at each word.
        }
      }
    }
  }    
}

我们想要的是

while(fin>>s) {
  auto split = Split(s);

  for (const auto& str : split) {
    if (HasEnougVowels(str, k)) {
      cout << s;
    }
  }
}

答案 3 :(得分:1)

感谢您的回答! 我已经根据您的帮助修改了我的代码:

int main(){

    ifstream fin("dateTest.in");
    char s[250];
    int k;
    fin>>k;
    int nrVowels=0;

    while(fin>>s) {

         int n = strlen(s);
            nrVowels=0;
            for(int i=0; i < n; i++)

            {
                    if (s[i] == 'a' ||  s[i] == 'e' ||  s[i] == 'o' ||  s[i] == 'i' || s[i] == 'u'){
                        nrVowels++;

                        if(nrVowels >= k){
                            cout<<s<<" ";
                            break;
                        }

                    }

            }
    }

}

现在这种工作方式可行,但我还需要分开具有。,?的单词。等等。应该怎么做?