C ++使用C字符串计算字符,单词,文件中的句子

时间:2014-04-20 15:48:23

标签: c++ c-strings

我将使用" C字符串,而不是C ++字符串对象"每个老师从输入文件中读取一个段落,并计算字符,单词,句子和要成为动词的数量(to,be,am,are,is,was,are)。我当前的程序清除了编译器,但我的字符数和字数都减去了两个。在计算一个句子后,我的句子计数停止了。任何有关我的错误的帮助表示赞赏。仍在努力调试。我的老师基本上告诉全班strtok做了什么,然后字面上告诉我们要从那里弄明白。没有要求你为我做这件事 - 只是提示/提示要回到正确的方向。复活节快乐。

#include <iostream>
#include <cstring>
#include <fstream>
#include <cstdlib>


using namespace std;

const int MAX_FILENAME = 256;
//Longest word length = 15 chars
const int MAX_WORD_CHARS = 16;
//Longest word in paragraph = 200 words
const int WORDS_MAX = 200;
//Max amount of chars in paragraph = 15*200
const int MAX_PARAGRAPH_CHARS = 3000;
//Max chars in a sentence
const int MAX_SENTENCE_CHARS = 200;
const int MAX_SENTENCES = 25;
const int NUM_TO_BE_VERBS = 5;

void readParagraph( ifstream& input, char [] );
int countWords( char [], char tp[][MAX_WORD_CHARS] );
int countSentences( char [] );

int main()
{
   int i;
   int words, sentences, average;
   char filename[MAX_FILENAME];
   ifstream input;
   //Holds paragraph characters 
   char p[MAX_PARAGRAPH_CHARS]; 
   const char TO_BE_VERBS[NUM_TO_BE_VERBS][MAX_WORD_CHARS] = { "am", "are", "is", "was", "were" };
   const char BE[] = "be";
   const char TO[] = "to";
   char tp[WORDS_MAX][MAX_WORD_CHARS];

   //Prompt user input file name
   cout << "Enter input file name: ";
   cin.get( filename, 256 );


   //Open input file
   input.open( filename );
   //Check input file exists
   if ( input.fail() )
   {
      cout << "Input file " << filename << " does not exist." << endl;
      exit(1);
   }

   //Reads paragraph into array  
   readParagraph( input, p );

   countWords( p, tp );


   countSentences( p );

   return(0);
}


void readParagraph( ifstream& input, char p[] )
{
   int count = 0;

   while ( input.get( p[count]) && (count < MAX_PARAGRAPH_CHARS) )
   {
      count++;
   }
   p[count - 1] = '\0';

   cout << "Number of characters: " << count << endl;
}

int countWords( char p[], char tp[][MAX_WORD_CHARS] )
{
   int i = 0;
   char* cPtr;

   cPtr = strtok( p, " " );
   while ( cPtr != NULL )
   {
      strcpy( tp[i], cPtr );
      i++;
      cPtr = strtok( NULL, " " );
   }

   cout << "Number of Words: " << i << endl;   
   return(i);
} 

int countSentences( char p[] )
{ 
   int j = 0;
   char* Ptr;
   char sent[25];

   Ptr = strtok( p, ".!?" );
   while ( Ptr != NULL )
   {
      strcpy( sent, Ptr );
      j++;
      Ptr = strtok( NULL, ".!?" );
   }

   cout << "Number of sentences: " << j << endl;

   return(j);
}      

2 个答案:

答案 0 :(得分:0)

代码存在许多问题,并且分配存在问题。首先,正如已经提到的,这不是专业程序员接近这个任务的方式,因此教师不要教导学生真实地使用C ++,这是非常遗憾的。也就是说,通过这样的任务还有很多东西需要学习。以下是您需要考虑和纠正的一些问题。

未使用的变量

未使用的变量通常是代码质量差的标志。它们使代码混乱,使其难以理解并且不增加任何价值。如果您要求它特别挑剔,您的编译器可以帮助您找到这些类型的问题。我使用g++编译代码并使用以下命令行:

g++ -Wall -Wextra -pedantic --std=c++11 -o stringcount stringcount.cpp

有用地指出iwordssentencesaverageTO_BE_VERBSBETO是未使用。

using namespace std;

using namespace std;合并到您编写的每个程序中都应该避免a bad habit。如果您的导师建议您使用此构造,请注意,如果您决定编写除该类之外的其他代码,您将不得不忘记这种坏习惯。

阅读段落

您的readParagraph例程包含此循环:

while ( input.get( p[count]) && (count < MAX_PARAGRAPH_CHARS) ) 

但请注意,只有当它到达文件末尾或超过MAX_PARAGRAPH_CHARS时才会停止,而readParagraph不是段落的通常定义。相反,您可能希望使用其他一些指示符(例如空行)来表示段落已结束。

从核心逻辑中分离输出

您的许多例程都会打印以及进行某种计算。虽然这是帮助解决非工作代码问题的合理方法,但通常最好将计算(与readParagraph}分开打印。这意味着可能更有意义的是让unsigned返回main,表示段落中的字符数而不打印任何内容。如果需要打印某些内容,请从其他常规或readParagraph打印出来。

错误处理

查看您的void readParagraph( std::ifstream& input, char p[] ) { int count = 0; while ( input.get( p[count]) && (count < MAX_PARAGRAPH_CHARS) ) { count++; } p[count - 1] = '\0'; std::cout << "Number of characters: " << count << std::endl; } 功能:

\0

那个countWords字符真的出现在正确的位置吗?如果没有读过字符,它会写在哪里?

仔细考虑问题

你能算出这句话中的单词吗?我算八。您的程序可能不会,因为您的cPtr = strtok( p, " " ); 函数包含以下行:

strtok

请注意,单词可能以句点或问号结尾,而不一定是空格字符。 countWords函数实际上可以在同一个调用中查找多个delmiters,因此您可能希望调整该调用。

创造额外的工作

tp函数会将每个发现的单词小心地复制到tp数组中,但是sent数组从不使用。如果您不使用它,请不要创建它。它将使您的程序更耐用,更容易排除故障,并且速度稍快。 countSentences函数中神秘的return变量也是如此。

return(j);不是函数

不要写return因为return j;不是函数。相反,只需编写const int,这是更惯用的C和C ++风格。

魔数

你在程序中对常量使用了许多std::cin.get( filename, 256 ); 声明,这是一件好事。但是,程序中仍然存在一些神秘且无法解释的“幻数”,例如此行中的256:

std::

(请注意,我在前面添加了using namespace std;,以显示当您从程序中省略{{1}}时的样子。)

答案 1 :(得分:0)

以下是如何调试这样的代码(这与编写代码的方式有关,但不一样,但首先要避免这种困境)。

第1步:选择观察到的问题并将其锁定。

字符数已关闭。鉴于文本&#34; red apple&#34;,代码报告Number of characters: 10

第2步:找到相关代码并尽可能地将其删除,同时仍然显示行为。

void readParagraph( ifstream& input, char p[] )
{
   int count = 0;

//   while ( input.get( p[count]) && (count < MAX_PARAGRAPH_CHARS) )
   char c;
   while ( input.get(c))
   {
      count++;
   }
//   p[count - 1] = '\0';

   cout << "Number of characters: " << count << endl;
}

步骤3:输入一些诊断输出语句,以便查看正在进行的操作(或者,对于更高级的学生,在调试器中运行整个过程)。

void readParagraph( ifstream& input, char p[] )
{
  int count = 0;

  char c;
  while(input.get(c))
  {
    count++;
    cout << count << ": " << c << endl;
  }

  cout << "Number of characters: " << count << endl;
}

输出结果为:

1: r
2: e
3: d
4:  
5: a
6: p
7: p
8: l
9: e
10: 

代码将空格和回车计算为字符。

第4步:修复它。

你如何处理这个问题取决于你想要它的数量。

返回第1步,重复直至您满意为止。