im intending to write a code that reads words and the lines that it appears at from a file and sort the words alphabetically in a linked list then prints them.
so far i've made out this... but it doesn't print them in alphabetic order and it prints duplicates as well (which it shouldn't be doing so)
any help ?

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

#define SIZE 1023
#define LENSTR_(x) #x
#define LENSTR(x) LENSTR_(x)
#define LEN  7

/* Struct for word and lines that appears in */
struct wordStruct {
char *word;
char *lines;
struct wordStruct *next;
};

static int compare_words(const struct wordStruct *a, const struct wordStruct *b) {
    return strcmp(a->word, b->word);
}

static struct wordStruct *insert_sorted(struct wordStruct *headptr, char *word, char *lines) {
    /* Struct head */
    struct wordStruct *pp = headptr;
    struct wordStruct *prior = headptr;
    struct wordStruct *ptr = malloc(sizeof(struct wordStruct));
    /*check for duplicate */
    while ( pp != NULL) {
        if ( strcmp ( word, pp->word) == 0) {
            size_t length = strlen ( pp->lines);
            char *temp = realloc ( pp->lines, length + strlen ( lines) + 3);
            if ( temp == NULL) {
                fprintf ( stderr, "problem reallocating\n");
            }
            else {
                pp->lines = temp;
                strcat ( pp->lines, ",");
                strcat ( pp->lines, lines);
            }
            return headptr;
        }
        pp = pp->next;
    }
    /* Allocate heap space for a record */

    if (ptr == NULL) {
        abort();
    }

    /* Assign to structure fields */
    ptr->word = malloc ( strlen ( word) + 1);
    strcpy ( ptr->word, word);
    ptr->lines = malloc ( strlen ( lines) + 1);
    strcpy ( ptr->lines, lines);
    ptr->next = NULL;

    pp = headptr;
    prior = headptr;

    /* Store words in alphabetic order */
    if ( headptr == NULL) {
        headptr = ptr;
    }
    else {
        while (pp != NULL && compare_words(ptr, pp) > 0) {
            prior = pp;
            pp = pp->next;
        }
        if ( pp == headptr) {
            ptr->next = headptr;
            headptr =  ptr;
        }
        else {
            prior->next = ptr;
            ptr->next = pp;
        }
    }

    return headptr;
}

static struct wordStruct *read_words (FILE *f, struct wordStruct *headptr) {
    char x[SIZE + 1];
    char ws[SIZE + 1];
    char line[SIZE + 1];
    char *pws = ws;
    int lines = 1;
    /* assumes no word exceeds length of 1023 */
    while (fscanf(f, "%"LENSTR(SIZE)"s", x) == 1) {
        /*printf ( "%s at line %d\n", x, lines);print the word and line */
        sprintf ( line, "%d", lines);
        headptr = insert_sorted(headptr, x, line);

        if ( fscanf ( f, "%"LENSTR(SIZE)"[ \n\t\r]", ws) == 1) {/*scan space, newline, tab and carriage return*/
            pws = ws;
            while ( *pws) {
                if ( *pws == '\n') {
                    lines++;/*count newlines*/
                }
                pws++;
            }
        }
    }
    return headptr;
}

int main(int argc, char **argv) {
    /* Snitialize empty list */
    struct wordStruct *headptr = NULL;
    /* Snitialize current */
    struct wordStruct *current;
    struct wordStruct *temp;
    FILE *fileptr = NULL;

    if ( NULL == ( fileptr = fopen ( "test.txt", "r"))) {
        fprintf ( stderr, "could not open file\n");
        return 0;
    }

    /* Insert words in list */
    headptr = read_words( fileptr, headptr);

    fclose ( fileptr);

    current = headptr;
    while (current != NULL) {
        printf("%s appears in lines %s.\n", current->word, current->lines);
        current = current->next;
    }
    /*release memory*/
    current = headptr;
    while (current != NULL) {
        temp = current;
        current = current->next;
        free ( temp->word);
        free ( temp->lines);
        free ( temp);
    }
    return 0;
}

Dani AI

Generated

You are close. The two big reasons you see odd order and duplicates are: (1) you compare with strcmp, which is case-sensitive, so all upper-case words sort before lower-case ones; and (2) your tokens still include punctuation, so word and word, are different keys. Your tolower loop looks like it does nothing because either it runs after you insert, or the punctuation keeps the strings different even when lowercased.

Normalize each token before you call insert_sorted: strip leading/trailing punctuation and lowercase in-place. Do that immediately after reading into x and before building the node.

static void normalize_word(char *s) {
    unsigned char *p = (unsigned char *)s, *q = (unsigned char *)s;
    /* skip leading non-alnum */
    while (*p && !isalnum(*p)) p++;
    /* keep alnum and selected in-word chars; lowercase */
    for (; *p; ++p) {
        if (isalnum(*p) || *p=='\'' || *p=='-') *q++ = (char)tolower(*p);
        else if (isspace(*p)) break; /* stop at whitespace */
    }
    /* trim trailing non-alnum */
    while (q > (unsigned char *)s && !isalnum(q[-1])) --q;
    *q = '\0';
}

/* usage right after reading x */
fscanf(f, "%1023s", x);
normalize_word(x);
if (*x) headptr = insert_sorted(headptr, x, line);

A few quick fixes to tighten things up:

  • Allocate the new node only after the duplicate scan in insert_sorted; right now you leak it when a duplicate is found.
  • If you keep case differences, switch your comparator to a case-insensitive one (strcasecmp on POSIX, _stricmp on Windows). With normalization, strcmp is fine.
  • When appending a line number to pp->lines, first check that it is not already listed to avoid 3,3,3 for repeated hits on the same line.
  • When lowercasing manually, use x[u] = (char)tolower((unsigned char)x[u]); to avoid undefined behavior on non-ASCII chars.

also when i try to put :

   int u=0;
   while( x[u] ) 
   {
      x[u] = (tolower(x[u]));
      u++;
   }

in line 90 so it'll insert the words in lower letters to the list, but it does nothing why?

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.