14 Replies - 3722 Views - Last Post: 01 January 2009 - 01:11 AM Rate Topic: -----

#1 clueless_81  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 9
  • Joined: 17-December 08

How to randomly select a word from a file and display it

Posted 19 December 2008 - 03:47 PM

Dear all,

I using C and not C++.

Can anyone advise me how to select a word RANDOMLY from a file (e.g. 30 words) and display it?
I only know how to select the whole text. Something like this,

fp=fopen("textfile.txt","r");
while(fscanf(fp,"%d %s %lf %c", &number, name, &number, &gender)!=EOF)
printf().....

Thank you.
Is This A Good Question/Topic? 0
  • +

Replies To: How to randomly select a word from a file and display it

#2 KYA  Icon User is offline

  • g++ jameson.cpp -o beverage
  • member icon

Reputation: 3101
  • View blog
  • Posts: 19,141
  • Joined: 14-September 07

Re: How to randomly select a word from a file and display it

Posted 19 December 2008 - 04:15 PM

//something like this:
 int messageNumber;
  int count;
  string message;
  ifstream in;
  //srand(time(NULL)); seed in main()

  in.open("filename.txt");
  in >> count;

  for(int i = 0; i < rand()%messageNumber+1; i++)
  {
	getline(in, message);
  }
  cout << message;


Was This Post Helpful? 0
  • +
  • -

#3 Hyper  Icon User is offline

  • Banned

Reputation: 108
  • View blog
  • Posts: 2,129
  • Joined: 15-October 08

Re: How to randomly select a word from a file and display it

Posted 19 December 2008 - 06:00 PM

KYA, You totally forgot one thing! You need to get the files size so you don't over-shoot, then use rand() like so...

srand(time(NULL));
int quote = 0;
int filesize = 0;
quote = rand() % filesize;



That was so poorly written, but still.

This post has been edited by Hyper: 19 December 2008 - 06:01 PM

Was This Post Helpful? 0
  • +
  • -

#4 baavgai  Icon User is offline

  • Dreaming Coder
  • member icon

Reputation: 5826
  • View blog
  • Posts: 12,678
  • Joined: 16-October 07

Re: How to randomly select a word from a file and display it

Posted 19 December 2008 - 08:09 PM

This one fascinated me, so I wrote a solution. Is it possible to randomly choose a line in a file if I don't know the size of the file? More, I don't want to store every line, just choose one randomly.

Here's my thought. Choose the first line. Read the next line, there is a 1/2 chance you want to replace the prior line with the current one. For the next line, 1/3, then 1/4, and so on. I'm not sure of the mathematical validity of this approach, but a quickly mocked up program for sampling seems to prove out the method.

Here's the code. Sorry for such a complete solution, but I didn't think it would be clear any other way.

#include <stdio.h>
#include <string.h>
#include <time.h>

#define MAX_STRING_SIZE 1000

int main() {
	char str[MAX_STRING_SIZE], pick[MAX_STRING_SIZE];
	FILE *fp;
	int readCount = 0;
	
	srand(time(NULL));
	
	fp = fopen("test.txt", "r");
	if(fp) {
		if (fgets(pick, MAX_STRING_SIZE, fp) != NULL) {
			readCount = 1;
			while(fgets(str, MAX_STRING_SIZE, fp) != NULL) {
				if ( (rand() % ++readCount)==0) {
					strcpy(pick, str);
				}
				// printf("%d\t%s", readCount, str);
			}
		}
	}
	fclose(fp);
	printf("%s\n", pick);
}



Hope this helps.

Ah, hell, here's my test, too, if anyone is interested:
#include <stdio.h>
#include <time.h>

#define POOL_SIZE 20
#define SAMPLE_SIZE 10000

int main() {
	int hits[POOL_SIZE];
	int i, n, pick, count;
	
	srand(time(NULL));
		
	for(i=0; i<POOL_SIZE; i++) { hits[i] = 0; }
	
	for(i=0; i<SAMPLE_SIZE; i++) {
		pick = 0;
		count = 1;
		for(n=1; n<POOL_SIZE; n++) {
			if ( (rand() % ++count)==0) {
				pick = n;
			}
		}
		hits[pick] = hits[pick] + 1;
	}
	
	for(i=0; i<POOL_SIZE; i++) { 
		printf("%d\t%d\t%f\n", i, hits[i], hits[i]/(float)SAMPLE_SIZE);
	}
	
	return 0;
}


Was This Post Helpful? 1
  • +
  • -

#5 clueless_81  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 9
  • Joined: 17-December 08

Re: How to randomly select a word from a file and display it

Posted 20 December 2008 - 09:56 AM

View Postbaavgai, on 19 Dec, 2008 - 07:09 PM, said:

This one fascinated me, so I wrote a solution. Is it possible to randomly choose a line in a file if I don't know the size of the file? More, I don't want to store every line, just choose one randomly.

Here's my thought. Choose the first line. Read the next line, there is a 1/2 chance you want to replace the prior line with the current one. For the next line, 1/3, then 1/4, and so on. I'm not sure of the mathematical validity of this approach, but a quickly mocked up program for sampling seems to prove out the method.

Here's the code. Sorry for such a complete solution, but I didn't think it would be clear any other way.

#include <stdio.h>
#include <string.h>
#include <time.h>

#define MAX_STRING_SIZE 1000

int main() {
	char str[MAX_STRING_SIZE], pick[MAX_STRING_SIZE];
	FILE *fp;
	int readCount = 0;
	
	srand(time(NULL));
	
	fp = fopen("test.txt", "r");
	if(fp) {
		if (fgets(pick, MAX_STRING_SIZE, fp) != NULL) {
			readCount = 1;
			while(fgets(str, MAX_STRING_SIZE, fp) != NULL) {
				if ( (rand() % ++readCount)==0) {
					strcpy(pick, str);
				}
				// printf("%d\t%s", readCount, str);
			}
		}
	}
	fclose(fp);
	printf("%s\n", pick);
}



Hope this helps.

Ah, hell, here's my test, too, if anyone is interested:
#include <stdio.h>
#include <time.h>

#define POOL_SIZE 20
#define SAMPLE_SIZE 10000

int main() {
	int hits[POOL_SIZE];
	int i, n, pick, count;
	
	srand(time(NULL));
		
	for(i=0; i<POOL_SIZE; i++) { hits[i] = 0; }
	
	for(i=0; i<SAMPLE_SIZE; i++) {
		pick = 0;
		count = 1;
		for(n=1; n<POOL_SIZE; n++) {
			if ( (rand() % ++count)==0) {
				pick = n;
			}
		}
		hits[pick] = hits[pick] + 1;
	}
	
	for(i=0; i<POOL_SIZE; i++) { 
		printf("%d\t%d\t%f\n", i, hits[i], hits[i]/(float)SAMPLE_SIZE);
	}
	
	return 0;
}




Hi baavgai,

Thank you for your advice. Appreciate it greatly.
I tried to compile it and manage to randomly select a word from a file with several words.
However, I'm facing another problem now.

I'm actually doing a hangman program, it's almost 90% completed after I used your RAND code.
As I tried to display the number of words for a player to guess in the form of '***', \0 is also being read and there is always an extra *. My code as follow,

while(a[n]!=NULL) n++;
for(i=0;i<n;i++) c[i]='*';
printf("c=%s\n",c);

Note: 'a' is a word being selected from the file.

Could you advise on this case? Thanks a lot.
Was This Post Helpful? 0
  • +
  • -

#6 KYA  Icon User is offline

  • g++ jameson.cpp -o beverage
  • member icon

Reputation: 3101
  • View blog
  • Posts: 19,141
  • Joined: 14-September 07

Re: How to randomly select a word from a file and display it

Posted 20 December 2008 - 10:08 AM

You don't really need two loops there:

for(int i = 0; a[i] != '\0'; i++)
{
	printf("*"); //or whatever
}


Was This Post Helpful? 0
  • +
  • -

#7 clueless_81  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 9
  • Joined: 17-December 08

Re: How to randomly select a word from a file and display it

Posted 20 December 2008 - 07:43 PM

View PostKYA, on 20 Dec, 2008 - 09:08 AM, said:

You don't really need two loops there:

for(int i = 0; a[i] != '\0'; i++)
{
	printf("*"); //or whatever
}




View PostKYA, on 20 Dec, 2008 - 09:08 AM, said:

You don't really need two loops there:

for(int i = 0; a[i] != '\0'; i++)
{
	printf("*"); //or whatever
}




Hi KYA,

Thank you for the reply.
It does not solve the problem.

I'm not sure why but there is always an extra 1 or 2 * when I tried to display the number of characters.
Do you have a solution for it?

If the last word of the file is being selected, the number of * will display correctly though. Is it due to the method of putting those words in the file like should I include ',' or something?
Was This Post Helpful? 0
  • +
  • -

#8 KYA  Icon User is offline

  • g++ jameson.cpp -o beverage
  • member icon

Reputation: 3101
  • View blog
  • Posts: 19,141
  • Joined: 14-September 07

Re: How to randomly select a word from a file and display it

Posted 20 December 2008 - 08:37 PM

Probably because you are allocating an additional whitespace at the end. I'd have to see the code you use to store the array though.
Was This Post Helpful? 0
  • +
  • -

#9 Hyper  Icon User is offline

  • Banned

Reputation: 108
  • View blog
  • Posts: 2,129
  • Joined: 15-October 08

Re: How to randomly select a word from a file and display it

Posted 21 December 2008 - 06:44 AM

View Postbaavgai, on 19 Dec, 2008 - 07:09 PM, said:

This one fascinated me, so I wrote a solution. Is it possible to randomly choose a line in a file if I don't know the size of the file? More, I don't want to store every line, just choose one randomly.


Um, correct me if I'm wrong, but you can use seekg to set it to the end of the file without ever having to "know" the end of the file, then check where it's at, no? I can vaguely remember reading on that a while back.
Was This Post Helpful? 0
  • +
  • -

#10 KYA  Icon User is offline

  • g++ jameson.cpp -o beverage
  • member icon

Reputation: 3101
  • View blog
  • Posts: 19,141
  • Joined: 14-September 07

Re: How to randomly select a word from a file and display it

Posted 21 December 2008 - 07:26 AM

Yes and subtracting seekg from the end to the beginning can give you a numerical "length" to work with.
Was This Post Helpful? 0
  • +
  • -

#11 clueless_81  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 9
  • Joined: 17-December 08

Re: How to randomly select a word from a file and display it

Posted 21 December 2008 - 07:49 AM

View PostKYA, on 20 Dec, 2008 - 07:37 PM, said:

Probably because you are allocating an additional whitespace at the end. I'd have to see the code you use to store the array though.


HI KYA,

Thanks. The code that I used to store and get the array is as follow.

#define MAX_STRING 20

srand(time(NULL));
	fp=fopen("word2.txt","r");

	 if(fp) {
		if (fgets(a, MAX_STRING, fp) != NULL) {
			
			flag=1;
			
			while(fgets(str, MAX_STRING, fp) != NULL) {

				if ( (rand() % ++flag)==0) {

					strcpy(a, str);
                        }
             }
        }  
     }
fclose (fp);



Thanks.

** Edit ** :code:
Was This Post Helpful? 0
  • +
  • -

#12 Hyper  Icon User is offline

  • Banned

Reputation: 108
  • View blog
  • Posts: 2,129
  • Joined: 15-October 08

Re: How to randomly select a word from a file and display it

Posted 30 December 2008 - 01:55 PM

View PostKYA, on 21 Dec, 2008 - 06:26 AM, said:

Yes and subtracting seekg from the end to the beginning can give you a numerical "length" to work with.


Quote

Constants
These constants can be combined eg bin_open_file("example.bin", IOS_IN | IOS_OUT)
IOS_IN allow read operations
IOS_OUT allow write operations
IOS_APP appends to a file
IOS_TRUNC current content is discarded
IOS_ATE starts at the end of the file


I was researching my own question earlier last night. Here's the answer:
Open a file with ios_ate, use tellg(); to get the file pointer (which'll be (obviously) at the end), now you have a limit in which you can randomize in (within the files length).

It's quite simple, and effective! :)

Sorry for the late post.
Hope this helps (if it does, remember to click the little green button that says "This Post Was Helpful!")! :D
Was This Post Helpful? 0
  • +
  • -

#13 numerical_jerome  Icon User is offline

  • D.I.C Head

Reputation: 12
  • View blog
  • Posts: 167
  • Joined: 16-September 07

Re: How to randomly select a word from a file and display it

Posted 30 December 2008 - 08:18 PM

Would draw your attention to the following procedures (C++ file structs aren't actually objects, they just dress up and play them on t.v.):

long ftell(FILE *) --> gives the current position in the file
int fseek(FILE *, int, int) --> moves the current position in stream [first arg] to N [second arg] places from an origin [last arg], where the origins are as follows:

SEEK_SET --> offset to beginning of file
SEEK_CUR --> current location in buffer
SEEK_END --> end of file

so the simple solution would be:


FILE * fin = fopen("file name", "r"); // open file
do
{
	fseek(fin, 0, SEEK_END);  // find the end of the file
	fseek(fin, -1 * (rand() % ftell(fin)), SEEK_END);  // move back random characters
	while(!isspace(fgetc(fin) && !feof(fin)); // find the first white space
	while(isspace(fgetc(in) && !feof(fin)); // find the start of the word
	fseek(fin, -1, SEEK_CUR); // step back, stream is now at the start of the random word
}
while(feof(fin));  // if the first white space was NULL / EOF, try again




-Jerome
Was This Post Helpful? 0
  • +
  • -

#14 baavgai  Icon User is offline

  • Dreaming Coder
  • member icon

Reputation: 5826
  • View blog
  • Posts: 12,678
  • Joined: 16-October 07

Re: How to randomly select a word from a file and display it

Posted 30 December 2008 - 08:35 PM

View PostHyper, on 30 Dec, 2008 - 02:55 PM, said:

Open a file with ios_ate, use tellg(); to get the file pointer (which'll be (obviously) at the end), now you have a limit in which you can randomize in (within the files length).

It's quite simple, and effective! :)


Makes sense, for a specific case.

What if my file is a list of quotes, or simple comma separated values. Your method makes sense if all records are exactly the same length. If it's not a static record structure, then if you use the filesize to choose a position in the file, you're preferring larger records and failing random.

The goal is to "select a word RANDOMLY from a file". My assumption is that the words will not be padded for size and are separated by new lines. If this is the case, your approach is not random and adds some complexity.
Was This Post Helpful? 0
  • +
  • -

#15 Hyper  Icon User is offline

  • Banned

Reputation: 108
  • View blog
  • Posts: 2,129
  • Joined: 15-October 08

Re: How to randomly select a word from a file and display it

Posted 01 January 2009 - 01:11 AM

View Postbaavgai, on 30 Dec, 2008 - 07:35 PM, said:

View PostHyper, on 30 Dec, 2008 - 02:55 PM, said:

Open a file with ios_ate, use tellg(); to get the file pointer (which'll be (obviously) at the end), now you have a limit in which you can randomize in (within the files length).

It's quite simple, and effective! :)


Makes sense, for a specific case.
.........

The goal is to "select a word RANDOMLY from a file".


You'd stated earlier (read your posts) you were unaware of how to obtain the full filesize so you could grab between X and X (beginning to ending), which is what I was answering. Unless I mis understood what you'd meant by that.

If you wanted to grab a random quote from a list inside of a file, you'd first off want to do what I'd posted regarding the files size (so you don't try to get text from another file), secondly, you'd want to check for a return line, if one's found, quit reading. If it's an unformatted file - but still cleartext - then the user is making it much harder and more difficult, and should change his ways. If the user does not, then he can build a case-specific solution to that unformatted (no enters, and not binary format) file.

Either way: Welcome.
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1