Вы находитесь на странице: 1из 19

)

{
FILE * pFile;
int c;
int n = 0;
pFile = fopen ("ArquivoTexto.txt", "r");
if (pFile !=NULL)
{
do { //DO
c = fgetc(pFile);
if (c == '\n') n++;
} //DO
while (c != EOF);
fclose(pFile);
printf("Nmero de linhas = %d.\n", n);
}
return 0;
}
#include <stdio.h>
int main ()
{
FILE * pFile;
int c;
int n = 0;
pFile = fopen ("ArquivoTexto.txt", "r");
if (pFile !=NULL)

{
do { //DO
c = fgetc(pFile);
if (c == '\n') n++;
} //DO
while (c != EOF);
fclose(pFile);
printf("Nmero de linhas = %d.\n", n);
}
return 0;
}
Listagem 1. Exemplo de programa em Linguagem C para contagem de linhas
de um arquivo.
O Desafio
Partido do exemplo anterior de contagem simples de linhas de um arquivo
texto, o desafio desta tarefa tem incio ao se querer determinar o nmero de
linhas do cdigo que so comentrios formatados segundo a sintaxe da
Linguagem C/C++. A sintaxe prev dois tipos de comentrios: linha nica
comeando com os caracteres // (barra, barra); e comentrios multi-linhas
comeando com /* (barra, asterisco) e com trmino determinado por */
(asterisco, barra).
Para uma viso de um problema real, considere o exemplo de cdigo fonte
escrito em C apresentado na Listagem 2. Observe os vrios trechos com
comentrios para ajudar a documentao do cdigo-fonte.
Listagem 2. Exemplo real de cdigo fonte com vrios comentrios.
//---------------------------------------------------------// Exemplo de Cabealho
//
// Neste tipo de comentrio, faz-se uma breve apresentao do contedo do
// mdulo em linguagem C. O cdigo apresentado a seguir um extrato de

// desenvolvimento criado para a disciplina de Classificao e Pesquisa.


// Pede-se ao leitor identificar os tipos de linhas com comentrios, em
// especial a diferenciao de comentrios de uma ou de vrias linhas.
//
// Autor: Marcelo Augusto Cicogna.
// Revises:
// 22/11/2005: Criao do mdulo.
// 01/11/2006: Expanso do mdulo em funo da lista de exerccios.
//---------------------------------------------------------#include "TBinTree.h"
#include <stdio.h>
//---------------------------------------------------------// Funces de manipulao do tipo TBinTree.
//---------------------------------------------------------TBinTree*
binTreeCreate(TData* pData)
/** Funo para criao de uma nova rvore binria. necessrio fornecer um
valor para o primeiro n.
@param pData varivel do tipo TData para compor o n raz (root).
@return ponteiro para uma rvore binria.
@see BinTree.#dataCopy dataCopy()
@version 1.01
@author Marcelo Augusto Cicogna
*/
//---------------------------------------------------------// Exemplo de Cabealho

//
// Neste tipo de comentrio, faz-se uma breve apresentao do contedo do
// mdulo em linguagem C. O cdigo apresentado a seguir um extrato de
// desenvolvimento criado para a disciplina de Classificao e Pesquisa.
// Pede-se ao leitor identificar os tipos de linhas com comentrios, em
// especial a diferenciao de comentrios de uma ou de vrias linhas.
//
// Autor: Marcelo Augusto Cicogna.
// Revises:
// 22/11/2005: Criao do mdulo.
// 01/11/2006: Expanso do mdulo em funo da lista de exerccios.
//---------------------------------------------------------#include "TBinTree.h"
#include <stdio.h>
//---------------------------------------------------------// Funces de manipulao do tipo TBinTree.
//---------------------------------------------------------TBinTree*
binTreeCreate(TData* pData)
/** Funo para criao de uma nova rvore binria. necessrio fornecer um
valor para o primeiro n.
@param pData varivel do tipo TData para compor o n raz (root).
@return ponteiro para uma rvore binria.
@see BinTree.#dataCopy dataCopy()
@version 1.01
@author Marcelo Augusto Cicogna

*/
{
TBinTree* binTree = malloc(sizeof(TBinTree));
if (binTree != NULL)
{ //Alocao do node raz.
TNodeBin* pNode = nodeCreate();
//Copia no novo n o valor data passado como parmetro.
dataCopy(pNode->pData, pData);
//Associa o novo n ao root da rvore binria.
binTree->root = pNode;
}
return (binTree);
}
//----------------------------------------------------------void
binTreeInsertNode(TNodeBin* pNode, TData* pData)
/** Funo para insero de um novo n em uma rvore binria.
Funo recursiva por meio do parmetro pNode.
@param pNode ponteiro para um n da rvore binria.
@param pData ponteiro para uma varivel do tipo TData a ser inserida.
@return No h retorno
@see BinTree.#dataCopy dataCopy()
@version 1.01
@author Marcelo Augusto Cicogna
*/
{

TNodeBin* pNodeAux;
if (pNode != NULL)
{ //Se for para inserir do lado esquerdo.
if ( dataComp(pData, pNode->pData, 0) < 0 )
{ //Inserir se o arco esquerdo for nulo.
if (pNode->esq == NULL)
{
pNodeAux = nodeCreate(); //Este um exemplo de comentrio
dataCopy(pNodeAux->pData, pData); //que ocorre junto com cdigo.
pNode->esq = pNodeAux; //Ser necessrio um tratamento.
}
//Caso contrrio, tentar inserir na sub-rvore a esquerda (recursivo).
else
binTreeInsertNode(pNode->esq, pData);
}
//Se for para inserir do lado direito.
else
{
TBinTree* binTree = malloc(sizeof(TBinTree));
if (binTree != NULL)
{ //Alocao do node raz.
TNodeBin* pNode = nodeCreate();
//Copia no novo n o valor data passado como parmetro.
dataCopy(pNode->pData, pData);
//Associa o novo n ao root da rvore binria.
binTree->root = pNode;

}
return (binTree);
}
//----------------------------------------------------------void
binTreeInsertNode(TNodeBin* pNode, TData* pData)
/** Funo para insero de um novo n em uma rvore binria.
Funo recursiva por meio do parmetro pNode.
@param pNode ponteiro para um n da rvore binria.
@param pData ponteiro para uma varivel do tipo TData a ser inserida.
@return No h retorno
@see BinTree.#dataCopy dataCopy()
@version 1.01
@author Marcelo Augusto Cicogna
*/
{
TNodeBin* pNodeAux;
if (pNode != NULL)
{ //Se for para inserir do lado esquerdo.
if ( dataComp(pData, pNode->pData, 0) < 0 )
{ //Inserir se o arco esquerdo for nulo.
if (pNode->esq == NULL)
{
pNodeAux = nodeCreate(); //Este um exemplo de comentrio
dataCopy(pNodeAux->pData, pData); //que ocorre junto com cdigo.
pNode->esq = pNodeAux; //Ser necessrio um tratamento.

}
//Caso contrrio, tentar inserir na sub-rvore a esquerda (recursivo).
else
binTreeInsertNode(pNode->esq, pData);
}
//Se for para inserir do lado direito.
else
{ //Inserir se o arco direito for nulo.
if (pNode->dir == NULL)
{
pNodeAux = nodeCreate();
dataCopy(pNodeAux->pData, pData);
pNode->dir = pNodeAux;
}
//Caso contrrio, tentar inserir na sub-rvore a direita (recursivo).
else
binTreeInsertNode(pNode->dir, pData);
}
}
}
//----------------------------------------------------------{ //Inserir se o arco direito for nulo.
if (pNode->dir == NULL)
{
pNodeAux = nodeCreate();
dataCopy(pNodeAux->pData, pData);

pNode->dir = pNodeAux;
}
//Caso contrrio, tentar inserir na sub-rvore a direita (recursivo).
else
binTreeInsertNode(pNode->dir, pData);
}
}
}
//----------------------------------------------------------Como resultado a ser conquistado, espera-se poder utilizar um aplicativo
auxiliar para contar as linhas do arquivo Exemplo.c (ou de outro que o
aluno achar conveniente durante a fase de testes). Veja um exemplo do
provvel funcionamento de tal programa.
Figura 1. Exemplo de uso e funcionamento do contador de linhas de cdigo
fonte.
Note-se que o programa CodeCount possui um parmetro c ou comment que permite ao usurio decidir a contagem, ou no, das linhas com
comentrios. Vale lembrar que no arquivo Exemplo.c, existe uma linha vazia
entre os dois #include. Alm disso, as linhas que terminam um comentrio
multi-linhas com */ no so contadas como linhas em branco, mas tambm
no so contadas como linhas de comentrio.
Permite-se aos alunos e professores encontrarem outras regras de contagem.
Esta atividade adotou algumas regras, mas elas no precisam ser as nicas
durante a fase de desenvolvimento.
ETAPA 1
Esta atividade importante para que voc compreenda os requisitos do
problema e determine uma organizao inicial do cdigo fonte que permita o
desenvolvimento de uma soluo.
Para realiz-la importante seguir os passos descritos.
PASSOS
Passo 1

Leia atentamente o desafio e os conceitos de contagem de linhas. Identifique


os dois tipos principais de comentrios possveis em linguagem C: comentrio
de uma linha apenas, que comea com //; e comentrios multi-linhas
determinado por /* e */.
Passo 2
Analise o problema e faa sugestes de como organizar o cdigo em uma
funo principal (main) e uma outra funo que far a contagem das linhas
dado como parmetro o nome do arquivo a ser pesquisado. Pode-se chamar
esta funo de ccRun.
Observao: ao utilizar o prefixo cc (de Code Count), ou qualquer outro que
o aluno achar conveniente, facilita-se a integrao do cdigo desenvolvido
nesta tarefa com outras que o programador venha a achar necessrio no futuro.
Como guia para alunos e professores, os autores deste desafio determinaram
dois mdulos para a soluo do problema.
O mdulo principal foi denominado MainCodeCount e um mdulo auxiliar
com funes de auxlio ao principal chamado LibCodeCount. Ao mesmo
tempo, foram projetadas duas funes, conforme a orientao anterior. Os
cabealhos e os nomes dos arquivos os quais contero o cdigo fonte so
apresentados na Figura 2.
Arquivo MainCodeCount.c
int main(int argc, char *argv[])
{...
}
Arquivo LibCodeCount.h
void ccRun(char* file, int* nLines, int* nLinesComment, int*
nLinesEmpty,int noComment, int silent);
Arquivo LibCodeCount.c
void ccRun(char* file, int* nLines, int* nLinesComment, int* nLinesEmpty,
int noComment, int silent);
{...
}
Arquivo MainCodeCount.c

int main(int argc, char *argv[])


{...
}
Arquivo LibCodeCount.h
void ccRun(char* file, int* nLines, int* nLinesComment, int*
nLinesEmpty,int noComment, int silent);
Arquivo LibCodeCount.c
void ccRun(char* file, int* nLines, int* nLinesComment, int* nLinesEmpty,
int noComment, int silent);
{...
}
Figura 2. Exemplo de uso e funcionamento do contador de linhas de cdigo
fonte.
Estude a modularizao proposta. importante que seu cdigo siga a
organizao sugerida nesta atividade, ou seja, que possua pelo menos dois
mdulos: um principal e outro auxiliar. No ser aceito na avaliao desta
etapa a apresentao de apenas um arquivo de cdigo fonte (arquivo.c).
Passo 3
Entregue o cdigo fonte formado por dois mdulos que contenham a funo
principal e uma funo auxiliar para o clculo do nmero de linhas,
considerando as opes fornecidas nesta etapa.
Arquivo MainCodeCount.cpp
#include <cstdlib>
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <ctype.h>
#include <string.h>

#include "LibCodeCount.h"
using namespace std;
int main(int argc, char *argv[])
{
int numeroLinhas, numeroComentarios, numeroVazias;
double porcentagemComentarios;
numeroLinhas = numeroComentarios = numeroVazias = 0;
if(argc < 2)
{
puts("\nUso correto: >MainCodeCount nomearquivo.ext [-c]");
}
else
{
printf("\n\tCode Count - Programmers Tool");
printf("\n\t Versao 1.0 - 2011");
printf("\n\n\tContagem para: "%s"", argv[1]);
if ((strcmp(argv[2], "-c") == 0) || (strcmp(argv[2], "-comment") == 0))
{
ccRun(argv[1], &numeroLinhas, &numeroComentarios, &numeroVazias, 0,
0);
printf("\n\tNumero de linhas..........: %i", numeroLinhas);
printf("\n\tNumero de linhas vazias...: %i", numeroVazias);
printf("\n\n\n");
}
else
{

ccRun(argv[1], &numeroLinhas, &numeroComentarios, &numeroVazias, 1,


0);
printf("\n\tNumero de linhas...................: %i", numeroLinhas);
printf("\n\tNumero de linhas com comentarios...: %i", numeroComentarios);
porcentagemComentarios = (numeroLinhas * numeroComentarios)/100;
printf("\n\tPorcentagem de comentarios.........: %2.1f%""%",
porcentagemComentarios);
printf("\n\tNumero de linhas vazias............: %i", numeroVazias);
printf("\n\n\n");
}
}
system("PAUSE");
return EXIT_SUCCESS;
}
Arquivo LibCodeCount.h
void ccRun(char* file, int* nLines, int* nLinesComment, int*
nLinesEmpty,int noComment, int silent);
Arquivo LibCodeCount.cpp
#include <stdio.h>
#include <stdlib.h>
#include "LibCodeCount.h"
void ccRun(char* file, int* nLines, int* nLinesComment, int*
nLinesEmpty,int noComment, int silent)
{
FILE * pFile;
int c1, c2;
int nL = 0, nLE = 0, nC = 0;
pFile = fopen (file, "r");

if (pFile !=NULL)
c1 = fgetc(pFile);
while (c1 != EOF)
{
if(c1 == '\n'){ nL++; }
if(c1 == '/')
{
c2 = fgetc(pFile);
if(c2 == '*')
{
do{
do{
c1 = fgetc(pFile);
if(c1 == '\n' && c1 != c2)
{
nC++;
nL++;
}
else if(c1 == '\n' && c2 == '\n'){ nLE++; }
c2 = c1;
}
while(c1 != '*');
c1 = fgetc(pFile);
}
while(c1 != '/');
}

if(c1 == '/' && c2 == '/'){ nC++; }


}
c2 = fgetc(pFile);
if(c2 == '\n' && c1 == '\n')
{
nLE++;
nL++;
}
c1 = c2;
}
fclose(pFile);
*nLines = nL;
*nLinesComment = nC;
*nLinesEmpty = nLE;
}
ArquivoTexto.txt
//-----------------------------------------------------------// Exemplo de Cabealho
//
// Neste tipo de comentrio, faz-se uma breve apresentao do contedo do
// mdulo em linguagem C. O cdigo apresentado a seguir um extrato de
// desenvolvimento criado para a disciplina de Classificao e Pesquisa.
// Pede-se ao leitor identificar os tipos de linhas com comentrios, em
// especial a diferenciao de comentrios de uma ou de vrias linhas.
//
// Autor: Marcelo Augusto Cicogna.

// Revises:
// 22/11/2005: Criao do mdulo.
// 01/11/2006: Expanso do mdulo em funo da lista de exerccios.
//-----------------------------------------------------------#include "TBinTree.h"
#include <stdio.h>
//-----------------------------------------------------------// Funces de manipulao do tipo TBinTree.
//-----------------------------------------------------------TBinTree*
binTreeCreate(TData* pData)
/** Funo para criao de uma nova rvore binria. necessrio fornecer um
valor para o primeiro n.
@param pData varivel do tipo TData para compor o n raz (root).
@return ponteiro para uma rvore binria.
@see BinTree.#dataCopy dataCopy()
@version 1.01
@author Marcelo Augusto Cicogna
*/
{
TBinTree* binTree = malloc(sizeof(TBinTree));
if (binTree != NULL)
{
//Alocao do node raz.
TNodeBin* pNode = nodeCreate();
//Copia no novo n o valor data passado como parmetro.

dataCopy(pNode->pData, pData);
//Associa o novo n ao root da rvore binria.
binTree->root = pNode;
}
return (binTree);
}
//-----------------------------------------------------------void
binTreeInsertNode(TNodeBin* pNode, TData* pData)
/** Funo para insero de um novo n em uma rvore binria.
Funo recursiva por meio do parmetro pNode.
@param pNode ponteiro para um n da rvore binria.
@param pData ponteiro para uma varivel do tipo TData a ser inserida.
@return No h retorno
@see BinTree.#dataCopy dataCopy()
@version 1.01
@author Marcelo Augusto Cicogna
*/
{
TNodeBin* pNodeAux;
if (pNode != NULL)
{
//Se for para inserir do lado esquerdo.
if ( dataComp(pData, pNode->pData, 0) < 0 )
{
//Inserir se o arco esquerdo for nulo.

if (pNode->esq == NULL)
{
pNodeAux = nodeCreate(); //Este um exemplo de comentrio
dataCopy(pNodeAux->pData, pData); //que ocorre junto com cdigo.
pNode->esq = pNodeAux; //Ser necessrio um tratamento.
}
//Caso contrrio, tentar inserir na sub-rvore a esquerda (recursivo).
else
binTreeInsertNode(pNode->esq, pData);
}
//Se for para inserir do lado direito.
else
{
//Inserir se o arco direito for nulo.
if (pNode->dir == NULL)
{
pNodeAux = nodeCreate();
dataCopy(pNodeAux->pData, pData);
pNode->dir = pNodeAux;
}
//Caso contrrio, tentar inserir na sub-rvore a direita (recursivo).
else
binTreeInsertNode(pNode->dir, pData);
}
}
}

//-----------------------------------------------------------Figura 3. Exemplo de uso e funcionamento do contador de linhas de cdigo


fonte.