Will it not store in in_name?
Will it not store in in_name?
Yes it will. I don't even know how I missed that there, but I did, so apologies. Yes that should be fine.
Ok, thank you so much. So the big main problem is still occurring. I've figured out my function "filesize" is returning -1.
Unfortunately, this is the piece of code I was given. I am nowhere near understanding what's going on except that "stat(filename, &status)" apparently is equal to -1. I don't even know what stat does. I'm stuck.Code:int filesize(char * filename){ struct stat status; if (stat(filename, &status) == -1) { return -1; } else { return (int) status.st_size; } }
That's why they gave us a manual. As it says, -1 is returned on error, and errno is set appropriately. You can use perror to show the system error message:
although I'd be willing to be a dollar to a doughnut that you've passed in a filename that doesn't exist.Code:int filesize(char * filename){ struct stat status; if (stat(filename, &status) == -1) { perror("stat"); return -1; } else { return (int) status.st_size; } }
Read the man page. From your terminal, you can type "man 3 stat", or search for that on the web. That 3 ensures you use section 3 of the man pages, which are for C library functions. You may occassionally want to check section 2 as well, which is system calls.
So, the code you were given calls the stat function. If stat returns -1 (error), then your function returns -1. Otherwise, your function returns the size as reported by stat.
Well, the filesize function was being passed "argv[1]" because that's what the professor told me to do but I changed it to in_name (the name of the file) and it began to work. I really hope changing that won't cause me trouble later on.
Someone (anduril) mentioned that earlier: are the specs to pass the filename in on the command line (in which case argv[1] is the way to go) or to type it in in response to a prompt, in which case your scanf is the way to go? You'll have to check the specs and follow them.
The filename is prompted for in the command line.
I've gotten much further, actually starting the sorting process before running into another problem. Here's what I have at the moment.
The problem is "if (strcmp(*e1,*e2)<0)" and, it seems I'm going about accessing the arrays to sort the wrong way.Code:#include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <stdlib.h> #include <string.h> int filesize(char * filename) { struct stat status; if (stat(filename, &status) == -1) { return -1; } else { return (int) status.st_size; } } int compare(const void *elem1, const void *elem2) { char **e1 = (char **) elem1; char **e2 = (char **) elem2; if (strcmp(*e1,*e2)<0) return -1; else if (strcmp(*e1,*e2)>0) return 1; else return 0; } void sort(char array[], int size) { qsort(array, size, sizeof(array[0]), &compare); } int main(int argc, char * argv[]) { FILE *read; char in_name[255]; int n = 0; int j = 0; int linecount = 1; printf("What file should be read?\n"); if (scanf("%s", in_name) != 1) { printf("Invalid input.\n"); return 1; } read = fopen(in_name,"r"); if (read == NULL) { printf("Cannot open input file.\n"); return 1; } char * data = malloc(filesize(in_name)); data[n] = fgetc(read); while (data[n] != EOF) { if (data[n] == '\n') { data[n] = '\0'; linecount++; } data[++n] = fgetc(read); } if (data[n] != '\0') data[++n] = '\0'; char ** lines = malloc(sizeof(lines[0]) * linecount); int i = 0; while (j < linecount) { lines[j] = &data[i]; while(data[i] != '\0') i++; i++; j++; } sort(*lines,linecount); for (int k = 0; k < linecount; k++) { printf("%s\n", lines[k]); } fclose(read); free(data); free(lines); return 0; }
Why not use a growing array to store the input? Your program would be more portable since you won't need to use stat.
In regard to your compare function, try reading the example provided in 'man qsort'.
i dont believe in competition in da field of cboard posts, u see, i believe in a collection of posts each 2 be admired for der own personal statement. when in doubt, ask Willy!
Barney- Honestly, I don't know how to use a growing array. I imagine figuring out how to do so, messing up, figuring out what went wrong, and fixing it would tack on more time. I've got a lot of work besides this to do before tomorrow. So... I suppose it's trying to take the easy way out, even if the program won't be as solid. Yes, I'm ashamed of this, but... well... not enough to give up on sleeping at all.
man sort gives me the parameters but not an example. I wasn't bright enough to pick up on discrepancies there.
Try another source: qsort(3) - Linux manual pageman sort gives me the parameters but not an example.
i dont believe in competition in da field of cboard posts, u see, i believe in a collection of posts each 2 be admired for der own personal statement. when in doubt, ask Willy!
Thank you for the link! Going through it... I think I'm doing something wrong regarding whether I'm using pointers to things or the things themselves? Am I on the right track?
I changed
Code:int compare(const void *elem1, const void *elem2) { char **e1 = (char **) elem1; char **e2 = (char **) elem2; if (strcmp(*e1,*e2)<0) return -1; else if (strcmp(e1,e2)>0) return 1; else return 0; }
to
Code:int compare(const void *elem1, const void *elem2) { char *e1 = (char *) elem1; char *e2 = (char *) elem2; if (strcmp(e1,e2)<0) return -1; else if (strcmp(e1,e2)>0) return 1; else return 0; }
Now I'm getting output. However, that output is wrong.
My input file says
"goat4
nine
1
2
pink"
and I'd like to get
"1
2
4
goat
nine
pink"
Right now, I'm getting
"t
nine
1
2
pink\377"
So I'm losing "goa" in goat and "4" and gaining "\377". These seem like separate problems. Am I pointing to the wrong thing?
Last edited by RElainaJ; 11-20-2013 at 12:00 AM. Reason: Format
qsort requires each element to be of the same length so, obviously, you can't move strings around in an array using it, since they may have different sizes. What you need to do is store a pointer to each string in an array, then sort those pointers, which is what the example in 'man 3 qsort' demonstrates.
EDIT: As in, the following array would be bad input for qsort:
char s[] = "the\0cow\0jumped\0over\0the\0moon\0";
Whereas the following would be good input:
char *p[] = { s + 0, s + 4, s + 8, s + 15, s + 20, s + 24 };
This is because the element type of the first array is a 'char' (though you'd need to scale it with a varying size, which doesn't work well with qsort), whereas the element type of the second array is 'char *', and you would be scaling it by exactly 'sizeof (char *)'.
Last edited by Barney McGrew; 11-20-2013 at 12:06 AM.
i dont believe in competition in da field of cboard posts, u see, i believe in a collection of posts each 2 be admired for der own personal statement. when in doubt, ask Willy!