Hello, I'm still a C beginner. I am trying to make a simple code for searching a string in a doc file.

I want to search for a name in the "Employee Database", and display the employee data no,name,desgnation,reg no.,Projects worked.

The template in the file is as follows:

Employee xx
  Name : SOME_NAME
  Designation : SOME_DES
  Employee no. : xx
  No. of projects worked : xx

where x is integers.

I have a problem fetching things from the buffer array. I get some long output of this form : ||[[-]||| ....etc.,

Here is my code:

void searchf()
{
	char S[500],I[500],B[500][50],T[500],K[500][5];
	int e=0,flag=0,i,l,v=0;
	FILE *j;
	printf("\n\nIn which file do you want a name to be searched?\nEnter the complete address below\n\n");
		scanf("%s",I);
		j=fopen(I,"r");

		if(j == NULL)
		{
			printf("ERROR : File not found. Try again later\n");
			getch();
			exit(1);
		}
	printf("Input name of employee to be found\n");
	scanf("%s",S);
	strcpy(T,"  Name : ");
	strcat(T,S);
	strcat(T,"\n");
	
		while(fgets(B[e],100,j)!=NULL)
		{
			if(strcmp(T,B[e])==0)
			{
				strcpy(K[0],B[e-1]);
				strcpy(K[1],B[e]);
				strcpy(K[2],B[e+1]);
				strcpy(K[3],B[e+2]);
				strcpy(K[4],B[e+3]);
				flag=1;
				goto end;
			}
			e++;
		}

fclose(j);

end:
	if(flag==0)
		printf("Employee not found!");
	else
		printf("Employee found in database.\nEmployee details:\n %s%s%s%s%s",K[0],K[1],K[2],K[3],K[4]);
}

Please help me. Thanks in advance!

1. You never compare Name : Rose with fgets'ed line because fgets appends '\n' to a line, so it looks like Name : Rose\n . Solution: use strstr instead strcmp:

if (strstr(T,B[e])) { /* T found */
    ...
} ...

2. You are trying to copy FUTURE lines: you don't get them yet:

strcpy(K[0],B[e-1]);
strcpy(K[1],B[e]); /* current line*/
strcpy(K[2],B[e+1]); /* you will get it on the next loop! */
strcpy(K[3],B[e+2]); /* no such line here and now */
strcpy(K[4],B[e+3]); /* - * - * - * - */

Solution: there are lots of possible and obvious variants...
3. What happens if the file contains more than 50 lines?
Solution: obvious, for example:

for (e = 0; e < 50 && fgets(...); ++e) [ /* why e ??? */

4. scanf("%s"...) gets one word only. You can't get names like "Mary Ann" - why? Solution: use fgets(T,...,stdin) to get the name to be searched.

Thanks for the fast reply... I really appreciate it.

But, I quite don't get what the following thing means?

3. What happens if the file contains more than 50 lines?
Solution: obvious, for example:....

Is my code stopping at 50 lines?

Please clarify it.

And thanks again.!!!

Ooh! I'm sorry! I got what you said. I have declared B[500][50] , which limits it to 50 lines. Can you please suggest some method by which I can address this is issue?

And also, do you know how to use fgets to retrieve some data from middle of the file.

For ex: Suppose I get some info required while I am searching in the above program, and then, I get some place in array like B[e].
Is there anyway to access the eth line from a text?

Also, I tried to access it after the loop. I printed the data after the while loop. But still I get the same result.
ie., [[-[[ .....

printf("Employee found in database.\nEmployee details:\n %s%s%s%s%s",B[e],B[e+1],B[e+2],B[e+3],B[e+4]);[code]

I did the above things prior to this question.

Thanks again ArkM

Latest update:

In the above program itself, the following modified code is yielding surprising values for pos. ie. In the document, if there are 2 employees arranged as given in the question, with a blank line between the two, the program should return a value 6 for pos, but the pos is having value 23. ie the 23rd word i'm searching for.

Here is the code:

while(fgets(B[e],100,j)!=NULL)
		{
			if(strstr(T,B[e]))
			{
				flag=1;
				pos=e;
			}
				e++;
		}

I don't know why this is not counting lines and is counting words.

Please look at it. Thanks in advance.

Let's start from the beginning. Probably the best way to go is to define ReadRecord function. Let it gets the next person record from the file. A new record started from "Employee xx" line then four data lines followed. You know how to detect "Employee" word. Define struct Record, for example:

#define NSZ 50
typedef struct _Record {
    char emp[NSZ];
    char name[NSZ];
    ... /* add other data field */
} Record;

#define LSZ 512
int ReadRecord(Record* prec, FILE* f)
{
    char line[LSZ];
    int done = 0; /* return 0 == read failed or eof */
    if (fgets(line,sizeof line,f) && strstr(line,"Employee") == line) {
        /* read xx from this line then read next 4 lines */
        /* fill structure fields from these lines info */
        done = 1;
    }
    return done;
}

Now search file code looks like:

...
    Record rec;
    char name[NSZ];
    .... /* enter file name, enter name to be searched etc */...
    while (ReadFile(&rec,f)) {
        if (strstr(rec.name,name)) { // found!
            /* print info from rec fields*/
            break;
        }
    }

No matters how many records are in the file now...

I don't know why this is not counting lines and is counting words.

Sorry, I don't understand your question. Counting words? Where are those bad words?..

ArkM what I was trying to tell is that, the name i was searching for was the 23rd word in the file. When I used strstr() , what happened is that the words were counted. I got the value in e as 23 where i should have got 7.

I don't understand this:

Sorry, I don't understand your question. Counting words? Where are those bad words?..

BAD WORDS???

Anyway thanks a lot for the help ArkM. I benefited a lot from you. Thank you very much!!! I love you.

Thank you.
Forgive "bad words". It was a joke.
But the variable e counts lines, not words (at least in the original snippet). That's why I don't understand your words about word numbers.
May be better post your current code again...

Sure, I have found a way to execute the it corely with your help.

Though I am stuck with how to append new data into existing employee database, I am really getting towards the end of the program. I will put the program (if its allowed) when its finished.

Thanks.

Appending a new employee to the should be easy. Declare a few "templates"(poor choice of word, perhaps) of string such as:

char empInfoTemp[] = "Employee ";
char nameTemp[]= "  Name : ";
.
.
.

Now prompt the user for employee information and get that using fgets(). Then use fprintf to add new info to the file:

fprintf(filePointer, "%s", empInfoTemp);
fprintf(filePointer, "%d\n", empNo);
fprintf(filePointer, "%s", nameTemp);
fprintf(filePointer, "%s\n", empName);
.
.
.

I'm still an amateur when it comes to handling files, so you might wanna take that with a pinch of salt. Maybe there's a better way to add employee info.

Also when you're declaring variables, give them names which conveys their purpose, like i have. It makes it easier to understand your code, and makes it easier to debug it- especially by others. :P

And did you get your search function to work? How did you solve this problem? -

strcpy(K[0],B[e-1]);
strcpy(K[1],B[e]);
strcpy(K[2],B[e+1]);
strcpy(K[3],B[e+2]);
strcpy(K[4],B[e+3]);

How did you manage to get employee information after finding a match? Am curious to know how you solved it. :)

That was sure direct way. Thanks for attempting to explain me things. But, I did things smoothly...


And did you get your search function to work? How did you solve this problem? -

strcpy(K[0],B[e-1]);
strcpy(K[1],B[e]);
strcpy(K[2],B[e+1]);
strcpy(K[3],B[e+2]);
strcpy(K[4],B[e+3]);

How did you manage to get employee information after finding a match? Am curious to know how you solved it. :)

Here is the part of code. You can understand neatly.

void searchf()
{
	char S[500],I[500],B[500][500],T[500],K[500][5];
	int e=0,flag=0,i;
	FILE *j;
	printf("\n\nIn which file do you want a name to be searched?\nEnter the complete address below\n\n");
		scanf("%s",I);
		j=fopen(I,"r");

		if(j == NULL)
		{
			printf("ERROR : File not found. Try again later\n");
			getch();
			exit(1);
		}
	printf("Input name of employee to be found\n");
	scanf("%s",S);
	strcpy(T,"  Name : ");
	strcat(T,S);
	strcat(T,"\n");
	
		while(fgets(B[e],100,j)!=NULL)
		{
			if(strcmp(T,B[e])==0)
			{
				flag=1;
				pos=e;
			}
				e++;
		}


	if(flag==0)
		printf("Employee not found!");
	else
	{
		printf("Employee found in database.\n\nEmployee details:\n");
		for(i=(pos-1);i<(pos+4);i++)
        {
	       puts(B[i]);
        }
	}

	fclose(j);

}

It works smoothly now.

And hey, I am gonna attach the file I did in the last post. Thanks

Though I am stuck with how to append new data into existing employee database, I am really getting towards the end of the program. I will put the program (if its allowed) when its finished.

Never pack all the program functionality in the single monoblock main function. Remember "divide and power" principle. Functional decomposition is one of the most valued concepts especially in C programming.
Make int WriteRecord(const Record* prec, FILE* f) function. Let it writes five lines (from Employee to No. of projects worked) from Record data fields (and, for example, returns 0 on success and != 0 on failure or vice versa).
Make int NewRecord(Record* prec) function. Let it gets data fields from cosole (with prompting and data checks) and returns proper values on success or cancel.
Now you can write simple and clear code with these function calls. Don't forget that you must open file in append mode. Also you can't delete or update records in place (they have varying lengths), you need to write all records in the new (temporary) file - move old records, skip deleted records, append new records - then delete old file and rename the new one.

Never pack all the program functionality in the single monoblock main function. Remember "divide and power" principle. Functional decomposition is one of the most valued concepts especially in C programming.
Make int WriteRecord(const Record* prec, FILE* f) function. Let it writes five lines (from Employee to No. of projects worked) from Record data fields (and, for example, returns 0 on success and != 0 on failure or vice versa).
Make int NewRecord(Record* prec) function. Let it gets data fields from cosole (with prompting and data checks) and returns proper values on success or cancel.
Now you can write simple and clear code with these function calls. Don't forget that you must open file in append mode. Also you can't delete or update records in place (they have varying lengths), you need to write all records in the new (temporary) file - move old records, skip deleted records, append new records - then delete old file and rename the new one.

Its really really true ArkM. I faced problem like that while I was starting. Anyway I divided the things into 3 major functions.


I created a program which makes an employee database in the form I told before, it can search for some employee in a given database of such nature(I slightly deviated from ArkM's last suggestions. Sorry!), put new employee, details into an existing database. Though this is a very very simple program, it has given me great opportunity to meet good people like ArkM.

This project has bugs like Can't intake names with spaces, mismatch causes it to store 0 values. But, I don't care...


I have attached the end - product along. Please enjoy!

This is solved!!!

You're still using scanf("%s",S); . Use fgets() (as previously mentioned by ArkM) or you won't be able to read a name with a space. Ex: Jack Ripper. scanf will only read Jack and ignore Ripper. That said your new function is a lot better. You even got rid of goto which, as legend goes, spawns a devil's minion under your bed.

EDIT: So you know about the name with spaces thing. That's an easy bug to fix. just replace scanf("%s",S); with fgets(S,50,stdin);

You're still using scanf("%s",S); . Use fgets() (as previously mentioned by ArkM) or you won't be able to read a name with a space. Ex: Jack Ripper. scanf will only read Jack and ignore Ripper. That said your new function is a lot better. You even got rid of goto which, as legend goes, spawns a devil's minion under your bed.

EDIT: So you know about the name with spaces thing. That's an easy bug to fix. just replace scanf("%s",S); with fgets(S,50,stdin);

Surely devnar. I knew it.

I just did it to simplify the program. However, please try the program that I have attached.

I did this because somebody told me create so as a challenge and he mentioned it to have Employee name(First name).

Thanks again!

Couldn't run your program. It said "Application failed to start because blah blah blah. Reinstalling the application may fix this problem." Anyway i believe you when you say your program works. :P

Couldn't run your program. It said "Application failed to start because blah blah blah. Reinstalling the application may fix this problem." Anyway i believe you when you say your program works. :P

But there ain't know installing!

Its just a simple program devnar...

Here is a screenshot if you would like...

I know. I just extracted it and ran it. I think you need to attach the text file with employee details. Otherwise where will it read and write from?

I know. I just extracted it and ran it. I think you need to attach the text file with employee details. Otherwise where will it read and write from?

Sorry! you have got me wrong... The prog will create a employee DB in a location you specify. It'll create a doc file... That's it. If you want to search, then create one and search in this case:D Sorry about that!

Well, then I wonder why it isn't running then. Anyway, it's alright, as long as you completed your challenge. :P