Thread: Simple search engine using maps

  1. #1
    Registered User
    Join Date
    Feb 2008
    Posts
    43

    Simple search engine using maps

    Hi, for my last assignment I must make a program that takes in up to six files through the command line then print out the files in order of highest relavance depending on how many times the 2 keywords appear in each file. This is what I have so far but i'm getting a segmentation fault and I think it has something to do with the array of maps at line 24 but im not sure.

    Code:
    #include <fstream>
    #include <iostream>
    #include <string>
    #include <map>
    
    using namespace std;
    
    int main(int argc, char* argv[])
    {
       map<string, int> info[argc-1];
       string fileNames[argc-1];
       string word;
       string keyword = "key";
       
       for(int i=1; i < argc; i++)
       {
          fileNames[i] = argv[i];
          info[i] =  map<string, int>;
          ifstream fin(argv[i]);
          if(!fin) exit(1);
      
         
          while(!fin.eof())
          {
             fin>>word;
    
             if(info[i].count(word) <0 ) 
                info[i][word];
             else
                info[i][word]++;
          }     
       }
    
    
    for(int i =0; i< info[i].size(); i++)
       for(map<string, int>::iterator x = info[i].begin(); x != info[i].end(); x++)
          cout<< x->first << ": "<< x->second << "\n";
    
    
    
    }

  2. #2
    Crazy Fool Perspective's Avatar
    Join Date
    Jan 2003
    Location
    Canada
    Posts
    2,640
    array indexing starts at zero and goes to array-size - 1.

  3. #3
    Registered User
    Join Date
    Feb 2008
    Posts
    43
    even when I put i-1 there I get an error: expected primary-expression before ";" token line 18

  4. #4
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    segmentation fault
    an error
    Okay, so which is it? Is the code you posted the code you really have?

    Soma

  5. #5
    Registered User
    Join Date
    Feb 2008
    Posts
    43
    It was a segmenation fault so I tried putting the code in red in but now I get error: expected primary-expression before ";" token line 18

  6. #6
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    map<string, int> info[argc-1];
    don't you need constant to declare array?
    make it vector

    while(!fin.eof()) - read FAQ why not to use eof with loops
    should be
    Code:
    while( fin>>word )
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  7. #7
    Registered User
    Join Date
    Feb 2008
    Posts
    43
    isnt argc a constant?

  8. #8
    Registered User
    Join Date
    May 2008
    Posts
    21
    Well it's a variable.

    You're getting a segfault because you're going out of bounds of your array.

    make it vector
    Agreed.

    To visualise your problem, let's assume I passed in 2 file names, file.a and file.b ....
    Code:
    for(int i = 1; i < argc; ++i)
        std::cout << "assigning fileNames[" << i << "] = " << argv[i] << "\n";
        fileNames[i] = argv[i];
    }
    Output:
    Code:
    assigning fileNames[1] = file.a
    assigning fileNames[2] = file.b <--- segfault, index out of bounds
    Your array length is 2, in C++ array indexing begins at 0. So if you wish to access an index in your existing loop - you'll need to be i-1.
    Last edited by scarecrow; 05-06-2008 at 09:39 PM.

  9. #9
    Registered User
    Join Date
    Feb 2008
    Posts
    43
    This is what I have using i-1 but I still get this error:
    expected primary-expression before ";" token line 18

    Code:
    #include <fstream>
    #include <iostream>
    #include <string>
    #include <map>
    
    using namespace std;
    
    int main(int argc, char* argv[])
    {
       map<string, int> info[argc-1];
       string fileNames[argc-1];
       string word;
       string keyword = "key";
       
       for(int i=1; i < argc; i++)
       {
          fileNames[i-1] = argv[i];
          info[i-1] =  map<string, int>; //error here
          ifstream fin(argv[i]);
          if(!fin) exit(1);
      
         
          while(!fin.eof())
          {
             fin>>word;
    
             if(info[i-1].count(word) <0 ) 
                info[i-1][word];
             else
                info[i-1][word]++;
          }     
       }
    
    
    for(int i =0; i< info[i].size(); i++)
       for(map<string, int>::iterator x = info[i].begin(); x != info[i].end(); x++)
          cout<< x->first << ": "<< x->second << "\n";
    
    
    
    }

  10. #10
    Registered User
    Join Date
    Feb 2008
    Posts
    43
    Never mind I just deleted the line and it works now but there is something odd that happens. When I put an even amount of text files in the program it produces a segmentation fault but when I put an odd number of files there is no error. for example:

    ./execProg word.txt - no error
    ./execProg word.txt word.txt - segmentation fault at end of output
    ./execProg word.txt word.txt word.txt - no error
    ./execProg word.txt word.txt word.txt word.txt - segmentation fault at end of output

    Code:
    #include <fstream>
    #include <iostream>
    #include <string>
    #include <map>
    
    using namespace std;
    
    int main(int argc, char* argv[])
    {
       map<string, int> info[argc-1];
       string fileNames[argc-1];
       string word;
       string keyword = "key";
       
       for(int i=1; i < argc; i++)
       {
          fileNames[i-1] = argv[i];
          ifstream fin(argv[i]);
          if(!fin) exit(1);
      
         
          while(!fin.eof())
          {
             fin>>word;
    
             if(info[i-1].count(word) <0 ) 
                info[i-1][word];
             else
                info[i-1][word]++;
          }     
       }
    
    
    for(int i =0; i< info[i].size(); i++)
       for(map<string, int>::iterator x = info[i].begin(); x != info[i].end(); x++)
          cout<< x->first << ": "<< x->second << "\n";
    
    
    
    }

  11. #11
    Registered User
    Join Date
    Dec 2006
    Location
    Canada
    Posts
    3,229
    variable length arrays are a compiler extension in C++, though it is so widely used (especially in old code) that I wouldn't imagine any compiler not implementing it (gcc accepts it without a warning even with -Wall).

  12. #12
    Registered User
    Join Date
    Oct 2001
    Posts
    2,129
    >(gcc accepts it without a warning even with -Wall).

    try -ansi -pedantic
    Last edited by robwhit; 05-06-2008 at 10:47 PM.

  13. #13
    Registered User
    Join Date
    Feb 2008
    Posts
    43
    I don't understand what you guys mean...^^^

  14. #14
    The larch
    Join Date
    May 2006
    Posts
    3,573
    Code:
    map<string, int> info[argc-1];
    The value of argc is not known to the compiler (it differs on each runtime), so it cannot create a usual, fixed-sized array. Instead your compiler as an extension allows you to create variable-sized arrays. Other compilers may not have that extension and your code may not be compilable for others.
    It was suggested to use a vector:
    Code:
    vector<map<string, int> > info(argc - 1);
    Code:
    while(!fin.eof())
          {
             fin>>word;
    
             if(info[i-1].count(word) <0 ) 
                info[i-1][word];
             else
                info[i-1][word]++;
          }
    Firstly, read the FAQ about why you shouldn't control the input loop with eof() (this code has potential for "reading" the last word twice). The logic here about the map is a bit over-complicated too. I guess the if part is never executed (count of matches less than 0? especially if count()'s return type is unsigned?), so you might just remove the conditional thing.

    Code:
    for(int i =0; i< info[i].size(); i++)
    This is probably causing your crashes. I can't see the relationship between the size of each dictionary and the total number of input files but that's what you are using to control the loop.
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  15. #15
    Registered User
    Join Date
    Dec 2006
    Location
    Canada
    Posts
    3,229
    how about running the code in a debugger? it will tell you what line does your program segfault.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. creating an AI engine for a simple game
    By cyb3r in forum Game Programming
    Replies: 1
    Last Post: 01-26-2009, 01:19 PM
  2. Search function not working fully
    By tabstop in forum C Programming
    Replies: 7
    Last Post: 12-04-2008, 02:57 AM
  3. Logical errors with seach function
    By Taka in forum C Programming
    Replies: 4
    Last Post: 09-18-2006, 05:20 AM
  4. Big help in Astar search code...
    By alvifarooq in forum C++ Programming
    Replies: 6
    Last Post: 09-24-2004, 11:38 AM
  5. Your favourite search engine?
    By ammar in forum A Brief History of Cprogramming.com
    Replies: 20
    Last Post: 12-03-2002, 12:43 PM