Search code examples
cpointersqsort

how to put char * into array so that I can use it in qsort, and then move on to the next line


I have lineget function that returns char *(it detects '\n') and NULL on EOF. In main() I'm trying to recognize particular words from that line. I used strtok:

int main(int argc, char **argv)
{
    char *line, *ptr;
    FILE *infile;
    FILE *outfile;
    char **helper = NULL;
    int strtoks = 0;
    void *temp;

    infile=fopen(argv[1],"r");
    outfile=fopen(argv[2],"w");

    while(((line=readline(infile))!=NULL))
    {
        ptr = strtok(line, " ");

        temp = realloc(helper, (strtoks)*sizeof(char *));
        if(temp == NULL) {
            printf("Bad alloc error\n");
            free(helper);
            return 0;
        } else {
            helper=temp;
        }
        while (ptr != NULL) {
            strtoks++;
            fputs(ptr, outfile);
            fputc(' ', outfile);
            ptr = strtok(NULL, " ");
            helper[strtoks-1] = ptr;
        }
        /*fputs(line, outfile);*/
        free(line);
    }
    fclose(infile);
    fclose(outfile);
    return 0;
}

Now I have no idea how to put every of tokenized words into an array (I created char ** helper for that purpose), so that it can be used in qsort like qsort(helper, strtoks, sizeof(char*), compare_string);.

Ad. 2 Even if it would work - I don't know how to clear that line, and proceed to sorting next one. How to do that?

I even crashed valgrind (with the code presented above) -> "valgrind: the 'impossible' happened: Killed by fatal signal"

Where is the mistake ?


Solution

  • The most obvious problem (there may be others) is that you're reallocating helper to the value of strtoks at the beginning of the line, but then incrementing strtoks and adding to the array at higher values of strtoks. For instance, on the first line, strtoks is 0, so temp = realloc(helper, (strtoks)*sizeof(char *)); leaves helper as NULL, but then you try to add every word on that line to the helper array.

    I'd suggest an entirely different approach which is conceptually simpler:

    char buf[1000]; // or big enough to be bigger than any word you'll encounter
    char ** helper;
    int i, numwords;
    
    while(!feof(infile)) { // most general way of testing if EOF is reached, since EOF 
                           // is just a macro and may not be machine-independent.
        for(i = 0; (ch = fgetc(infile)) != ' ' && ch != '\n'; i++) { 
            // get chars one at a time until we hit a space or a newline
            buf[i] = ch; // add char to buffer
        }
        buf[i + 1] = '\0' // terminate with null byte
        helper = realloc(++numwords * sizeof(char *)); // expand helper to fit one more word
        helper[numwords - 1] = strdup(buffer) // copy current contents of buffer to the just-created element of helper
    }
    

    I haven't tested this so let me know if it's not correct or there's anything you don't understand. I've left out the opening and closing of files and the freeing at the end (remember you have to free every element of helper before you free helper itself).