I have almost completed my devowelling program for class but have encountered the memory access violation error when it reaches a while loop where I have tried to detect the absence of vowels from a linked list node. I realise that the way I have done this is ridiculously inefficient (many logical OR checks) but I was struggling with other ways to do this. Utterly confused. Not expecting too much help but any pointers (:S) would be greatly appreciated.
https://gist.github.com/3992412
Or, copy'n'paste:
#include <iostream>
#include <stdlib.h>
struct NODE {
char letter;
struct NODE *next;
};
int vowelcheck(struct NODE *llist, int num);
void addnode(struct NODE *llist, char c);
void showsentence(struct NODE *llist);
void devowel(struct NODE *llist);
int main(void) {
char charin;
int input = 1;
struct NODE *llist;
int nodeno = 0;
llist = (struct NODE *)malloc(sizeof(struct NODE));
llist->letter = 0;
llist->next = NULL;
while(input != 0) {
printf("\n\n --Disemvoweler--\n");
printf("(0) Quit\n");
printf("(1) Enter sentence\n");
printf("(2) Disemvowel\n");
printf("(3) Display parsed sentence\n");
scanf("%d", &input);
switch(input) {
case 0: //exit
default:
printf("Exiting\n");
break;
case 1: //sentence input
printf("\nEnter sentence, finish sentence with full stop (.) :\n");
do
{
charin=getchar();
addnode(llist, charin);
}
while (charin != '.');
break;
case 2: //remove vowels
printf("Your choice: `Disembvowel'\n");
while(llist->next != NULL) {
devowel(llist);
llist = llist->next;
}
printf("Disembvoweled!\n");
break;
case 3: //show sentence in memory (devoweled or not)
printf("\n Parsed sentence: \n");
showsentence(llist);
break;
}
}
free(llist);
return(0);
}
void showsentence(struct NODE *llist) {
while(llist->next != NULL) { //while not the last link (ie not full stop)
printf("%c ", llist->letter); //print letter
llist = llist->next; //move to next link
}
}
void addnode(struct NODE *llist, char charin) {
while(llist->next != NULL)
llist = llist->next;
llist->next = (struct NODE *)malloc(sizeof(struct NODE));
llist->next->letter = charin;
llist->next->next = NULL;
}
void devowel(struct NODE *llist) {
struct NODE *temp;
temp = (struct NODE *)malloc(sizeof(struct NODE));
if(llist->letter == 'A' || llist->letter == 'a' || llist->letter == 'E' || llist->letter == 'e' || llist->letter == 'I' || llist->letter == 'i' || llist->letter == 'O' || llist->letter == 'o' || llist->letter == 'U' || llist->letter == 'u')
{
/* remove the node */
temp = llist->next;
free(llist);
llist = temp;
} else {
while(llist->next->letter != 'A' || llist->next->letter != 'a' || llist->next->letter != 'E' || llist->next->letter != 'e' || llist->next->letter != 'I' || llist->next->letter != 'i' || llist->next->letter != 'O' || llist->next->letter != 'o' || llist->next->letter != 'U' || llist->next->letter != 'u')
llist = llist->next;
temp = llist->next->next;
free(llist->next);
llist->next = temp;
}
}
while(...HORRIBLE CONDITION DEREFERENCING llist->next SNIPPED...)
llist = llist->next;
temp = llist->next->next;
free(llist->next);
llist->next = temp;
}
This piece of code has at least two fatal problems. First of all, in C++ indentation does not determine blocks, {} do, and you are missing a pair. Second, you access contents of llist->next without checking if there is next element, or if list has ended.
You might have use for something like:
int character_is_vowel(char ch)
{
return strchr("AEIOUaeiou", ch) != NULL;
}
See what I did, there? I took a small part of the problem at hand (determine whether a character is a vowel in English) and broke it out into a standalone piece of the program.
Then, using standard library functions to cut down on the repetitive nature is of course another idea that's generally good to make code more readable.
Regarding your code, your linked-list code is severely broken in many places. You should consider if you really must implement this using linked lists. It's a string transform, and strings in C are not typically treated as linked lists. Of course, since this was for class, I guess your hands are tied.
Then, you should look hard at all the list operations you do, and analyze if they make sense. Think about memory validity, checks for NULL so you don't overstep the end of the list, and (again) if it's maybe possible to break these operations out into dedicated functions that you can write, think about, and test in isolation from each other and from the actual problem you're trying to solve.
Epigrams about mountains and molehills spring to mind.
Here's a working program that reads lines of input and then disemvowels those lines.
Sample run
$ ./disemvowel
What's the point of including vowels if you're going to strip 'em all?
Entered: What's the point of including vowels if you're going to strip 'em all?
Disemvowelled: Wht's th pnt f ncldng vwls f y'r gng t strp 'm ll?
$
Sample source
#include <string.h>
#include <stdio.h>
static int is_vowel(char c)
{
return(strchr("aeiouAEIOU", c) != 0);
}
int main(void)
{
char line[4096];
while (fgets(line, sizeof(line), stdin) != 0)
{
printf("Entered: %s", line);
char *dst = line;
char *src = line;
char c;
while ((c = *src++) != '\0')
{
if (!is_vowel(c))
*dst++ = c;
}
*dst = '\0';
printf("Disemvowelled: %s", line);
}
return(0);
}
If the string contains no vowels, it copies the string, byte-by-byte, over itself. However, adding a conditional in the loop to see if dst < src would complicate things for negligible benefit (and, in the long run, it would slow things down). If you want to speed this up, you'd use a table-driven is_vowel() function:
static int is_vowel(char c)
{
static vowels[256];
if (vowels['a'] == 0)
{
unsigned char *v = "aeiouAEIOU";
while (*v != '\0')
vowel[*v++] = 1;
}
return vowels[(unsigned char)c];
}
Note the coercion of possibly signed char c to unsigned char to ensure no problems.
The next level of performance would replace the is_vowel() function with a macro that accesses a global array vowels that is appropriately initialized before first use. That's harder to orchestrate (but it's what typically happens with the macros in <ctype.h> such as isalpha()).
Note, too, that the name is_vowel() steers clear of the names reserved by the <ctype.h> header:
§7.31.2 Character handling <ctype.h>
¶1 Function names that begin with either is or to, and a lowercase letter may be added to
the declarations in the <ctype.h> header.
Related
I am working on a simple parser which takes a string as input and parses a string to see if the opening and closing parentheses/brackets/braces are correctly placed. One step in this involves me skipping every character that is not a valid token (a parenthesis, bracket, or brace), because at this point I don't care whether the expression inside the parentheses are valid or not–I'm only interested in whether the parentheses are syntactically correct. I wrote an if statement which tells the loop to skip to the next iteration when it encounters anything that's not an opening or closing brace, but the code looks ugly and is repetitive. I was wondering if there was a better way to do it–perhaps with an enum. Directly below is the function in question, (parse), and below that, I've pasted the code for the entire program so far. If you answer or attempt to answer this, thank you for your time.
void parse(char *string) {
for (int i = 0; i < strlen(string); i++) {
if (string[0] == ')' || string[0] == ']' || string[0] == '}') {
printf("ParseError: Statement begins with invalid token '%c'", string[0]);
return;
}
if (string[i] != '(' || string[i] != '[' || string[i] != '{' ||
string[i] != ')' || string[i] != ']' || string[i] != '}') {
continue;
}
}
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Node {
char character;
struct Node *link;
} * top;
struct Node *getNewNode(char);
void push(char);
void pop(void);
void parse(char *);
void print(void);
int main() {
top = NULL;
char string[100];
char *string_ptr = string;
printf("Enter an expression to parse: ");
fgets(string, sizeof(string), stdin);
parse(string_ptr);
print();
}
struct Node *getNewNode(char character) {
struct Node *newNode = (struct Node *)(malloc(sizeof(struct Node)));
newNode->character = character;
newNode->link = top;
return newNode;
}
void push(char character) {
struct Node *newNode = getNewNode(character);
top = newNode;
}
void pop(void) {
struct Node *temp;
if (top == NULL) {
printf("Stack is empty!");
return;
}
temp = top;
top = top->link;
free(temp);
temp = NULL;
}
void print(void) {
struct Node *temp = top;
while (temp != NULL) {
printf("%c", temp->character);
temp = temp->link;
}
}
void parse(char *string) {
for (int i = 0; i < strlen(string); i++) {
if (string[0] == ')' || string[0] == ']' || string[0] == '}') {
printf("ParseError: Statement begins with invalid token '%c'", string[0]);
return;
}
if (string[i] != '(' || string[i] != '[' || string[i] != '{' ||
string[i] != ')' || string[i] != ']' || string[i] != '}' ||) {
continue;
}
}
}
There are college courses on parsing theory. We construct software “machines” of various kinds to parse strings, so good solutions for issues like this involve incorporating them into an overall parsing scheme, not solving each one individually.
However, given that, a typical way to handle something like this is to prepare an array with information about the characters:
#include <limits.h>
// Define bit flags for character properties.
enum { IsOpener = 1, IsCloser = 2, };
// Initialize array with flags for characters.
static unsigned CharacterProperties[UCHAR_MAX+1] =
{
['('] = IsOpener,
['['] = IsOpener,
['{'] = IsOpener,
[')'] = IsCloser,
[']'] = IsCloser,
['}'] = IsCloser,
};
…
if (CharacterProperties[string[0]] & IsOpener)
… // Here string[0] is one of the “open parentheses” type of characters.
Note there are some sign issues to watch out for: The subscript to CharacterProperties should be nonnegative, so string should be unsigned char * or you should cast it with (unsigned char) in the subscript or you should ensure char is unsigned. And, if any of the characters in the initialization could be negative (are not in C’s basic execution character set), they should be cast too.
This may be a good use case for a switch:
void parse( char *string )
{
/**
* Make sure string[0] is valid first
*/
switch( string[0] )
{
case ')':
case ']':
case '}':
fprintf( stderr, "parse error..." );
return;
break;
default:
break;
}
/**
* Compute the length of the string once rather
* than every time through the loop.
*/
size_t len = strlen( string );
for ( size_t i = 0; i < len; i ++ )
{
/**
* Is the current character a delimiter?
*/
switch( string[i] )
{
case '(':
case ')':
case '[':
case ']':
case '{':
case '}':
// we'll process the delimiter character following
// the end of the switch statement
break;
default:
// this is not a delimiter, go back to the beginning of
// the loop
continue;
break;
}
// process delimiter character
}
}
but that heavily depends on how you're going to process other characters once you beef up your parser. Switches can get ugly and unmaintainable in a hurry. I've written this such that the switches act only as filters; they simply decide whether to proceed with the current operation or not, there's no processing logic in either one.
I'll preface this with the fact that this is for a homework assignment, so I'm just trying to understand what's going wrong not necessarily exactly how to fix it. I'm working in C, taking a name and grade from the user to create/manipulate structs and use a stack. This while loop won't exit and it isn't reaching the testing print statement at the bottom. line, name, cGrade, and fullData are all character arrays, maxGrade and numGrade are both double variables, s is a stack and item is a void*:
while ((fgets(line, SIZE, stdin)) != NULL && line[0] != '\n') {
if (sscanf(line, "%s %s", name, cGrade) == 2) {
numGrade = atoi(cGrade);
fullData[0] = 0;
if (numGrade >= 0 && numGrade <= 100) {
strcat(fullData, name);
strcat(fullData, " ");
strcat(fullData, cGrade);
printf("Added %s\n", fullData);
item = name;
push(s, item);
if (numGrade > maxGrade) {
maxGrade = numGrade;
}
i++;
} else {
printf("ERROR: Grade must be between 0 and 100\n");
}
}
printf("Outside if: line[0] = %c", line[0]);
}
Edit: adding a screenshot of the output
Screenshot of output
Edit: Adding push code
void push(stack s, void* item){
stackelement* e = malloc(sizeof(stackelement*));
e->contents = malloc(sizeof(void*));
e->next = malloc(sizeof(stackelement*));
e->contents = item;
e->next = s->top;
s->top = e;
}
Here's the struct definition as well. I was given this for the assignment so I'm not allowed to change it.
struck stackelementS {
void* contents;
struct stackelementS* next;
}
typedef struct stackelementS stackelement;
struct stackS {
stackelement* top;
}
typedef struct stackS* stack;
It ended up being the simple fact that using sscanf doesn't include the escape character \0 in the returned string which I assume was messing up some of the string functions. I added a char *end; *end = '\0'; and used strcat() to append it to the name and cGrade. I fixed some of the errors suggested in the comments and it cleaned up the code a lot.
Here's the fixed code:
while(fgets(line, SIZE, stdin) != NULL && line[0] != '\n'){
if(sscanf(line, "%s %s", name, cGrade) == 2){
strcat(name, end);
strcat(cGrade, end);
numGrade = strtod(cGrade, &ptr);
if(numGrade >=0 && numGrade<= 100){
push(s, line);
printf("Added student %s with grade %s to the stack\n", name, cGrade);
if(numGrade > maxGrade){
maxGrade = numGrade;
}
i++;
}
else{
printf("ERROR: Grade must be between 0 and 100, please re-enter the information\n"); }
}
}
I need some help regarding dynamic allocation of arrays of pointers in C. I am trying to create a program that reads a sentence of words from user input, and stores the words in character array strings. I then want to save the pointers char *word to these words in an array of pointers char **wordArray.
Creating a working method for dynamic allocation for the words was easy enough, and it reads character by character from user input. However, trying to adapt this method for the array of pointers was trickier.
The current function char **varArray is obviously flawed, but my thinking was "while the user has input, get words pointers for the array of pointers". It now effectively loops the first word for every char c.
My question is, how do I implement a second layer (char **varArray()) of dynamic memory allocation of my array of pointers? How can the function detect when to call char *word()?
Feedback for the code, style, or other errors are of course appreciated. My level is intermediate beginner.
/*CREATES AND ALLOCATES DYNAMIC VARIABLE ARRAY*/
#include <stdio.h>
#include <stdlib.h>
char **varArray();
char *word();
char **varArray()
{
char **tmp=NULL;
char **wordArray=NULL;
size_t size=0;
char c = EOF;
int words=0;
while(c) {
c=getc(stdin);
if (c == EOF || c == '\n')
c=0;
if (size <= words) {
size+=sizeof(char *);
tmp = realloc(wordArray,size);
if(tmp == NULL) {
free(wordArray);
wordArray=NULL;
printf("Memory allocation failed. Aborted.\n");
break;
}
wordArray=tmp;
}
words++;
wordArray[words]= word();
return wordArray;
}
The method for retrieving ONE word:
/*GETS ONE WORD FROM USER INPUT*/
char *word()
{
char *word=NULL, *tmp=NULL;
size_t size=0;
char c = EOF;
int letters=0;
while(c) { //reads character by character
c=getc(stdin);
if (c == EOF || c == '\n' || c==' ') //remove ' ' to read all input
c =0;
if (size <= letters) { //increase and reallocate memory
size = size + sizeof(char);
tmp = realloc(word,size);
if (tmp==NULL) { //check if allocation failed
free(word);
word=NULL;
printf("Memory allocation failed. Aborted.\n");
break;
}
word= tmp;
}
letters=letters+1;
word[letters]=c;
}
/*ADD SENTINEL CHARACTER*/
letters++;
size += sizeof(char);
word = realloc(word,size);
word[letters]='\n';
return word;
}
Here's the skeleton of the program you want to write.
...
char* currentWord;
char **wordArray=NULL;
while ((currentWord = word()) != NULL) {
.... add current word to word array with realloc...
}
....
char* word() {
int ch;
char* outputWord = NULL;
while ((ch = getch()) != EOF) {
if ( ... ch is a word character ... )
... add ch to output word with realloc ...
else {
char* ret = outputWord;
outputWord = NULL;
return ret;
}
}
return NULL;
}
Note how the two while loops are doing exactly the same thing.
while ((element = getNextElement()) != sentinelValue) {
.... process newly obtained element ....
}
I have now successfully implemented a version of the shell provided by #n.m. However, another problem arose - since word() relies on the sentinel newline character \n to quit, it also fails to read the final word, and does not enter the loop the last, vital time.
I have tried to implement some if-cases, but these of course fail due to the while-condition. Another idea would be to implement some switch case, but I am not sure that would avoid the nastiness of the while loop?
Do note that the code has little error checking to minimise the clutter.
char **wordArray() {
char *currentWord;
char **wordArray=NULL;
size_t size=0;
int i=0;
while((currentWord = word()) != NULL) {
size+=sizeof(char *);
wordArray=(char **) realloc(wordArray,size);
wordArray[i]=currentWord;
printf("Test - Current word: %s\n",currentWord);
i++;
}
return wordArray;
}
The relevant word() function:
char *word() {
char ch;
int i=0;
size_t size=0;
char *returnWord = NULL;
char *outputWord = NULL;
char *tmp = NULL;
while((ch = getc(stdin)) != EOF && ch !='\n') { //&& ch !='\n'
if (ch != ' ' ) { //&& ch !='\n'
size += sizeof(char);
tmp = (char *) realloc(outputWord,size);
outputWord= tmp;
outputWord[i]=ch;
printf("Test1: %c\n",*(outputWord+i));
i++;
} else {
printf("Test2: %s\n",outputWord);
returnWord=outputWord;
outputWord=NULL;
printf("Test3: %s\n",returnWord);
return returnWord;
}
}
return NULL;
}
I am taking a beginner's course in C, and trying to wrap my head around "strings". I have previously programmed in Java, so it is a bit confusing.
I am wondering how to split a "string" into characters, so as to be able to remove certain characters. I have written code for a linked list, with each node holding a data value, as well as a next pointer (calling it node_line, as it holds lines).
typedef struct node {
char *data;
struct node *next;
} node_line;
This works without problems, and I can traverse the entire list and print out each element:
void print_list(node_line head) {
node_line * current = head;
while(current != NULL) {
printf("%s\n", current->data);
current = current->next;
}
}
However, I am having problems with converting the "string" in current->data into characters. That is, reading one character at a time.
For instance, I want to write a program that removes all the vowels in a "string". I have managed to solve this when reading a file, using the getc() function. However, I can't seem to do so with the text in current-> data.
int c;
while((c = getc(f)) != EOF) {
//REMOVE
if(c=='a' || c=='e' || c=='i' || c=='o' || c=='u' || c=='y') {
printf(""); //Remove the vowel
}
else {
putchar(c); //Write out one character at the time.
}
}
I imagine it being something like:
while ((c = getc(current->data) != NULL) { ... }
Any help, tips, etc. are highly appreciated!
getc is for reading from files. To access chars in a char * buffer (string) you would typically do something like this:
for (const char * p = current->data; *p != '\0'; ++p)
{
char c = *p;
if (c=='a' || c=='e' || c=='i' || c=='o' || c=='u' || c=='y') {
...
}
}
Or if you prefer explicit array indexing rather than pointers:
const char * s = current->data;
for (int i = 0; i < strlen(s); ++i)
{
char c = s[i];
if (c=='a' || c=='e' || c=='i' || c=='o' || c=='u' || c=='y') {
...
}
}
void print_list(node_line head) {
should be
void print_list(node_line *head) {
getc:
Returns the character currently pointed by the internal file position
indicator of the specified stream.
That's not what you want, use pointer arithmetic:
char *s = current->data;
while (*s) {
if(*s=='a' || *s=='e' || *s=='i' || *s=='o' || *s=='u' || *s=='y') {
printf(""); //Remove the vowel
}
else {
putchar(*s); //Write out one character at the time.
}
s++;
}
or better:
char *s = current->data;
while (*s) {
if(*s!='a' && *s!='e' && *s!='i' && *s!='o' && *s!='u' && *s!='y') {
putchar(*s); //Write out one character at the time.
}
s++;
}
This program will create link list from text alphabetically.
It is case-sensitive and it will eliminate the marks.
When I run the program, it gives a segmentation fault. I can't find where the problem is. I added the printf() in order to find the mistake but i can't.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
typedef struct NODE {
char *word;
int count;
struct NODE *next;
}NODE;
char *get_word(FILE *fp){
printf("getWord");
char *str = (char*)malloc(sizeof(char)*100);
char c;
do {
c = fgetc(fp);
if (c == EOF)
return 0;
} while (!isalpha(c));
do {
printf("getWord");
*str++ = tolower(c);
c = fgetc(fp);
printf("Word");
} while (isalpha(c));
return str;
}
void insert(NODE* sortedList, char *word) {
printf("INSERT ");
char *str = (char*)malloc(sizeof(char)*100);
if (sortedList == NULL || word < sortedList->word) {
NODE *ekle;
ekle=(NODE*)malloc(sizeof(NODE));
strcpy(ekle->word,word);
ekle->count = 1;
ekle->next = sortedList;
sortedList = ekle;
}
else {
//
NODE *current = sortedList->next;
NODE *pre = sortedList;
while (current != NULL && word > current->word) {
pre = current;
current = current->next;
}
if (current != NULL && word == current->word) {
(current->count)++;
}
else {
NODE *ekle;
ekle=(NODE*)malloc(sizeof(NODE));
strcpy(ekle->word,word);
ekle->count = 1;
ekle->next = current;
pre->next = ekle;
}
}
}
void createList(FILE* fp,NODE *n) {
printf("CREATELIST ");
char *word;
strcpy(word,get_word(fp));
puts(word);
while (strcmp(word,"")) {
printf("Create_LİST2");
insert(n,word);
word = get_word(fp);
}
}
NODE *head;
int main(){
NODE *list=NULL;;
FILE *fp;
fp=fopen( "text.txt", "r" );
head=list;
while(!feof(fp)){
createList(fp,list);
}
while(list->next != NULL){
printf("%s", list->word);
}
return 0;
}
A major problem is this line
*str++ = tolower(c);
This changes the pointer str, so when you return str from the function it actually points beyond the string. A string which you, by the way, do not terminate.
Another major problem are these lines:
NODE *ekle;
ekle=(NODE*)malloc(sizeof(NODE));
strcpy(ekle->word,word);
Here you allocate a NODE structure, but you do not allocate memory for ekle->word, so it points to indeterminate memory. You have the above code in two places.
Equal to the above allocation problem, you have
char *word;
strcpy(word,get_word(fp));
Here too you don't allocate memory for word, so you have a pointer to indeterminate memory.
Also, in C you should not cast the return of malloc. You should also look out for warnings from the compiler, and if you don't get any from the code you have then you need to enable more warnings. Compiler warnings are often a sign of undefined behavior which is what all of the above leads to. And finally, next to the compiler I would argue that a debugger is a developers best tool. Learn to use it, it would have helped you with some of the above problems.
Here's one problem:
char c;
do {
c = fgetc(fp);
if (c == EOF)
return 0;
This is wrong; fgetc() returns int, since EOF does not fit in a char. The first line should therefore be:
int c;
Fist you have to verify if the file is correctly open. Then AFAIK the strcpy requires that destination has enough space to store the data (line 74), instead of "char *word" use "char word[255]" for instance (if you know the size limit).
Your main problem is here:
*str++ = tolower(c);
First of all, once you increment str, you no longer hold a pointer to the dynamically allocated memory. Therefore, you will not be able to release that memory at a later point in the execution of your program, which will eventually lead to memory leaks. Second, when you return str at the end of the function, you are not returning a pointer to that string as you're probably hoping to.
Additional problems are:
You are not making sure that no more than 99 characters are stored.
You are not terminating the string pointed by str with a null-character.
You are not de-allocating the string pointed by str if an EOF is encountered.
You are not using an int in order to store the return value of function fgetc.
Here is how your function should look like:
#define MAX_WORD_LEN 101
char* get_word(FILE* fp)
{
char* str = (char*)malloc(sizeof(char)*MAX_WORD_LEN);
int c,i;
do
{
c = fgetc(fp);
if (c == EOF)
{
free(str);
return 0;
}
}
while (!isalpha((char)c));
i = 0;
do
{
str[i++] = tolower((char)c);
c = fgetc(fp);
}
while (isalpha((char)c) && i < MAX_WORD_LEN-1);
str[i] = 0;
return str;
}
Please note that if a word in your file is longer than MAX_WORD_LEN-1 characters, then you will essentially "lose" the last character that was read, because it will not be stored anywhere.
not the segfault, but: you malloc str, without using or freeing it
void insert(NODE* sortedList, char *word) {
printf("INSERT ");
char *str = (char*)malloc(sizeof(char)*100);
Here i write code which may helps you to understand problem. It's not exact what as your program does but somewhat similar and easier to understand and also find your all problems solution from below code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
typedef struct NODE
{
char word[100];
int count;
struct NODE *next;
}NODE;
NODE *head = NULL;
NODE *list = NULL;
void insert(char *word)
{
if (list == NULL)
{
list = calloc(1, sizeof(NODE));
if (NULL == list)
{
perror("Memory allocation failed");
return;
}
strncpy(list->word, word, 99);
list->count = 1;
list->next = NULL;
head = list;
}
else
{
list->next = calloc(1, sizeof(NODE));
if (NULL == list->next)
{
perror("Memory allocation failed");
return;
}
strncpy(list->next->word, word, 99);
list->next->count = 1;
list->next->next = NULL;
list = list->next;
}
}
void createList(FILE* fp)
{
char word[100] = {0};
while (EOF != fscanf(fp, "%99s", word))
{
if (0 < strlen(word))
{
insert(word);
}
memset(word, 0x00, 100);
}
}
int main()
{
FILE *fp = NULL;
fp = fopen("text.txt", "r");
if (NULL == fp)
{
//File is not readable
perror("text.txt file open failed");
return -1;
}
createList(fp);
list = head;
while(NULL != list)
{
printf("%s\n", list->word);
list = list->next;
}
if (NULL != fp)
{
fclose(fp);fp = NULL;
}
return 0;
}
And also create function to free all memory which is allocated in insert function.