Dear all,
how can i make a program that count the different words in a text(input stop with EOF) and the number of the lines which a word appears?

Recommended Answers

All 4 Replies

#include <stdio.h>
#include <conio.h>
#define IN 1 /* inside a word */
#define OUT 0 /* outside a word */
/* count lines, words, and characters in input */
main()
{
int c, nl, nw, nc, state;
state = OUT;
nl = nw = nc = 0;
while ((c = getchar()) != EOF) {
++nc;
if (c == '\n')
++nl;
if (c == ' ' || c == '\n' || c = '\t')
state = OUT;
else if (state == OUT) {
state = IN;
++nw;
}
printf("%d %d %d\n", nl, nw, nc);
}
getch();
}

maybe this will help you...this will count the new line, new word and no. of characters :)

i try to count the number of different words and put them in an array,but i didn't succeed.any ideas?

#include<stdio.h>
#include<string.h>
main()
{
	int wcount=0,j,counter=1;
	char c,word[300][100];
	c=scanf("%s",word[0]);
	while (c!=EOF)
	{	  
		c=scanf("%s",word[counter]);
		for (j=0;j<counter;j++)
		{
			if (strcmp(word[j],word[counter])==0) break;
			else counter++;
		}
		wcount++;
	}
	printf("%d %d\n",wcount,counter);
	for (j=0;j<counter;j++) puts(word[j]);
}

I am unable to understand what you really wanted to know?? Do you want to count the no. of words only??
If so, then you should count on the spaces, tabs, new lines...and increment the counter by 1 when it encounters any of the spaces, tabs or new lines. This will be processed until it reaches EOF.

So... I thought, how would I do this the RIGHT way in C? No STL at all. Hm...
Arrays, well, they're kind of passe'. Linked Lists are the bees knees. Or something. I was thinking about using BSTs, but wasn't sure at what point to implement leveling/balancing. I decided that would be for the next little project.
BTW, if this code is shoddy, I apologize. I wrote it from scratch. I'm still in college, so cut me a little slack.

//============================================================================
// Name        : TextAnalyzer.c
// Author      : Dean M. Sands, III
// Version     : 0.7e (I made that number up.)
// Copyright   : I will set fire to the flamingos, if any, in your front yard.
// Description : Linked List Experiment in C.
//============================================================================

#include <string.h>	//for malloc
#include <ctype.h>	//isalpha
#include <stdio.h>	//File functions
#include <stdlib.h>	//free

/******************************************************************************\
*                           Generic Functions                                  *
\******************************************************************************/
long hashBlock(char *pointer,long length){
	long i;
	long hash=0;
	//Same hash function as Java String
	for(i=0;i<length;i++){
		hash=(hash<<5)-hash;	//Multiply by 31
		hash+=(long)pointer[i];
	}
	return hash;
}

long	getFileSize(FILE *myFile){
	long fileSize;
	fseek (myFile, 0 , SEEK_END);
	fileSize = ftell (myFile);
	rewind (myFile);
	return fileSize;
}

/******************************************************************************\
*                           Buffer  Functions                                  *
\******************************************************************************/
//I'm not even sure why I created this data structure. It seemed like a good idea at the time.
typedef struct {
	char *data;
	unsigned long length;
} buffer;

//Destructor
void destroyBuffer(void *deadBuffer){
	buffer *myBuffer=(buffer*)deadBuffer;	//Why not directly? So I can use in destroyLinkedList.
	//If already freed, return.
	if(myBuffer==NULL)
		return;
	//Is data array still allocated? Free if it is.
	if(myBuffer->data!=NULL){
		free(myBuffer->data);
		myBuffer->data=NULL;
	}
	myBuffer->length=0;
	//Free the data structure.
	free(myBuffer);
	myBuffer=NULL;
}

//Constructor
buffer *allocateBuffer(unsigned long bufferSize){
	//Allocate the data structure itself, but not its data array. Return on error.
	buffer *myBuffer=(buffer*)malloc(sizeof(buffer));
	if(myBuffer==NULL){
		fprintf(stderr,"Failed to pre-allocate buffer.");
		return NULL;
	}
	//Allocate the data array. Return on Error.
	myBuffer->data=(char*)malloc(sizeof(char)*(bufferSize+1)); //+1 for NULL
	if(myBuffer->data==NULL){
		fprintf(stderr,"Failed to allocate buffer data.");
		destroyBuffer(myBuffer);
		return NULL;
	}
	myBuffer->length=bufferSize;
	return myBuffer;
}

buffer *readFileIntoBuffer(char *fileName){
	FILE *fileHandle;
	buffer *myBuffer=NULL;
	long actualLength;
	//Open the file, but return error if it doesn't exist.
	//Open in binary mode instead of text mode.
	//Windows changes the line endings and fread will get a different size than ftell.
	if((fileHandle = fopen ( fileName , "rb" ))==NULL){
		fprintf(stderr,"Failed to open %s.\n", fileName);
		return NULL;
	}
	//How big is the file?
	myBuffer=allocateBuffer(getFileSize(fileHandle));
	//Read the data in, but return error if it's not the right size.
	actualLength=fread(myBuffer->data,1,myBuffer->length,fileHandle);
	if(myBuffer->length!=actualLength){
		fprintf(stderr,"Error reading data %s.\n", fileName);
		fprintf(stderr,"Reported length: %ld.\n", myBuffer->length);
		fprintf(stderr,"Actual length: %ld.\n", actualLength);
		return NULL;
	}
	fclose(fileHandle);
	return myBuffer;
}


/******************************************************************************\
*                        Linked List  Functions                                *
\******************************************************************************/

struct sLinkedList;
typedef struct sLinkedList linkedList;
struct sLinkedList{
	void *data;
	linkedList *next;
};
//Constructor
linkedList *allocateLinkedList(){
    linkedList *temp;
    temp=(linkedList*)malloc(sizeof(linkedList));
    if(temp==NULL){
		fprintf(stderr,"Error allocating Linked List.\n");
		return NULL;
	}
	temp->next=NULL;
    temp->data=NULL;
    return temp;
}

//For Each Element in Linked List. Useful for destructor, etc.
void forEachElementInLinkedList(linkedList *head, void(*function)(void*)){
	linkedList *current;
	linkedList *next;
	if(head==NULL)return;
	current=head->next;
	next=head->next;
	while(current!=NULL){
		next=current->next;	//Save just in case.
		function(current);
		current=next;
	}
}

//For Each Data in Linked List. Useful for various.
void forEachDataInLinkedList(linkedList *head, void(*function)(void*)){
	linkedList *current;
	linkedList *next;
	if(head==NULL){
//	printf("FEDILL:Head is NULL.\n");											//DEBUG
		return;
	};
	current=head->next;
	next=head->next;
	while(current!=NULL){
		next=current->next;	//Save just in case.
		function(current->data);
		current=next;
	}
}

//For Each Data in Linked List with parameter. Useful for LinkedListLength.
void forEachDataInLinkedList2(linkedList *head, void(*function)(void*,void*),void*parameter){
	linkedList *current;
	linkedList *next;
	if(head==NULL)return;
	current=head->next;
	next=head->next;
	while(current!=NULL){
		next=current->next;	//Save just in case.
		function(current->data,parameter);
		current=next;
	}
}

//Helper function to linkedList Length
void linkedListLengthAdd(void *dummy, void *length){
	(*(long*)length)++;
}
//Returns length of linked list
long linkedListLength(linkedList *head){
	long length=0;
	forEachDataInLinkedList2(head, linkedListLengthAdd, (void*)&length);
	return length;
}

//Returns last element in list.
linkedList *findLinkedListTail(linkedList *head){
	linkedList *current=head;
	while(current->next!=NULL){
		current=current->next;
	}
	return current;
}

//Find in Linked List. Would have used forEachDataInLinkedList2, but would have rewrite that one.
linkedList *findInLinkedList(linkedList *head, int(*comparison)(void*,void*),void*parameter){
    	linkedList *current;
	if(head==NULL)return NULL;
	current=head->next;
	while(current!=NULL){
		if(comparison(current->data,parameter)==0){
		    return current;
		}
		current=current->next;
	}
	return NULL;
}

//Destructor: Destroys linked list and data elements inside.
void destroyLinkedList(linkedList *head, void (*destructor)(void*)){
	if(destructor!=NULL){
		forEachDataInLinkedList(head, destructor);
	}else{
		forEachDataInLinkedList(head, free);
	}
	forEachElementInLinkedList(head, free);
}

/******************************************************************************\
*                         Found Word  Functions                                *
\******************************************************************************/

typedef struct {
	char *text;
	long hash;
	linkedList *lineNumbers;
}foundWord;

//Destructor
void destroyFoundWord(void *deadWord){
	foundWord *myWord=(foundWord*)deadWord;	//Why not directly? So I can use in destroyLinkedList.
	//If already freed, return.
	if(myWord==NULL)
		return;
	//Is data array still allocated? Free if it is.
	if(myWord->text!=NULL){
		free(myWord->text);
		myWord->text=NULL;
	}
	myWord->hash=0;
	//Free the Linked list.
	destroyLinkedList(myWord->lineNumbers, free);
	//Free the data structure.
	free(myWord);
	myWord=NULL;
}

foundWord *allocateFoundWord(char *textStart, char *textEnd){
	foundWord *temp;
	long length;
	length=(long)textEnd-(long)textStart;
	//Allocate data structure; return NULL on error
	temp=(foundWord *)malloc(sizeof(foundWord));
	if(temp==NULL){
		fprintf(stderr,"Error allocating foundWord variable.\n");
		return NULL;
	}
	//Allocate text; free data structure and return NULL on error
	temp->text=(char *)malloc((length+1)*sizeof(char)); //Add spot for NULL
	if(temp->text==NULL){
		free(temp);
		fprintf(stderr,"Error allocating text for foundWord variable.\n");
		return NULL;
	}
	strncpy(temp->text, textStart,length);
	temp->text[length]=0;	//Cap with null.
	temp->hash=hashBlock(temp->text,length);
	//Allocate text; free data structure and return NULL on error
	temp->lineNumbers=allocateLinkedList();
	if(temp->lineNumbers==NULL){
		free(temp->text);
		free(temp);
		fprintf(stderr,"Error allocating line number linked list.\n");
		return NULL;
	}
	return temp;
}

void listLineNumber(void *lineNumber){
	if(lineNumber!=NULL)
		printf("%ld ", *(long*)lineNumber);
}

void listLineNumbersForFoundWord(foundWord *myWord){
	forEachDataInLinkedList(myWord->lineNumbers,listLineNumber);
}
void showWordAndLineNumbers(void *myWord){
    printf("%s: ",((foundWord*)myWord)->text);
    listLineNumbersForFoundWord((foundWord*)myWord);
    printf("\n");
}
int compareWordToHash(void *myWord, void *thatHash){
	long comparison=((foundWord*)myWord)->hash-*(long*)thatHash;
	if(comparison>0) return 1;
	if(comparison<0) return -1;
	return 0;
}

linkedList *appendDataToLinkedList(linkedList *head, void *data){
	linkedList *temp=findLinkedListTail(head);
	temp->next=allocateLinkedList();
	if(temp->next==NULL){
		return NULL;
	}
	temp=temp->next;
	temp->data=data;
	return temp;
}
linkedList *joinLinkedLists(linkedList *head, linkedList *tail){
	linkedList *temp=findLinkedListTail(head);
	temp->next=tail;
	temp=temp->next;
	return temp;
}
linkedList *appendLineNumberToFoundWord(foundWord *myWord, long lineNumber){
	long *tempLineNumber=(long*)malloc(sizeof(long));
	if(tempLineNumber==NULL){
		fprintf(stderr,"Error allocating Line Number.\n");
	}
	*(tempLineNumber)=lineNumber;
	return appendDataToLinkedList(myWord->lineNumbers, (void *)tempLineNumber);
}
int compareLongsPointedToByVoids(void *a, void *b){
	long comparison=*(long*)a-*(long*)b;
	if(comparison>0) return 1;
	if(comparison<0) return -1;
	return 0;
}

int main(int argumentCount, char **arguments){
	buffer *textBuffer;
	long lineNumber=1;
	char *itemStart;
	char *itemEnd;
	char *bufferEnd;
	long itemLength=0;
	long itemHash;
	linkedList *tempLL;
	foundWord *tempWord;
	linkedList *dictionary;
	if(argumentCount>2){
		printf("Please specify a file name.\n");
		return -1;
	}
	dictionary=allocateLinkedList();
	if(dictionary==NULL){
	    return -2;
	}
	textBuffer=readFileIntoBuffer(arguments[1]);
	if(textBuffer==NULL){
		return -3;
	}
	//printf("Read file into text buffer.\n");														//DEBUG
	itemStart=textBuffer->data;
	bufferEnd=(char*)((long)textBuffer->data+textBuffer->length);
	while(((*itemStart)!=EOF)&&itemStart<bufferEnd){

		if((*itemStart=='\n')){
			lineNumber++;
			//printf("Line: %ld.\n",lineNumber);													//DEBUG
		}
		if(isspace(*itemStart)||ispunct(*itemStart)){
			itemStart++;
		}
		if(isalnum(*itemStart)){
			itemEnd=itemStart;
			while(isalnum(*itemEnd)){
				if(((*itemEnd)&0x60)==0x60)	{(*itemEnd)&=0x5f;}	//Convert to lower case so that "The" is the same as "the".
				itemEnd++;
			}
			itemLength=(long)itemEnd-(long)itemStart;
			itemHash=hashBlock(itemStart,itemLength);
			tempLL=findInLinkedList(dictionary,compareWordToHash,(void*)&itemHash);
			if(tempLL==NULL){
			    tempWord=allocateFoundWord(itemStart,itemEnd);
			    tempLL=allocateLinkedList();
			    tempLL->data=tempWord;
				joinLinkedLists(dictionary, tempLL);
				//printf("New word added: %s\n",tempWord->text);									//DEBUG
			}else{
				tempWord=(foundWord*)tempLL->data;
			}
			if(findInLinkedList(tempWord->lineNumbers, compareLongsPointedToByVoids, (void*)&lineNumber)==NULL){
				appendLineNumberToFoundWord(tempWord,lineNumber);
				//printf("New Line number added!\n");												//DEBUG
			}
			itemStart=itemEnd;
		}

	}
	forEachDataInLinkedList(dictionary, showWordAndLineNumbers);
	destroyLinkedList(dictionary,destroyFoundWord);
	destroyBuffer(textBuffer);
	return 0;
}
/* Before you use my code, please, think of the flamingos. */
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.