Thread: opening a file... should be easy fix

  1. #1
    Shake Zula- The Mic Rula!
    Join Date
    Sep 2004
    Posts
    69

    opening a file... should be easy fix

    will someone please tell me why this won't open the file "defs.dat", i have the "defs.dat" in the same folder as the .cpp program, i don't understand...
    Code:
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <iostream.h>
    #include <fstream.h>
    #include <ctype.h>
    
    
    // class definition
    class wordanddef
    {
    public:
    	char word[20];
    	char def[80];
    };
    
    // function definitions
    int loaddata(char *fn, wordanddef *wadptr[]);
    void sortdata(int numlines, wordanddef *wadptr[]);
    int findword(int numlines, wordanddef *wadptr[], char *wrd);
    
    // main program
    int main(void)
    {
    char fname[100], sword[20], origword[20];
    int linecnt, fwordnum, ccnt;
    wordanddef *pwordanddef[400];
    
    	// setup file name
    	strcpy(fname, "defs.dat");
    
    	// load data from file, returns number of line read from file
    	linecnt=loaddata(fname, pwordanddef);
    	if(linecnt==-1)
    	{
    		cout<<"File open failed.\n";
            system("Pause");
    		exit(1);
    	}
    
    	// sort the data
    	sortdata(linecnt, pwordanddef);
    
    	// allow user to search for words
    	while(1)
    	{
    		// prompt user for search word
    		cout<<"\nEnter the word to search for, or leave blank to quit:  ";
    		cin.getline(sword, 20);
            strcpy(origword, sword);
    
    		// change all characters to upper case
    		for(ccnt=0; ccnt<strlen(sword); ccnt++)
            	sword[ccnt]= toupper(sword[ccnt]);
    
    		// exit for blank search word
    		if(strcmp(sword, "")==0) exit(1);
    
    		// search for the word
    		fwordnum=findword(linecnt, pwordanddef, sword);
    
    		// print the result
    		if(fwordnum==-1) cout<<"\nNot found.\n";
    		else
    		{
    			cout<<"\nWord found.\n";
                cout<<"Original word as typed (LaRue): "<<origword<<"\n";
    			cout<<"Word: "<<pwordanddef[fwordnum]->word<<"\n";
    			cout<<"Definition: "<<pwordanddef[fwordnum]->def<<"\n";
    
    		}
    	}
    
    }
    
    // function to load data from file
    int loaddata(char *fn, wordanddef *wadptr[])
    {
    ifstream file;
    char line[80];
    int i, j;
    int cnt=0;
    
    	// open the file
    	file.open(fn);
    
    	// make sure file opened okay
    	if(file.fail()) return -1;
    
    	// read until end of file
    	while(!file.eof())
    	{
    		// set character counters
    		i=0;
            j=0;
    
    		// get line into character string
    		file.getline(line, 80, '\n');
    
    		// new class instance
    		wadptr[cnt] = new wordanddef;
    
    		// copy the word into the new class, change all characters to upper case
    		while(i<strlen(line))
    		{
    			if(line[i]!=' ') wadptr[cnt]->word[i]=toupper(line[i]);
                else break;
    			i++;
    		}
    		wadptr[cnt]->word[i]=0;
    
    		// skip the white space between word and definition
    		while(line[i]==' ')
    		i++;
    		
    		// copy the definition into the new class
    		while(i<strlen(line))
    		{
    			if(line[i]!=' ') wadptr[cnt]->def[j]=line[i];else break;
    			i++;
    			j++;
    		}
    		wadptr[cnt]->def[j]=0;
    
    		// increase the line count
    		cnt++;
    	}
    
    	// close the file
    	file.close();
    
    	// return the number of lines
    	return cnt;
    }
    
    // function to sort data by alphabet
    void sortdata(int numlines, wordanddef *wadptr[])
    {
    int swap, sortcnt;
    wordanddef *twadptr;
    
    	// sort the pointers, alpha by word
    	swap=1;
    	while(swap)
    	{
    		swap=sortcnt=0;
    		while(sortcnt<numlines-1)
    		{
    			if(strcmp(wadptr[sortcnt]->word, wadptr[sortcnt+1]->word)>0)
    			{
    				twadptr=wadptr[sortcnt];
    				wadptr[sortcnt]=wadptr[sortcnt+1];
    				wadptr[sortcnt+1]=twadptr;
    				swap=1;
    			}
    			sortcnt++;
    		}
    	}
    }
    
    // search data for a word
    int findword(int numlines, wordanddef *wadptr[], char *wrd)
    {
    int i;
    
    	for(i=0; i<numlines; i++)
    	{
    		if(strcmp(wadptr[i]->word, wrd)==0) return i;
    	}
    
    	return -1;
    }

  2. #2
    Registered User hk_mp5kpdw's Avatar
    Join Date
    Jan 2002
    Location
    Northern Virginia/Washington DC Metropolitan Area
    Posts
    3,817
    What compiler are you using? How are you running the program, from within an IDE of some kind or from the command line?

    Code:
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <iostream.h>
    #include <fstream.h>
    #include <ctype.h>
    These are all old/deprecated headers, you should be using the newer ones if possible:

    Code:
    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <iostream>
    #include <fstream>
    #include <cctype>
    using namespace std;
    You can potentially overrun your pwordanddef array in your code. You allocate space for a maximum of 400 elements but do nothing in your loaddata function to guard against more than 400 records being loaded:

    Code:
    int cnt=0;
    
    // open the file
    file.open(fn);
    
    // make sure file opened okay
    if(file.fail()) return -1;
    
    // read until end of file
    while(!file.eof())
    {
        ...
    
        // new class instance
        wadptr[cnt] = new wordanddef;
    
        ...
    
        // increase the line count
        cnt++;
    }
    You can easily protect yourself against over running this array:

    Code:
    int cnt=0;
    
    // open the file
    file.open(fn);
    
    // make sure file opened okay
    if(file.fail()) return -1;
    
    // read until end of file
    while(!file.eof() && cnt < 400)
    {
        ...
    
        // new class instance
        wadptr[cnt] = new wordanddef;
    
        ...
    
        // increase the line count
        cnt++;
    }
    You have similar potential problems copying the word and definition into the class members. word can hold at most 20 characters with the last character always being set to 0, thus you should make sure you only copy at most 19 characters into the array. Likewise for the def member you should only copy at most 79 characters into the array, the last one always being set to 0:

    Code:
    // copy the word into the new class, change all characters to upper case
    while(i<strlen(line) && i < 19  )
    {
        if(line[i ]!=' ') wadptr[cnt]->word[i ]=toupper(line[i ]);
        else break;
        i++;
    }
    wadptr[cnt]->word[i ]=0;
    
    ...
    
    // copy the definition into the new class
    while(i<strlen(line) && j < 79)
    {
        if(line[i ]!=' ') wadptr[cnt]->def[j]=line[i ];
        else break;
        i++;
        j++;
    }
    wadptr[cnt]->def[j]=0;
    As an aside, your program seems a perfect opportunity for use of a map<string,string> STL container. You wouldn't need to allocate space for an array of objects. The sorting is handled automatically for you by the container itself. Adding and searching for elements in the container is easy.

    At the very least you could look up how to use the string containers. They could help tremendously here.
    "Owners of dogs will have noticed that, if you provide them with food and water and shelter and affection, they will think you are god. Whereas owners of cats are compelled to realize that, if you provide them with food and water and shelter and affection, they draw the conclusion that they are gods."
    -Christopher Hitchens

  3. #3
    Shake Zula- The Mic Rula!
    Join Date
    Sep 2004
    Posts
    69

    thanks

    thanks alot, i got it workin.... i know about protecting for the buffer overrun, but there will never be more than 19 entered for the word to search for and no more than 79 ever for the definition, otherwise i would've put that in there, heck, i might as well do it anyways just to protect against it, i'm not familiar with the string containers, are they covered in the FAQ?

  4. #4
    Registered User
    Join Date
    Jun 2004
    Posts
    722
    Quote Originally Posted by hk_mp5kpdw
    Code:
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <iostream.h>
    #include <fstream.h>
    #include <ctype.h>
    These are all old/deprecated headers, you should be using the newer ones if possible:
    Not old nor deprecated... Simply don't comply with the C++ standard. Those are C standard libs...!

  5. #5
    Registered User jlou's Avatar
    Join Date
    Jul 2003
    Posts
    1,090
    Actually,
    Code:
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <ctype.h>
    I believe these are standard in C++, but they are deprecated in favor of the C++ versions.
    Code:
    #include <iostream.h>
    #include <fstream.h>
    and these are non-standard in C and C++, and are therefore just old.

    So hk_mp5kpdw was correct, those headers are all old and/or deprecated.

  6. #6
    Registered User hk_mp5kpdw's Avatar
    Join Date
    Jan 2002
    Location
    Northern Virginia/Washington DC Metropolitan Area
    Posts
    3,817
    A possible version of this program using strings and a map:

    Code:
    #include <map>
    #include <iostream>
    #include <iterator>
    #include <algorithm>
    #include <string>
    #include <fstream>
    #include <cctype>
    using namespace std;
    
    
    // function definitions
    bool loaddata(string fn,map<string,string>& dict);
    
    
    const string fname = "defs.dat";
    
    
    int main()
    {
        map<string,string> dictionary;	// Store our word/definition pairs
    
        // load data from file
        if( !loaddata(fname,dictionary) )
        {
            cout << "File open failed.\n";
            cin.get();
            exit(1);
        }
    
        //exit if nothing loaded into dictionary
        if( dictionary.empty() )
        {
            cout << "No entries loaded into dictionary.\n";
            cin.get();
            exit(1);
        }
        else cout << dictionary.size() << " entries have been loaded into dictionary.\n";
    
        // allow user to search for words
        while(1)
        {
            string word, original;
    
            // prompt user for search word
            cout<<"\nEnter the word to search for, or leave blank to quit:  ";
            getline(cin,original);
            cin.ignore(80,'\n');
    		        
            // exit for blank search word
            if( !original.length() ) break;
    
            // change all characters to upper case
            transform(original.begin(),original.end(), inserter(word,word.end()), toupper);
    
            // search for the word
            if( dictionary.find(word) == dictionary.end() )
                cout << "\nCould not find " << word << ".\n";
            else
            {
                cout << "\nWord found.\n";
                cout << "Original word as typed (LaRue): " << original << "\n";
                cout << "Word: " << word << "\n";
                cout << "Definition: " << dictionary[word] << "\n";
            }
    
        }
    
        return 0;
    }
    
    // function to load data from file
    bool loaddata(string fn,map<string,string>& dict)
    {
        ifstream file;
        string word, def;
    	
        // open the file
        file.open(fn.c_str());
    
        // make sure file opened okay
        if( !file.is_open() ) return false;
    
        // read until end of file
        while( !file.eof() )
        {
            file >> word;
            getline(file,def);
    
            // change all characters in 'word' to upper case
            transform(word.begin(),word.end(),word.begin(), toupper);
    
            // copy word/definition into the dictionary
            dict[word] = def;
        }
    
        // return success
        return true;
    }
    "Owners of dogs will have noticed that, if you provide them with food and water and shelter and affection, they will think you are god. Whereas owners of cats are compelled to realize that, if you provide them with food and water and shelter and affection, they draw the conclusion that they are gods."
    -Christopher Hitchens

  7. #7
    Registered User
    Join Date
    Jun 2004
    Posts
    722
    Quote Originally Posted by jlou
    Actually,
    Code:
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <ctype.h>
    I believe these are standard in C++, but they are deprecated in favor of the C++ versions.
    Code:
    #include <iostream.h>
    #include <fstream.h>
    and these are non-standard in C and C++, and are therefore just old.

    So hk_mp5kpdw was correct, those headers are all old and/or deprecated.
    Deprecated symbols or names.. because it's the implementation that counts...

  8. #8
    Toaster Zach L.'s Avatar
    Join Date
    Aug 2001
    Posts
    2,686
    It is advisable to use the standard. Many compilers provide those old headers for convenience. <iostream.h> for example, may very well look like this:
    Code:
    #ifndef __WHATEVER__
    #include <iostream>
    using std::cout;
    using std::cin;
    ... // etc
    ##endif
    Not all compilers will necessarily provide them, and not all compilers will continue to have them indefinitely. There is no reason not to use the standard.
    The word rap as it applies to music is the result of a peculiar phonological rule which has stripped the word of its initial voiceless velar stop.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. A development process
    By Noir in forum C Programming
    Replies: 37
    Last Post: 07-10-2011, 10:39 PM
  2. help with text input
    By Alphawaves in forum C Programming
    Replies: 8
    Last Post: 04-08-2007, 04:54 PM
  3. Game Pointer Trouble?
    By Drahcir in forum C Programming
    Replies: 8
    Last Post: 02-04-2006, 02:53 AM
  4. Replies: 3
    Last Post: 03-04-2005, 02:46 PM
  5. System
    By drdroid in forum C++ Programming
    Replies: 3
    Last Post: 06-28-2002, 10:12 PM