Segmentation Fault when trying to count words in a file.

Pages: 12
Sep 11, 2010 at 7:00am
Hello all, I'm still pretty new to programming and have been working on my first programming assignment for Computer Science II. The program is supposed to open up a file, count the number of characters and lines in the file, then count the words and put the words into an array, then sort the words in order and eliminate duplicates. We're also supposed to use functions for each of these goals. Counting the characters and lines I managed to figure out fine, and I thought I finally found out how to count the words and put them into an array but when I tried to run the program I got a segmentation fault. Here is my code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
#include <fstream>
#include <iostream>
#include <iomanip>

using namespace std;

/*********************************************************************/
/*  Author:     removed                                              */
/*  Course:     CSC136 010                                           */
/*  Assignment: #1                                                   */
/*  Due Date:   September 13, 2010                                   */
/*  Filename:   p1.cpp                                               */
/*  Purpose:    This program will determine the number of characters */
/*                and lines in a file and print the number of times  */
/*                each word occurs and sort them accordingly.        */
/*********************************************************************/

//This function calculates the number
//of characters and lines in the file.
int charCount(ifstream& inf, int& a, int& b)
{
  //Declare variables.
  char c;
  string d;
  a, b = 0;
  
  //Finds the number of characters.
  inf.get(c);
  inf.seekg(0, ios::end);
  a = inf.tellg();
  inf.seekg(0, ios::beg);
  
  //Finds the number of lines.
  while (getline(inf, d, '\n'))
    b++;
}

string wordCount(ifstream& inf, int& count)
{
  int i;
  string word[1000];

  while ((inf >> word[i]) && (i < 1000))
    {
    i++;
    count++;
    }
  return word[1000];  
}

int main()
{
  //Delcare variables.
  string fileName;
  ifstream inf;
  int charNum, newLine;
  string WordRec;
  string wordList[1000];
  int words;
  
  
  //Prompt user for filename and attempt to
  //open that file.
  cout << "Enter filename.\n >";
  cin >> fileName;
  inf.open(fileName.c_str());
  
  //If the file doesn't open, display an
  //error message and close the program.
  if (!inf.is_open())
  {
    cout << "File " << fileName << " does not exist in the client's current directory" << endl;
    exit(1);
  }
  
  //Finds the number of characters and lines.
  charCount(inf, charNum, newLine); 
  
  inf.close();
  inf.clear();
  inf.open(fileName.c_str());
  
  wordList[1000] = wordCount(inf, words);
  
  cout << words;
  
  return 0;
}


The segmentation fault is either in the function call itself or within wordCount (er..I hope so at least, the rest of the program didn't have any problems before). I have looked up Segmentation Faults and apparently it's a pretty vague error. Can anyone help me out? Also, did I even do it right? I have it set to output "words" as a means to test whether or not it successfully counted the words. Also, I think that each word will be stored properly into the array that way, but I'm not sure.

Thanks a lot in advance, and I hope I was specific enough. :)
Last edited on Sep 11, 2010 at 7:45pm
Sep 11, 2010 at 8:31am
closed account (EzwRko23)
1
2
3
string wordList[1000];
...
wordList[1000] = wordCount(inf, words);


This is an off-by-one error.
The last valid index of the wordList array is 999.
Elements in the array are counted from 0: 0, 1, 2, ..., 999.

The same problem exists in the wordCount function.
Additionally, here you have an uninitialized variable i:

1
2
3
4
5
6
7
8
9
10
11
12
string wordCount(ifstream& inf, int& count)
{
  int i;   //                   <<<< here
  string word[1000];

  while ((inf >> word[i]) && (i < 1000))
    {
    i++;
    count++;
    }
  return word[1000];  
}
Last edited on Sep 11, 2010 at 8:33am
Sep 11, 2010 at 11:40am
Why do you use an array to read in your words? You don't seem use any of them. It looks like you could just use a single string here.

1
2
3
4
5
6
7
8
9
10
11
12
string wordCount(ifstream& inf, int& count)
{
  int i;
  string word[1000]; // Why is this an array?

  while ((inf >> word[i]) && (i < 1000))
    {
    i++;
    count++;
    }
  return word[1000];  
}
Sep 11, 2010 at 7:32pm
xorebxebx - I fixed the unitialized variable, and I changed the coding around a bit. The function now reads as follows:

1
2
3
4
5
6
7
8
9
10
11
12
string wordCount(ifstream& inf, int& i)
{
  string word;
  string wordList[999];

  while ((inf >> word) && (i < 1000))
    {
    wordList[i] = word;
    i++;
    }
  return wordList[999];  
}


Is this what you meant by off-by-one? I changed the array to 999 throughout the program and still get the segmentation fault. I also removed the variable "count" as it is really just i and is therefore not needed. In the main function I initialize words (the variable that i references) as 0.

Galik - I didn't put them into the array like I was supposed to, so I hope I fixed that there. We're supposed to put them into an array (a max of 1000 words) and then sort the words in that array. He gave us the basic function to do this already, so this is really the only thing I have to figure out. I didn't code that portion yet because I want to make sure I can figure this out first. The professor told us it's better to test as you go so that you know you're on the right track.

I appreciate the help so far, guys.
Sep 11, 2010 at 7:35pm
At line 4: Keep the number elements in the array at 1000. Then it'll be better. ;)

-Albatross
Sep 11, 2010 at 7:42pm
Albatross - words cannot properly describe how much I love you.

Thanks a bunch , guys! If I have any issues with sorting the words I'll be back. ;P But I hope I'll be able to figure it out.
Sep 11, 2010 at 8:21pm
The way you use that array is not going to work for you. You are only passing one string back from the function, not the entire array. If you want to fill the array then it is best to pass the array in as a parameter to the function:
1
2
3
4
5
6
7
8
9
10
void wordCount(ifstream& inf, int& i, string wordList[1000])
{
  string word;
 
  while ((inf >> word) && (i < 1000))
    {
    wordList[i] = word;
    i++;
    }
}

And you should declare wordList as 1000 but access it from 0-999.
Sep 11, 2010 at 8:43pm
Garik -- Ah, I didn't know it wouldn't work that way... hm. So I tried that, and now the compiler is giving an error stating:

error: cannot convert `std::string' to `std::string*' for argument `3' to `void wordCount(std::ifstream&, int&, std::string*)'

Any idea on how to fix that? I don't understand why it won't convert the string to a string.. is it because it's an array?
Sep 11, 2010 at 8:45pm
It sounds like you're trying to input a single string into a function that takes an array of strings. No, you'll need to input an array.

-Albatross
Last edited on Sep 11, 2010 at 8:45pm
Sep 11, 2010 at 8:45pm
I just realized--we're supposed to be constructing an array of struct, not a string array. I can't believe I forgot that. x.x
Sep 11, 2010 at 8:48pm
I trust you know how structs work, but just as a reminder... what kind of struct is it? You'll need to use that as the type.

Sorry if you felt like I thought you were an idiot (I don't think you are), but it's just a heads up.

-Albatross
Sep 11, 2010 at 9:00pm
I didn't get that implication at all, don't worry.

I only vaguely know how structs work... now that I recall, the whole point of this program is to help us understand how data structures work. I'm not sure how to create an array of struct. Ahh..just when I thought I was nearing completion of this program it seems I've been knocked back a few notches... that's what I get for not reading the instructions more carefully I suppose.
Sep 11, 2010 at 9:06pm
Am I on the right track with this?

1
2
3
4
5
struct wordList;
  {
  string wordRec;
  int count;
  }


wordRec is going to be where the words themselves go, and the count will count the number of words.
Sep 11, 2010 at 9:18pm
You're missing a semicolon at the end of all of that.

And, to create an array of structs of type wordList...

wordList naem[int];

-Albatross
Last edited on Sep 11, 2010 at 9:24pm
Sep 11, 2010 at 9:35pm
M'kay, so I got this:

1
2
3
4
5
6
7
struct wordList
  {
    string wordRec;
    int count;
  }; 
  
  wordList list[1000];


If I understand this correctly, that creates 1000 of that particular struct, correct? Now then, the function call:

wordCount(inf, list[1000]);

Is that how that works? Or should I type in "wordList" to be passed? I'm sorry, now I feel like I'm asking for too much... but I'm starting to get how this works I think.

Sep 11, 2010 at 9:43pm
Nah, you're not asking for too much.

Axe the [1000] in the function call. If you keep it, you will pass only one wordList, not an array, and you'd get a compile-time error.

-Albatross
Sep 11, 2010 at 10:02pm
Hmm..okay. If I recall correctly, referring to each part of the struct kinda goes something like "list.wordRec" or something? So I put list in the function call (without the [1000] as you said). So, wordCount(inf,list);

What should the prototype be?

void wordCount(ifstream& inf, struct& list) doesn't work, and if I type struct without the & it tells me that I'm declaring it wrong.

Once I get that far I'm not entirely sure how to place the words in the array or even count them..I've never worked with structs before, especially not in functions.
Sep 11, 2010 at 10:23pm
*smiles* I did warn ya.

Replace struct with the name of the (struct array you'll be putting into it)'s type.

-Albatross
Sep 11, 2010 at 10:36pm
I think I finally have it figured out. Structs can be global/static, just like any regular variable, yes? After doing that (and messing with my code a bit) it works. Now I'm on the hard part: sorting the array. I managed to remember how structs work a bit more.

I'm going to work on this on my own for a bit to see if I can figure it out. It only returned a single error and I'm trying to work that out. I'll report back within 20 minutes or so if I can't get it to work right.

Thanks a bunch, guys. You've all been a tremendous help. :)
Sep 11, 2010 at 11:14pm
Okay, I'm back. (you probably saw this coming ya?)

So, the sort function I have written out doesn't appear to be doing it's job. Here is the function:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
void selSort(wordList list[], int& elts)
{
  int spot = 0;
  int idxMin = 0;
  int idxMax = elts - 1;

  for(int spot = 0; spot < elts - 1; spot++)
    int idxMin = spot;
    for(int idx = idxMin+1; idx < elts; idx++)
      if(list[idx].wordRec < list[idxMin].wordRec)
        idxMin = idx;
      if(idxMin != spot)
        swap(list[idxMin].wordRec,list[spot].wordRec);
      else
        {
        swap(list[idxMin].wordRec,list[idxMax].wordRec);
        elts--;
        }
}


The words in my test file all stayed in the same position...the first word was placed in the last slot and removed, for reasons I do not understand. Any idea as to why this isn't working at all? I'm so close to being done with the project, I just want to be done with it. This is the final part, all I gotta do after this is output it all, which is easy.

Thanks again for the help thusfar, guys.

EDIT:

To clarify: The function is supposed to look at the current word, compare it to the previous word, and then swap them accordingly. Is this possible with string? Should I try to convert the strings to ints? At the end, it checks if the current word is the same as the previous one, and then places the current one up front and removes it if it is. At least that's what it's supposed to do..hmm.

EDIT2:

Oh, almost forgot, here's the function for swap:

1
2
3
4
5
6
7
void swap(int x, int y)
{
  int temp;
  temp = x;
  x = y;
  y = temp;
}

Last edited on Sep 11, 2010 at 11:24pm
Pages: 12