I am trying to print an array of linked lists. I am having trouble getting it to print. Here is my struct.
typedef struct VERTEXTAG
{
char c;
bool isvisited;
struct EDGETAG* p;
}VERTEX;
typedef struct EDGETAG
{
VERTEX* v;
struct EDGETAG* q;
//cookies rock
//I like cookies
}EDGE;
Here are my variable declarations
VERTEX v[100];
EDGE *e;
EDGE* temp;
int counter = 0;
int addcounter = 0;
int i = 0;
Here is where I try to create the linked lists. I have an even case and an odd case.
//even case
if(counter - i == 1 && flag == 0)
{
vertices[addcounter] = (char)c;
//printf("The vertice is %c :\n", vertices[addcounter]);
e = (EDGE*) malloc(sizeof(EDGE));
v[addcounter].p=e;
v[addcounter].c= (char)c;
v[addcounter].isvisited=false;
v[addcounter].p=NULL;
addcounter++;
}
//odd case
if(counter - i == 1 && flag == 0)
{
vertices[addcounter] = (char)c;
//printf("The vertice is %c :\n", vertices[addcounter]);
e = (EDGE*) malloc(sizeof(EDGE));
v[addcounter].p=e;
v[addcounter].c= (char)c;
v[addcounter].isvisited=false;
v[addcounter].p=NULL;
(*e).v= &v[addcounter];
e->q = NULL;
addcounter++;
}
Here is where I try to print my linked list. For some reason temp is equal to NULL so it is not printing. I know I am correctly passing my variables to each case with vertices array. It prints out correctly. I am not sure if I am correctly creating the linked list of arrays since it will not print out. Also the second print statement in the while loop creates a segmentation when I take it out of the while loop so the program can reach it.
temp = v[0].p;
if(temp == NULL)
{
printf("Temp is Null\n");
}
while(temp != NULL)
{
printf("While loop");
printf("%c", (*(*temp).v).c);
temp = temp->q;
}
printf("The vertice is %s :\n", vertices);
Your problem is likely here:
v[addcounter].p=e;
v[addcounter].c= (char)c;
v[addcounter].isvisited=false;
v[addcounter].p=NULL;
Why are you setting v[x].p to e, then setting it to NULL a few lines after? Later on when you try to access v[0].p, of course it's going to still be NULL.
Related
I've been trying to create a dictionary of words and their definitions(sort of Oxford English Dictionary). So far, I've finished half of the job:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct{
char wordInDictionary[32];
int numberOfMeanings;
char *wordDefinitions[10];
}Entry; //struct that describes a single entry in the dictionary
typedef struct{
int entries;
Entry* arrayOfEntries[100];
}Dictionary; //dictionary itself
Dictionary createDictionary(){
Dictionary emptyDictionary;
emptyDictionary.entries = 0;
int i,j;
for(i=0;i<100;i++){
emptyDictionary.arrayOfEntries[i] = malloc(sizeof(Entry));
emptyDictionary.arrayOfEntries[i]->numberOfMeanings = 0;
strcpy(emptyDictionary.arrayOfEntries[i]->wordInDictionary, "");
for(j=0;j<10;j++){
emptyDictionary.arrayOfEntries[i]->wordDefinitions[j] =
malloc(500*sizeof(char));
strcpy(emptyDictionary.arrayOfEntries[i]->wordDefinitions[j], "");
}
}
return emptyDictionary; //created empty dictionary with 0 entries and empty content
}
Entry* searchWord(char word[], Dictionary *dict){
Entry* foundWord;
int i;
for(i=0;i<100;i++){
if(strcmp(dict->arrayOfEntries[i]->wordInDictionary, word) != 0){
foundWord = NULL;
}else{
foundWord = dict->arrayOfEntries[i];
break;
}
}
return foundWord; //searches for a given word and returns NULL, if word is not found, or pointer to entry in the dictionary that corresponds to word, if word is found.
}
int addDefinition(char word[], char meaning[], Dictionary *dict){
Entry* foundEntry = searchWord(word, dict);
int returnNumber;
if((foundEntry == NULL || strcmp(foundEntry->wordInDictionary, word) != 0)
&& dict->entries < sizeof(dict->arrayOfEntries)/sizeof(dict->arrayOfEntries[0])){
Entry* newEntry = malloc(sizeof(Entry)); //allocating space if searched word is not found in dictionary
strcpy(newEntry->wordInDictionary, word); //now there is a new word in the dictionary
newEntry->numberOfMeanings = 0; //but the new word has 0 meanings
dict->arrayOfEntries[dict->entries++] = newEntry;
if(newEntry->numberOfMeanings<10){
newEntry->wordDefinitions[newEntry->numberOfMeanings] = malloc(500*sizeof(char));
strcpy(newEntry->wordDefinitions[newEntry->numberOfMeanings], meaning); //new word now has a new meaning since its meanings' amount is less than 10(which is max)
}
int oldNumberOfMeanings = newEntry->numberOfMeanings;
int newNumberOfMeanings = oldNumberOfMeanings + 1;
if(newNumberOfMeanings>oldNumberOfMeanings){
returnNumber = 2; //returns 2 if both new entry and new definition were added into the dictionary
}
newEntry->numberOfMeanings++;
}else if((foundEntry != NULL || strcmp(foundEntry->wordInDictionary, word) == 0)
&& dict->entries < sizeof(dict->arrayOfEntries)/sizeof(dict->arrayOfEntries[0])){
if(foundEntry->numberOfMeanings<10){
foundEntry->wordDefinitions[foundEntry->numberOfMeanings] = malloc(500*sizeof(char));
strcpy(foundEntry->wordDefinitions[foundEntry->numberOfMeanings], meaning);
}
int oldNumberOfMeanings = foundEntry->numberOfMeanings;
int newNumberOfMeanings = oldNumberOfMeanings + 1;
if(newNumberOfMeanings == oldNumberOfMeanings){
returnNumber = 0; //returns 0 if no new entry and no new meaning are added to already found one
}else if(newNumberOfMeanings > oldNumberOfMeanings){
returnNumber = 1; //returns 1 if no new entry and one new meaning are added to already found one
}
foundEntry->numberOfMeanings++;
}
return returnNumber;
}
So this vague piece of code describes my program. But the problem itself occurs when I test the code in main():
int main(void){
Entry* entryPtr;
Dictionary dict = createDictionary();
entryPtr = searchWord("include", &dict);
if(entryPtr != NULL){
printf("\nWord found: 'include'");
}else{
printf("\nWord 'include' is not found in the dictionary.");
}
int count;
count = addDefinition("include", "(verb) def1", &dict);
count = addDefinition("assist", "(verb) def2", &dict);
count = addDefinition("house", "(noun) def3", &dict);
count = addDefinition("camera", "(noun) def4", &dict);
count = addDefinition("valid", "(adjective) def5", &dict);
printf("\nLast count: %i", count);
int i, j;
for(i=0;i<100;i++){
if(strcmp(dict.arrayOfEntries[i]->wordInDictionary, "")!=0){
printf("\n\t%i. %s", i+1, dict.arrayOfEntries[i]->wordInDictionary);
}
for(j=0;j<10;j++){
if(strcmp(dict.arrayOfEntries[i]->wordDefinitions[j], "")!=0){
printf("\n\t\t%i.%i. %s\n", i+1, j+1, dict.arrayOfEntries[i]->wordDefinitions[j]);
}
}
}
entryPtr = searchWord ("exam", &dict);
if (entryPtr != NULL) {
printf("\nWord found: 'exam'");
} else {
printf("\nWord 'exam' is not found in the dictionary.");
}
entryPtr = searchWord ("include", &dict);
if (entryPtr != NULL) {
printf("\nWord found: 'include'");
} else {
printf("\nWord 'include' is not found in the dictionary.");
}
count = addDefinition ("house", "(adjective) def6", &dict);
count = addDefinition ("house", "(adjective) def7", &dict);
count = addDefinition ("house", "(adjective) def8", &dict);
printf("\n\nThe the value returned by the last addition: is %i.", count);
}
What the output gives is:
Word 'include' is not found in the dictionary.
Last count: 2
1. include
1.1. (verb) def1
Segmentation fault: 11
I changed the condition in nested for loops in main() as follows:
for(i=0;i<5;i++){
if(strcmp(dict.arrayOfEntries[i]->wordInDictionary, "")!=0){
printf("\n\t%i. %s", i+1, dict.arrayOfEntries[i]->wordInDictionary);
}
for(j=0;j<1;j++){
if(strcmp(dict.arrayOfEntries[i]->wordDefinitions[j], "")!=0){
printf("\n\t\t%i.%i. %s\n", i+1, j+1, dict.arrayOfEntries[i]->wordDefinitions[j]);
}
}
}
Then it showed the right content, though it is not what it should be like. Instead, it should work for all the entries in the dictionary, not first 5.
I've tried doing debugging many times and investigate it myself but still could not find the solution. Any hints to solve the possible problem(-s)?
P.S. I run the program on VS Code, macOS, GCC.
The issue is in line
if(strcmp(dict.arrayOfEntries[i]->wordDefinitions[j], "")!=0)
It doesn't check for valid dict.arrayOfEntries[i]->wordDefinitions[j] pointer. Something like this:
if(dict.arrayOfEntries[i]->wordDefinitions[j] && strcmp(dict.arrayOfEntries[i]->wordDefinitions[j], "")!=0)
Beside that, I think you are using malloc badly, you are creating at runtime a whole empty dictionary in createDictionary and then creating new entries in addDefinition and adding them like this:
dict->arrayOfEntries[dict->entries++] = newEntry;
This newEntry replaces the old pointer and it doesn't event delete it, this is a memory leak, and beside that newEntry is not fully initialized, and that's the main reason of the segmentation fault.
EDIT: So, it turns out that 'index' was not being returned to 0. Well then. That fixed one segfault. But still getting a different segfault. Working on it.
node* new_node(void){
node* ptr = malloc(sizeof(node));
for (int i = 0; i<27; i++) {
ptr->next[i] = NULL;
}
return ptr;
}
bool load(const char* dictionary)
{
FILE* dict = fopen(dictionary, "r");
node* ptr = new_node;
char word[LENGTH+1];
int index = 0;
for (int c = fgetc(dict); c!=EOF; c = fgetc(dict)){
if(c!='\n'){
word[index]=c;
index++;
}
else {
for(int x=0; x<=index; x++){
int ch = (word[x] == '\'') ? 26 : tolower(word[x])-'a';
if (ptr->next[ch] == NULL){
ptr->next[ch] = new_node;
}
ptr = ptr->next[ch];
}
ptr->end=true;
}
}
return true;
}
I'm trying to implement a trie data structure for a dictionary but my program seems to segfault somewhere in this function. I can't seem to pin it down even with the help of GDB, so can someone give me a hand?
Node is defined as such:
typedef struct node{
bool end;
struct node* next[27];
} node;
Dictionary file:
a
aaa
aaas
aachen
aalborg
aalesund
aardvark
aardvark's
aardvarks
aardwolf
(...)
You have many issues in your code:
When you allocate memory with malloc, it is uninitialised. initialise it directly after allocating it, so that NULL pointers really are null. (calloc, a cousin of ´malloc´, initialises all memory to zero.)
When you loop over the word, you should nor include index:
for (int x = 0; x < index; x++) ...
When you have found the end of a word, you must reset the index to 0. Otherwise, you will append to the old word and overflow the buffer. (You should probably also enforce the upper bound of ´index´.)
Likewise, when you insert a word into the trie, you must reset your pointer for trie traversal to the trie's root. You need two pointers here: A root node pointer and an auxiliary pointer for traversing the trie.
As is, your trie is local to your function. Return the root node, so that other functions can use the trie, or NULL on failure.
Fix these, and you will have a non-crashing function. (It still leaks memory and may not construct the trie properly.)
node *load(const char *dictionary)
{
FILE *dict = fopen(dictionary, "r");
node *head = calloc(1, sizeof(node));
char word[LENGTH + 1];
int index = 0;
for (int c = fgetc(dict); c != EOF; c = fgetc(dict)) {
if (c != '\n') {
word[index] = c;
index++;
} else {
node *ptr = head;
for (int x = 0; x < index; x++) {
int ch = (word[x] == '\'') ? 26 : tolower(word[x]) - 'a';
if (ptr->next[ch] == NULL) {
ptr->next[ch] = calloc(1, sizeof(node));
}
ptr = ptr->next[ch];
}
ptr->end = true;
index = 0;
}
}
return head;
}
The line:
node* ptr = new_node;
and
ptr->next[ch] = new_node;
are not calling the function, but assigning the address of the function to ptr. Call the function instead.
This problem could have been prevented if compiler warnings: -Wall and -Wextra were enabled.
There is no bounds checking done on the array word. Use the value LENGTH to check if the index is in bounds before using it.
It isn't clear what the if statement inside the for loop is doing. It appears that every time a newline is found the whole array word is added to the tree, but the index isn't reset so the same array is added multiple times. At some point index will point out of bounds causing undefined behavior. You should reset index after you use the array word.
You forgot to reset index to 0 at the beginning of the loop.
You should also use calloc(1, sizeof(node)) instead of malloc(sizeof(node)) to avoid leaving memory uninitialized. I suggest you use valgrind to help you track problems of this kind in your code.
You should filter punctuation\unsupported characters a bit more. Any character outside of [a-z|A-Z|\n|\\] will crash your program because of
int ch = (word[x] == '\'') ? 26 : tolower(word[x])-'a';
if (ptr->next[ch] == NULL){
Given that you open a file, there might be a space somewhere or some unexpected character. You need something like
if(c!='\n'){
int num = (c == '\'') ? 26 : tolower(c)-'a');
if(num >=0 && num < 27)
{
word[index]=c;
index++;
}
}
I have a LinkedList implementation which holds structs which contain words and a few other pieces of information. In the LinkedList I have a function which checks to see if a word is
already contained in one of the structs in the list. Problem is, this returns 0 every single time. Any idea why this is?
This compiles completely fine and every single aspect of this function works besides the if(strcmp(ll->value->word, word)) statement.
EDIT: Sorry, forgot to add in the !
int llContains(LinkedList* ll, char* word){
LinkedList* nn= ll;
if(nn != NULL){
for(int i=0; nn != NULL; i++){
if(!strcmp(ll->value->word, word)){
return i;
}
nn = nn->next;
}
} else {
return -1;
}
}
The code has undefined behaviour as there is a path through the function that does not have an explicit return: if the return within the for is not executed.
Note that strcmp() returns 0 when strings equal so the if within the for will be "true" if the strings do not match. This means if the first entry in the list does not equal then 0 will be returned.
Change to:
int llContains(LinkedList* ll, char* word){
LinkedList* nn= ll;
if(nn != NULL){
for(int i=0; nn != NULL; i++){
if(strcmp(ll->value->word, word) == 0){
return i;
}
nn = nn->next;
}
}
/* ALWAYS return a value. */
return -1;
}
Add some debug info before "return i"
int llContains(LinkedList* ll, char* word){
LinkedList* nn= ll;
if(nn != NULL){
for(int i=0; nn != NULL; i++){
if(strcmp(ll->value->word, word)){
printf("Linked->word : %s, word : %s\n",ll->value->word, word);
return i;
}
nn = nn->next;
}
} else {
return -1;
}
}
Try this, and let's see what you have
It seems at least weird to me... The program runs normally.But after I call the enter() function for the 4th time,there is a segmentation fault!I would appreciate any help.
With the following function enter() I wanna add user commands' datas to a list.
[Some part of the code is already posted on another question of me, but I think I should post it again...as it's a different problem I'm facing now.]
/* struct for all the datas that user enters on file*/
typedef struct catalog
{ char short_name[50];
char surname[50];
signed int amount;
char description[1000];
struct catalog *next;
}catalog,*catalogPointer;
catalogPointer current;
catalogPointer head = NULL;
void enter(void) //user command: i <name> <surname> <amount> <description>
{
int n,j=2,k=0;
char temp[1500];
char *short_name,*surname,*description;
signed int amount;
char* params = strchr(command,' ') + 1; //strchr returns a pointer to the 1st space on the command.U want a pointer to the char right after that space.
strcpy(temp, params); //params is saved as temp.
char *curToken = strtok(temp," "); //strtok cuts 'temp' into strings between the spaces and saves them to 'curToken'
printf("temp is:%s \n",temp);
printf("\nWhat you entered for saving:\n");
for (n = 0; curToken; ++n) //until curToken ends:
{
if (curToken)
{ short_name = malloc(strlen(curToken) + 1);
strncpy(short_name, curToken, sizeof (short_name));
}
printf("Short Name: %s \n",short_name);
curToken = strtok(NULL," ");
if (curToken)
{ surname = malloc(strlen(curToken) + 1);
strncpy(surname, curToken,sizeof (surname)); }
printf("SurName: %s \n",surname);
curToken = strtok(NULL," ");
if (curToken)
{ //int * amount= malloc(sizeof (signed int *));
char *chk;
amount = (int) strtol(curToken, &chk, 10);
if (!isspace(*chk) && *chk != 0)
fprintf(stderr,"Warning: expected integer value for amount, received %s instead\n",curToken);
}
printf("Amount: %d \n",amount);
curToken = strtok(NULL,"\0");
if (curToken)
{ description = malloc(strlen(curToken) + 1);
strncpy(description, curToken, sizeof (description));
}
printf("Description: %s \n",description);
break;
}
if (findEntryExists(head, surname,short_name) != NULL) //call function in order to see if entry exists already on the catalog
printf("\nAn entry for <%s %s> is already in the catalog!\nNew entry not entered.\n",short_name,surname);
else
{
printf("\nTry to entry <%s %s %d %s> in the catalog list!\n",short_name,surname,amount,description);
newEntry(&head,short_name,surname,amount,description);
printf("\n**Entry done!**\n");
}
// Maintain the list in alphabetical order by surname.
}
catalogPointer findEntryExists (catalogPointer head, char num[],char first[])
{ catalogPointer p = head;
while (p != NULL && strcmp(p->surname, num) != 0 && strcmp(p->short_name,first) != 0)
{ p = p->next; }
return p;
}
catalogPointer newEntry (catalog** headRef,char short_name[], char surname[], signed int amount, char description[])
{
catalogPointer newNode = (catalogPointer)malloc(sizeof(catalog));
catalogPointer first;
catalogPointer second;
catalogPointer tmp;
first=head;
second=NULL;
strcpy(newNode->short_name, short_name);
strcpy(newNode->surname, surname);
newNode->amount=amount;
strcpy(newNode->description, description);
while (first!=NULL)
{ if (strcmp(surname,first->surname)>0)
second=first;
else if (strcmp(surname,first->surname)==0)
{
if (strcmp(short_name,first->short_name)>0)
second=first;
}
first=first->next;
}
if (second==NULL)
{ newNode->next=head;
head=newNode;
}
else //SEGMENTATION APPEARS WHEN IT GETS HERE!
{ tmp=second->next;
newNode->next=tmp;
first->next=newNode;
}
}
UPDATE:
SegFault appears only when it gets on the 'else' loop of InsertSort() function.
I observed that segmentation fault appears when i try to put on the list names that are after it.
For example, if in the list exists:
[Name:b Surname:b Amount:6 Description:b]
[Name:c Surname:c Amount:5 Description:c]
[Name:d Surname:d Amount:4 Description:d]
[Name:e Surname:e Amount:3 Description:e]
[Name:g Surname:g Amount:2 Description:g]
[Name:x Surname:x Amount:1 Description:x]
and i put: " x z 77 gege" there is a segmentation
but if i put "x a 77 gege" it continues normally....
Can't post into comment, so here it goes:
while (first!=NULL) { //-> this loop can exit ONLY with 'first' being NULL
if (strcmp(surname,first->surname)>0)
second=first;
else if (strcmp(surname,first->surname)==0) {
if (strcmp(short_name,first->short_name)>0)
second=first;
}
first=first->next;
}
if (second==NULL) {
newNode->next=head;
head=newNode;
}
else {
tmp=second->next;
newNode->next=tmp;
first->next=newNode; // first used (but it's NULL!)
}
In other words, your program will crash if it finds any entry that satisfy conditions inside the loop and set 'second'. (This triggers intended addition "inside" the list).
Ok ~ no time to wait for answer :o), in a case you want to enter "after" the 'second' change code to this:
if (second==NULL) {
newNode->next=head;
head=newNode;
}
else {
newNode->next=second->next;
second->next=newNode;
}
explanation (S is 'second', N a 'newNode', A B just some exisiting entries in the list):
initial:
N
A -> S -> B
first assignment:
N ---\
|
v
A -> S -> B
second assignment:
N ---\
^ |
| v
A -> S B
and thus:
A-> S -> N -> B
Not sure what's causing the bug, but I did see this bad pattern:
char *short_name;
short_name = malloc(strlen(curToken) + 1);
strncpy(short_name, curToken, sizeof (short_name));
sizeof(short_name) will be always the same thing (usually 4 for 32 bit platforms and 8 for 64 bit platforms) so is not the correct value to use here. You should be doing:
strncpy(short_name, curToken, strlen(curToken) + 1);
Use something like valgrind to find problems like this.
Falling out of your while loop requires first to be null. In the else statement you attempt to access first.
For this assignment I had to create my own string class. I initially wrote the compareto method to compare two string but return whichever is overall larger. What I want to do is compare and return which one is alphabetically larger i.e. comparing two strings, for example: smith and htims. With the way I designed the compareto method is that the result will be that they are equal. What I want to do is tell me which one comes first alphabetically, so for my example htims would come first. I understand how to do this in Java or even in C with using the <string.h> library, I am just confused as to how to do this myself.
EDIT: I just wanted to note that I am not looking for code answer, rather a nudge in the how I should write the code.
int compareto(void * S1, void * S2){
String s1 = (String S1);
String s2 = (String S2);
int i, cs1 = 0, cs2 = 0; //cs1 is count of s1, cs2 is count of s2
while(s1->c[i] != '\0'){ //basically, while there is a word
if(s1->c[i] < s2->c[i]) // if string 1 char is less than string 2 char
cs2++; //add to string 2 count
else (s1->c[i] > s2->c[i]) //vice versa
cs1++;
i++;
}
//for my return I basically have
if(cs1>cs2){
return 1;
}
else if(cs2 > cs1){
return 2;
}
return 0;
here is mystring.h
typedef struct mystring {
char * c;
int length;
int (*sLength)(void * s);
char (*charAt)(void * s, int i);
int (*compareTo)(void * s1, void * s2);
struct mystring * (*concat)(void * s1, void * s2);
struct mystring * (*subString)(void * s, int begin, int end);
void (*printS)(void * s);
} string_t;
typedef string_t * String;
Any suggestions, all of my google searches involve using the <string.h> library, so I've had no luck.
Im using this to traverse through a linked list and remove the person whose last name matches the person the user is trying to delete.
Here is my test code to help clarify my problem (Note that compareto is in the remove function):
int main() {
Node startnode, currentnode, newnode;
int ans, success;
String who;
who = newString2();
startnode = (Node) malloc(sizeof(pq_t));
startnode->next = NULL;
currentnode = startnode;
ans = menu();
while (ans != 0) {
switch (ans) {
case add:
newnode = getStudent();
startnode = insert(newnode, startnode);
break;
case remove:
printf("Enter the last name of the person you want to delete : \n");
scanf("%s", &who->c);
startnode = removeStudent(startnode, who, &success);
if (success == 0)
printf("UNFOUND\n");
else
printf("permanently DELETED\n");
break;
case view:
printf("Now displaying the list : \n");
displaylist(startnode);
break;
}
ans = menu();
}
}
Node removeStudent(Node head, String who, int * success) {
Node p, l; //p = pointer node, l = previous node
Student current; //Im using generics, so I have to case the current node->obj as a student.
String ln, cln; //the last name of the person I want to remove, and the last name of the current node
p = head;
l = p;
//there can be three cases, p->first node, p->last node, p->some node in between
if (head->obj == NULL) {
printf("The list is empty\n"); //when the list is empty
*success = 0;
return NULL;
}
while (p != NULL) {
current = (Student) p->obj;
cln = current->ln;
if (ln->compareTo(who, cln) == 0) {
if (head == p) { //when there is only one node
head = head->next;
free(p);
*success = 1;
return head;
} else if (p->next == NULL) { //last node
l->next = NULL;
free(p);
*success = 1;
return head;
} else {
l->next = p->next; //middle
free(p);
*success = 1;
return head;
}
}
l = p;
p = p->next;
}
*success = 0;
return head;//couldnt find the node
}
Try comparing the following pairs of strings:
"ABC" vs "DEF"
"ADF" vs "BBB"
"ABC" vs "CBA"
What results do you get? More importantly, why? How do these results compare to what you want to get?
(You should first work it out in your head. Work out the values of c1 and c2 for each step of the comparison loop.)
First, ln isn't properly initialized in the sample removeStudent(), so calling ln->compareTo will probably cause a segfault. Hopefully, ln is properly initialized in your actual code.
To define an ordering on the strings, you can first define what's known in database circles as a "collation": an ordering on characters. You can implement the collation as a function (called, say, chrcmp), or inline within your string comparison function. The important thing is to define it.
Generally speaking, an ordering on a type induces a lexicographic order on sequences of that type: to compare two sequences, find the first place they differ; the lesser sequence is the one with the lesser element at that position.
More formally, suppose sequences are indexed starting at 0. let a and b be sequences of the base type of lengths m and n, respectively. The lexicographic order a ≤ b is:
a < b where ai R bi and aj=mj for all 0 ≤ j < i
a < b if a is a prefix of b
a=b if m=n and ai=bi for all 0 ≤ i < m
Where "a is a prefix of b" means m < n and ai = bi for all 0 ≤ i < m.
The advantage of this approach is you can write a comparison function that will work with any homogeneous sequence type: strings, lists of strings, arrays of integers, what-have-you. If you specialize the comparison function for null-terminated strings, you don't need to worry about the cases for prefixes; simply have '\0' be the least character in the collation.
From a general comparison function (called, say, lexiCompare), you can define
lexicCompareString (a, b):
return lexicCompare(a, b, chrcmp)
and set a String's compareTo member to lexicCompareString.