0

I am writing a program that is intended to count the number of times each word occurs in a text file. I am getting a runtime error that says: Segmentation fault (core dumped). I understand this has to do with trying to access memory that has not been allocated.

Also, I am receiving warnings about my arguements for getline, and I am unsure if I am using it correctly. Any advice is appreciated.

My code is:

#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>

#define MAXWORDS 5000
#define MAXLINE 1000
#define MAXWORDLEN 100


int count = 0;
struct wordcount *wordPtr[MAXWORDS];

typedef struct wordcount *wordcountptr;

typedef struct wordcount {
    char word[50];
    int count;
} wordcount_t;


main()
{

    int wordfound = 0;
    int len;
    char line[MAXLINE];
    int printcount;

    while ((len = getline(line, MAXLINE, stdin))> 0)
    {
        int i = 0;
        int j = 0;

        for( ; i<len; i++)
        {
            if(line[i] != isalnum(line[i]) && line[i] != 32)
                line[i] = 32;
            else
                line[i] = tolower(line[i]);
        }

        for( ; j<len; j++)
        {

            char currentword[MAXWORDLEN];

            if(line[j] != 32)
            {
                for(i=0; line[j] != 32; i++)
                    currentword[i] = line[j];
            }
            if(line[j] == 32)
            {
                for(i=0;i<MAXWORDS; i++)
                {
                    if(strcmp(currentword, (*wordPtr[i]).word) == 0)
                    {
                        (*wordPtr[i]).count++;
                        wordfound = 1;
                    }
                }

                if(wordfound == 0)
                {
                    wordPtr[i] = (wordcount_t*)malloc(sizeof(wordcount_t));
                    strcpy((*wordPtr[i]).word, currentword);
                    (*wordPtr[i]).count = 1;
                    count++;
                }
            }
            wordfound = 0;
        }
    }

    for(printcount = 0; printcount < count; printcount++)
        printf("There are %d occurances of the word %s\n", (*wordPtr[printcount]).count, (*wordPtr[printcount]).word);

    for(printcount = 0; printcount < MAXWORDS; printcount++)
    {
        free((void*)wordPtr[printcount]);
        wordPtr[printcount]= NULL;
    }
}
Atache
  • 169
  • 1
  • 13
  • 2
    you should properly declare main() and have a return value, best to always do that instead of forgetting it when it counts. – AndersK Dec 04 '13 at 06:47
  • and use `int main(void)` rather than simply `main()`... and no need to cast to `void*` in **free** , or to `(wordcount_t*)` in **malloc** ... and `->` is an useful "shortcut" ... – ShinTakezou Dec 04 '13 at 07:30

2 Answers2

2

getline() expects the first agrument to be of the type char ** so you should call it as such:

getline(&line, MAXLINE, stdin)

because line is a char array, it is equivalent to char * not the required char **.

To quote from this SO answer the reason for using char ** and not char * is:

You need to pass in a char** (ie a pointer to a pointer to a char) so that the function is able to update the value of the char* that it points to.

Community
  • 1
  • 1
imp25
  • 2,327
  • 16
  • 23
1

ssize_t getline(char **lineptr, size_t *n, FILE *stream);this is getline prototype,The first argument is char **,not char *, you can use like this:getline(&line, MAXLINE, stdin)

sundq
  • 735
  • 2
  • 9
  • 28
  • Ok, thank you. I am confused about what char ** is vs char *. I assumed the first argument was the address of where I would want to put the line I am reading, and because referring to an array without an & or index is just the address of the first element, that "line" would suffice. – Atache Dec 04 '13 at 06:39