Saturday, January 23, 2010

Reading multiple words from text file

scanf allows us to read a single word but not multiple words.
gets allows us to read multiple words but only one string
In Let Us C chap 9 page 334, there is a solution to readng multiple words and strings using : scanf("%[^\n]s",word);
However when we want to read from a text file we cannot use
fscanf(file,"%[^\n]s",word); to read a multiple word string as it is logically not possible to do so.
fscanf only allows us to read one word at a time. This is due to the fact that the format of how the text are arranged in the text file are arranged and defined by the user.
For example, lets say we have a text file having an address and the number of houses in that location.

If we have an address like "Green Park 22" and the number of houses here in the location is 50, the format of the text file would be something like this:

"Green Park 22 50"

If you give this information to a stranger, he/she wouldn't know what the data is about. It might be that "Green Park" is the address, "22" is the number of houses and
"50" is the number of inhabitants or that "Green" is a country, "Park" is a district and "22 50" is the house number.

Therefore to read the text file in a proper manner, it has to be done by the user.

In the example below, the program stores students names and the scores they have.
In this program,unlike all the other solutions previously, the students' names can have multiple words(Up to 3 though it can be edited to accomodate more words) e.g "Mr Multiple". For this program you have to

1)Create a folder name "ctxt" in C: Drive
2)Create a new text file named "11TEST".
3)Then you would have the directory C:\\ctxt\\11TEST.txt as required by the program.

The format of the data in the text file is:

Name Marks

The method used is to detect the spacing between the name of the student and his/her marks. To do this, i have applied a double spacing between the name and marks so when the program detects this double spacing, it knows the next data it reads is marks.

Below is the solution:

#include "stdio.h"
struct data
{
char name[30];
int numb;
};
void main()
{
FILE *fs;
struct data d;
int choice,i,f;
long pos;
char another,ch,word[3][30];

fs=fopen("c:\\ctxt\\11TEST.txt","r+");

while(1)
{
clrscr();
printf("1) Key in new data");
printf("\n2) List down the data keyed");
printf("\n3) Exit\n");
scanf("%d",&choice);

switch(choice)
{
case 1:
clrscr();
fseek(fs,0,SEEK_END);
while(1)
{
clrscr();
another='n';
printf("Key in name\n");
fflush(stdin);
scanf("%[^\n]s",d.name);
printf("Key in score\n");
scanf("%d",&d.numb);
fprintf(fs,"%s(double spacing here) %d\n",d.name,d.numb);
clrscr();
printf("Do you want to key in another record?(y/n)");
fflush(stdin);
another=getche();
if(another!='y')
break;
}
break;

case 2:
clrscr();
fseek(fs,0,SEEK_SET);
while(ch!=EOF)
{
d.name[0]='\0';
word[0][0]='\0';
word[1][0]='\0';
word[2][0]='\0';
f=0;
for(i=1;ch!=EOF,f==0;i++)
{

ch=fscanf(fs,"%s",word[i-1]);

ch=fgetc(fs);
if(ch==32)
{
f=0;

}
else
{
f=1;
break;
}
ch=fgetc(fs);
if(ch!=32)
{
f=0;

}
else
{
f=2;
break;
}
fseek(fs,-2,SEEK_CUR);
}
if(f==2)
fseek(fs,-2,SEEK_CUR);

if(i==2)
{
strcat(word[0]," ");
strcat(word[0],word[1]);
}
if(i==3)
{
strcat(word[0]," ");
strcat(word[0],word[1]);
strcat(word[0]," ");
strcat(word[0],word[2]);
}
strcpy(d.name,word[0]);
if(d.name[0]=='\0')
break;
printf("%s",d.name);
ch=fscanf(fs,"%d",&d.numb);
printf(" %d\n",d.numb);
if(ch==EOF)
break;
}

case 3:
fclose(fs);
exit();
}
}
}