-
Linked List
My program takes in an input file from the command line and converts the string from the file into a linked list and then depending on the command it will manipulate the string to either reverse the list, print the list, or take a character out...I'm having trouble taking a character out, my code compiles fine but doesn't change the string at all
Code:
#include <stdio.h>
#include <stdlib.h>
#define SIZE 1024
typedef struct node
{
char data;
struct node *next;
} node;
int main(int argc, char **argv)
{
char chr;
char str[SIZE];
char key;
char buffer[SIZE];
FILE *file = fopen(argv[1], "r");
if (file == 0)
{
printf("Could not open file\n");
}
fgets(buffer, SIZE, file);
node *new_head = stringToList(buffer);
while(fscanf(file, " %c", &chr) != EOF){
if(chr == '!')
printList(new_head);
if(chr == '~')
new_head = reverseList(new_head);
if(chr == '-')
{
fscanf(file, "%c", &key);
fscanf(file, "%s", str);
new_head = replaceChar(new_head, key, "");
}
}
fclose(file);
return 0;
}
node *stringToList(char *str)
{
node *temp = NULL;
node *tail = NULL;
for(; *str != '\0'; str++)
{
if (temp==NULL)
{
temp=(node*)malloc(sizeof(node));
temp->data = *str;
temp->next = NULL;
tail = temp;
}
else
{
tail->next = (node*)malloc(sizeof(node));
tail = tail->next;
tail->data = *str;
tail->next = NULL;
}
}
return temp;
}
node *replaceChar(node *head, char key, char *str)
{ node *temp;
if(head == NULL)
return NULL;
if(head->data == key)
{
temp = head->next;
free(head);
return temp;
}
head->next = replaceChar(head->next, key, "");
return head;
}
node *reverseList(node *head){
node *temp;
node *rev_head = NULL;
while(head != NULL){
temp = head->next;
head->next = rev_head;
rev_head = head;
head = temp;
}
return rev_head;
}
void printList(node *temp)
{
node *p;
for(p=temp; p != NULL; p = p->next)
{
printf("%c", p->data);
}
printf("\n");
}
The input.txt file has the following
hello
!
~
- e
!
-
Your code does not compile fine (turn your compiler's warning level up to the max):
Code:
$ make list
gcc -Wall -ggdb3 -std=c99 -o list list.c -lm -lpthread
list.c: In function ‘main’:
list.c:34:3: warning: implicit declaration of function ‘stringToList’ [-Wimplicit-function-declaration]
list.c:34:20: warning: initialization makes pointer from integer without a cast [enabled by default]
list.c:41:7: warning: implicit declaration of function ‘printList’ [-Wimplicit-function-declaration]
list.c:45:7: warning: implicit declaration of function ‘reverseList’ [-Wimplicit-function-declaration]
list.c:45:16: warning: assignment makes pointer from integer without a cast [enabled by default]
list.c:52:7: warning: implicit declaration of function ‘replaceChar’ [-Wimplicit-function-declaration]
list.c:52:16: warning: assignment makes pointer from integer without a cast [enabled by default]
list.c: At top level:
list.c:64:7: error: conflicting types for ‘stringToList’
list.c:34:20: note: previous implicit declaration of ‘stringToList’ was here
list.c:93:7: error: conflicting types for ‘replaceChar’
list.c:52:18: note: previous implicit declaration of ‘replaceChar’ was here
list.c:116:7: error: conflicting types for ‘reverseList’
list.c:45:18: note: previous implicit declaration of ‘reverseList’ was here
list.c:135:6: warning: conflicting types for ‘printList’ [enabled by default]
list.c:41:7: note: previous implicit declaration of ‘printList’ was here
Those are all basically the same type of warning. Your function definitions are placed after you use them. The C compiler reads your source file top to bottom, and doesn't know about anything it hasn't read yet, so when you call stringToList on line 34, the compiler can't check that you're calling it correctly (correct parameter count and type, and correct return type). Either move the function definitions up in the file, before you call them, or put function prototypes near the top of your file (between the typedef and main), so the compiler knows what they look like and can do proper type checking.
Next:
Code:
$ ./list
Could not open file
Segmentation fault (core dumped)
If you can't open the file, you print a message, but let the program continue, which causes a seg fault (the file handle is NULL). You should fail gracefully, by exiting with an error code.
You're having a minor fscanf issue. I added the following line (after the two fscanf calls around line 52), which produced the following output when I ran against the input file you provided:
Code:
printf("replacing key = [%c], str = [%s]\n", key, str);
// output
// replacing key = [ ], str = [e]
Notice, key is a space char, and str (whatever that is used for) is the letter e. I'm guessing that is not what you want, rather you want to remove the letter 'e' from the string. The problem is with your fscanf call. The %c matches any character, including white space (unlike most other format specifiers, which skip over white space -- a confusing nuance of scanf). Put a space before the %c there, to cause scanf to skip the white space, and (possibly) remove the str since I don't think you need it:
Code:
if(chr == '-')
{
fscanf(file, " %c", &key); // note the space
new_head = replaceChar(new_head, key, "");
}
-
Wow thanks for your help, its compiling and taking out the character...the only problem I am having is that say I have the word telephone in my input.txt document it only takes out the first e and not the other one too
-
Notice that, if your function finds the key to replace, it does so, then returns the remainder of the list. It never calls itself recursively in that case (only when it doesn't find the key).
Honestly, I would not bother bother with making that a recursive function, however if you really want to (or must), it's fine. Note, you can simplify this a bit, to only include one recursive call, and one return statement (excluding the base case).
-
well looks like to remove all occurrences you need in line 105 replace the return temp with