Thread: Reading a file, sorting and counting contents, help?

  1. #1
    Registered User
    Join Date
    Apr 2005
    Posts
    7

    Reading a file, sorting and counting contents, help?

    Ok I have program due for my class. And it's a doozy, at least for me, I'm supposed to give the user a choice of 5 files to read. Then tell them the first and last 10 words of the file and how many times that word occurs in the file. Then sort the words alphabetically and tell them the first and last 10 words again and how many times they occur. I need some help with a few aspects

    1. How do I print the last 10 words?
    2. How can I get the count to print in a table form. All pretty and even and stuff.
    3. For some reason it only works when the user chooses 1. I have all the files saved in the same place. I can't see why it wouldn't work for the other choices.

    Here's what I have so far, and just ignore that the count is 0 for every word, I haven't worked on that part yet. Thanks for any help in advance.

    Code:
    #include <stdio.h>
    #include <string.h>
    
    int main( )
    {
    FILE *myfile = NULL; //file pointer
    int fileselect; //holds the choice
    char filename[30]; //holds the file name
    char words[5000][20]; //array to hold the words
    int i; //for the loop
    int x=0;
    
    while(1)
    {
        printf( "\nSelect the number of the text file to read\n");
        printf( "1 - words_emancip\n");
        printf( "2 - words_flatland\n");
        printf( "3 - words_macbeth\n");
        printf( "4 - words_prince\n");
        printf( "5 - words_purloin\n");
        printf("6 - Quit\n");
    
        fflush( stdin);
        scanf( "%d", &fileselect);
        printf( "\n");
    
        switch(fileselect)
        {
    
           case 1: strcpy(filename, "words_emancip.txt");
                         break;
           case 2: strcpy(filename, "words_flatland.txt");
                         break;
           case 3: strcpy(filename, "words_macbeth.txt");
                         break;
           case 4: strcpy(filename, "words_prince.txt");
                         break;
           case 5: strcpy(filename, "words_purloin.txt");
                         break;
           case 6: printf("Goodbye!\n");
                         return 0;
                         break;
           default: printf("That is not a valid choice.\n");
                         break;
           }
    
    
    
           myfile=fopen(filename, "r");
    
           if(myfile==NULL)
           {
                  printf("File not found\n");
           }
    
           //stores the words into the array words
           for(i=0; !feof(myfile); i++)
           {
                  fscanf(myfile, "%s ", &words[i]);
           }
    
           //print the first 10
           printf( "First 10 words of the unsorted array\n");
    
           for(i=0; i<10; i++)
           {
                  printf("Word # %d = %s ,Count = %d\n", i, words[i], x);
           }
    
           fclose(myfile);
    
    }
    
    
    return 0;
    }
    Last edited by mmmm_strawberri; 04-03-2005 at 05:01 PM.

  2. #2
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    1) Your indentation is horrible. Oh wait, there isn't any.
    2) Read this FAQ entry on why fflush( stdin ) is wrong.
    3) Read this FAQ entry on why you shouldn't use feof to control loops.

    That'll get you started.

    Quzah.
    Hope is the first step on the road to disappointment.

  3. #3
    Registered User
    Join Date
    Apr 2005
    Posts
    7
    Sorry about the indentation, that's just how it copied and pasted into it. My professor told us we had to use fflush, and feof. He won't let us use things he hasn't taught us himself. So that didn't help, but thanks anyway.

  4. #4
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Well your professor is an idiot. Send him here so he can learn a few things. Oh, and I meant for you to actually read those links.

    Quzah.
    Hope is the first step on the road to disappointment.

  5. #5
    Registered User
    Join Date
    Apr 2005
    Posts
    7
    I have read those links, I understand what you are saying. But I can't change my program to suit the content of those links due to restrictions from my professor. The fact that he is an idiot doesn't change the fact that I must program the way he wants, he's the one giving me the grade.

  6. #6
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    You're telling me you can't use the return value of fscanf, and are forced to rely on feof? I find that hard to believe. Also, do you know how to read a character at a time from a file? If so, that takes care of your input flush.

    You're also saying that you're too lazy to edit your post and indent it I guess.

    Quzah.
    Hope is the first step on the road to disappointment.

  7. #7
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    Perhaps your "prof" would care to explain why this program is broken then.
    Code:
    #include <stdio.h>
    
    int main(void)
    {
        char words[100][10];
        FILE *fp = fopen( "words.txt", "r" );
        int i,j;
        for ( i = 0 ; !feof(fp) ; i++ ) {
            fscanf( fp, "%s", words[i] );
        }
        fclose( fp );
        printf( "Number of words read = %d\n", i );
        for ( j = 0 ; j < i ; j++ ) {
            printf( "Word %d = %s\n", j, words[j] );
        }
        return 0;
    }
    I get this output
    Code:
    $ cat words.txt && ./a.out
    hello
    world
    Number of words read = 3
    Word 0 = hello
    Word 1 = world
    Word 2 =
    Now quite what that last entry is is a mystery, since the text file in question has only got TWO words in it.

    > he's the one giving me the grade.
    But you're the one paying for the education, and perhaps hoping to get a job at the end of it.
    If he's nothing more than a "dung merchant", then isn't it better you figure that out sooner rather than later?
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  8. #8
    Registered User
    Join Date
    Apr 2005
    Posts
    7
    Ok the original code is now full of tabs.

    And yes I am saying that my professor forces me to use feof and fflush(stdin).

    I know I'm the one paying for my education but I see no point in starting a revolution against my teacher because he uses some out of date coding, as long as I know that it's out of date and I know the better, more modern, alternative then it doesn't really matter what he makes me put in the program I turn in. Also I am in an intro to programming class, he's just introducing us to programming, I'm not expecting to come out of this class with a deep knowledge for all things programming related. Regardless I'd like to just code the way he wants, get a good grade in the class, and read online tutorials, read message boards, and talk to other programmers to get my programming knowledge.

    Right now what I need help with is this program, that is restrained to the wishes of my professor. Can you please answer my questions?

  9. #9
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    It's not "out of date". It's wrong. Neither of those have ever been correct. They didn't just "update" them and now they're obsolete. They've never ever been the right way to do it.

    Sure, I'll answer your question. Keep track of the total number of read items. Now subtract 10 from that. Start your loop there, end it when you've displayed ten items.

    Perhaps your professor can teach you basic logic while they're at it.

    Furthermore, I think you're a liar. I doubt very much that your professor said: "Do not use the return value of fscanf to see when you've reached the end. Instead, you MUST use feof to control your loop!"

    Quzah.
    Hope is the first step on the road to disappointment.

  10. #10
    Registered User
    Join Date
    Apr 2005
    Posts
    7
    Well thank you for answering my question.

    Forgive me for saying they are out of date. Thank you for correcting me. Now I will know for future reference. But when this program compiles and run. It's what I've used for all previous homework assignments, it's what he uses in his examples.

    And Furthermore I am not a liar. Who are you to say what my professor told me to do and what not to do. Do you honestly think anybody in their right mind would listen to so many people telling him that he is wrong and insist on doing it the wrong way anyway. THe only reason I am writing this program in this way is because I have been told to do it.

    All I needed was a few questions answered. Is that so hard to do without confrontation?

  11. #11
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    I never said you were in your right mind. Why would I make that assumption based on this conversation? One last time, and I'm done with this thread:
    Code:
    //stores the words into the array words
           for(i=0; !feof(myfile); i++)
           {
                  fscanf(myfile, "%s ", &words[i]);
           }
    Aside from the obvious feof problem, watch me kill your program by having more lines in my file than you have in your array. Ooops. I guess your professor didn't expect that.

    Code:
    while( i < whateversize && fscanf( fp, "%s", words[i] ) == 1 )
        i++;
    Yeah, much worse. You should definately fail for that.

    Quzah.
    Hope is the first step on the road to disappointment.

  12. #12
    Registered User
    Join Date
    Apr 2005
    Posts
    7
    Ok I'm going to ask this again. Hopefully I can get an intelligent, helpful response from somebody besides quzah. If not, I suppose I'll find help somewhere else.

    Can anybody see why the program I posted will crash if I enter 2-5?

  13. #13
    Yes, my avatar is stolen anonytmouse's Avatar
    Join Date
    Dec 2002
    Posts
    2,544
    >> 2. How can I get the count to print in a table form. All pretty and even and stuff. <<

    Pad the word with spaces so it occupies a fixed-width column:
    - Print out word.
    - For i = 0 to (20 - strlen(word)) print space
    - Print count

    >> 3. For some reason it only works when the user chooses 1. I have all the files saved in the same place. I can't see why it wouldn't work for the other choices. <<

    The only difference appears to be the filename. What is different about these files? Do they exist? Do they have too many words? Is a word too long?

    You can sort your words array with the help of the qsort function.

  14. #14
    Registered User
    Join Date
    Apr 2005
    Posts
    7
    Thank you anonytmouse, it looks much better now.

    My files are all the same pretty much. They're all saved in the same location, and all the words are under 20 letters long and none contain more than 5000 words. I'm completely stumped.

  15. #15
    Registered User
    Join Date
    Apr 2004
    Posts
    173
    Here's a sample code that I coded up (quite messy since I rushed it a bit )
    Then again, it's better than nothing so! Note this uses fscanf() to control the loop not feof(), if you "must" use feof() then you should do something about the irregularities of using feof(). Such as being "1 loop" late at noticing the EOF indicator, which means you should minus 1 from count and discard the last reading. Even if your professor mentioned to use feof() I would recommend sending him an e-mail about it because like Quzah said it's wrong to do.

    Code:
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    
    int sequential_search(char* word_table[], char* key, int word_count);
    void initialisation(char* objects[]);
    
    int main(void)
    {
    	FILE* fp;
    	int fileselect;
    	char filename[BUFSIZ];
    	char* words[10000];
    	int word_count = 0;
    
    	int i;
    	int j;
    	
    	while(1)
    	{
    		printf("\nSelect filename: \n");
    		printf("1 - words_death\n");
    		printf("2 - words_live\n");
    		printf("3 - Quit\n");	
    	
    		scanf("%d",&fileselect);
    
    		printf("\n");
    	
    		switch(fileselect)
    		{
    			case 1:
    				strcpy(filename,"words_death.txt");
    				break;
    			case 2:
    				strcpy(filename,"words_live.txt");
    				break;
    			case 3:
    			default:
    				return 0;
    		}
    
    		fp = fopen(filename,"r");
    		if (fp == NULL)
    		{
    			fprintf(stderr,"Could not open!");
    			return 1;
    		}
    
    		initialisation(words);
    		/* Read all words */
    		while (fscanf(fp,"%s",words[word_count]) != EOF)
    		{
    			word_count++;
    		}
    
    		i = word_count;
    
    		printf("\n\nThe first ten words: \n");
    		/* Print first ten words */
    		for (j = 0; j < 10 && j < i; j++)
    		{
    			printf("%d:\t %s\t\t\n",j+1,words[j],
    				sequential_search(words,words[j],word_count));
    		}
    
    		printf("\n\nThe last ten words: \n");
    		if (i > 10)
    			j = i - 10;
    		else
    			j = 0;
    	
    		/* Print last ten words */
    		for ( ; j < i ; j++)
    		{
    			printf("%d:\t %s\t\t%d\n",j+1, words[j],
    				sequential_search(words,words[j],word_count));
    		}
    
    
    		/* Echo the amount of words */
    		printf("\n\nOverall amount of words in file %s: %d\n",
    				filename,word_count);
    
    		if (fclose(fp) == EOF)
    		{
    			fprintf(stderr,"Could not close!");
    			return 1;
    		}
    
    		return 0;
    	}
    }
    
    int sequential_search(char* word_table[], char* key, int word_count)
    {	
    	int i; 
    	int instances = 0;
    
    	for (i = 0; i < word_count; i++)
    	{
    		if (strcmp(key,word_table[i]) == 0)
    			instances++;
    	}	
    	return instances;
    }
    
    void initialisation(char* objects[])
    {
    	int i;
    	for (i = 0 ; i < 10000; i++){
    		objects[i] = malloc(sizeof(char) * BUFSIZ);
    	}
    }
    I've used different filenames to what you did but it shouldn't really matter. The sequential search algorithm is just used to count how many instances the word appears in the file after all the words are read in by the fscanf() function.

    Heres a sample output:
    Code:
    bash-3.00# ./file1
    
    Select filename: 
    1 - words_death
    2 - words_live
    3 - Quit
    1
    
    The first ten words: 
    1:       hmmm           1
    2:       this           1
    3:       is             1
    4:       a              2
    5:       word           1
    6:       that           2
    7:       I              7
    8:       should         1
    9:       never          1
    10:      forget         1
    
    
    The last ten words: 
    55:      was            1
    56:      only           1
    57:      a              2
    58:      dream..                1
    59:      dammit!                1
    60:      I              7
    61:      dreamt         1
    62:      for            1
    63:      45             1
    64:      years!         1
    
    
    Overall amount of words in file words_death.txt: 64
    There are some small formatting issues that I would leave up to you to fix. It's primarily to give you an idea on how to approach the problem. I recommend you code small sections of the problem to see how it works before putting that section into your main code, it helps in both debugging and understanding the problem.

    After you have implemented up to this stage with your files and how you want it formatted etc. you will need to make a sorting function or simply use the qsort() function from C as anonytmouse mentioned. Simply send in the strcmp() function as a function pointer to the qsort() function if you are using it.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 26
    Last Post: 06-11-2009, 11:27 AM
  2. Counting sorting operations
    By Cpro in forum C++ Programming
    Replies: 19
    Last Post: 01-25-2008, 10:46 AM