I'm having problem with pointers in a C program that count the occurrences of a string or more in a bunch of file. The program take in input a file which contains the paths of the files in which search the occurrences. All the files that i will mention are contained in the same folder of the project, whose name is "find". In my case, the input file is "path.txt":
C:\Users\Utente\Desktop\find\try.txt
C:\Users\Utente\Desktop\find\try1.txt
The try.txt content is:
abc
abc
abc
ac
ac
ac
ac
The try1.txt content is:
ac
ac
ac
ac
abc
abc
abc
My program is composed by 4 files, two header-files and two source files:
find.c:
#include "find.h"
int main(int argc, char * argv[]){
FILE *fInput = NULL;
FILE *fp = NULL;
char *line1;
char *line2;
int endOfLineDetected = 0;
size_t nrOfCharRead = 0;
char ch;
fWord *w = NULL;
fWord *start = NULL;
fWord *tail = NULL;
fPath *head = NULL;
fPath *current = NULL;
fInput = fopen(argv[1], "r"); //the file that contains the path of the file in which search.
if(fInput == NULL){
fprintf(stderr, "Cannot open %s, exiting. . .\n", argv[1]);
exit(1);
}
while(!endOfLineDetected){ //read line by line the input file in order to save the path in a structure
line1 = getLineOfAnySize(fInput,128,&endOfLineDetected,&nrOfCharRead);
fPath *node = malloc (sizeof(fPath));
node->path = line1;
node->fileOccurrences = 0;
node->position = NULL;
node->next = NULL;
if(head == NULL){
current = head = node;
}else{
current = current->next = node;
}
}
fclose(fInput);
//create a linked list of the type fWord, one structure for each word.
do{
fWord *app = malloc(sizeof(fWord));
printf("Insert the word to search: ");
scanf("%s", app->word);
app->totalOccurences = 0;
app->p = head;
app->next = NULL;
if(start == NULL){
tail = start = app;
}else{
tail = tail->next = app;
}
printf("Do you want to insert another word? (Y/N): ");
scanf(" %c", &ch);
}while(ch == 'y' || ch == 'Y');
w = start; //pointer back to the top of the fWord structure
//traverse all the structure and execute the algorithm
while(w != NULL){
while(w->p != NULL){
fp = fopen(w->p->path, "r");
if(fp == NULL){
fprintf(stderr, "Cannot open %s, exiting. . .\n", w->p->path);
exit(1);
}
int countLine = 0;
w->p->fileOccurrences = 0;
endOfLineDetected = 0;
while(!endOfLineDetected){
line2 = getLineOfAnySize(fp,128,&endOfLineDetected,&nrOfCharRead);
int n = strlen(line2);
int m = strlen(w->word);
w->p->fileOccurrences = w->p->fileOccurrences + KMP(line2, w->word, n, m, countLine, w->p);
countLine = countLine + 1;
}
w->totalOccurences = w->totalOccurences + w->p->fileOccurrences;
w->p->position = getHead(); // //pointer back to the top of the fPosition structure
w->p = w->p->next;
fclose(fp);
}
w->p = head; //pointer back to the top of the fPath structure
}
w = start; //pointer back to the top of the fWord structure
//traverse all the structure and print out the occurrences and their position
while(w != NULL){
w->p = head;
printf("WORD %s \r\n", w->word);
printf("TOTAL %d \r\n", w->totalOccurences);
while(w->p != NULL){
printf("FILE %s \r\n", w->p->path);
printf("OCCURENCES %d \r\n", w->p->fileOccurrences);
while (w->p->position != NULL){
printf("%d %d\r\n", w->p->position->line, w->p->position->character);
w->p->position = w->p->position->next;
}
w->p = w->p->next;
}
w = w->next;
}
printf("\r\n"); //the file ends with an empty line
return 0;
}
//method used for read line by line a file
char * getLineOfAnySize(FILE* fp, size_t typicalSize, int *endOfLineDetected,size_t *nrOfCharRead){
char *line; // buffer for our string
int ch; // we will read line character by character
size_t len = 0; // number of characters read (character counter)
size_t lineSize = typicalSize; // initial size of the buffer allocated for the line
*nrOfCharRead = 0;
if(!fp) return NULL; // protection
// allocating the buffer
line = realloc(NULL, sizeof(char)*lineSize); // expected size of the line is up to typicalSize
if (!line) return line; // protection, if we fail to allocate the memory we will return NULL
while (1) { // loop forever
ch = fgetc(fp); // getting character by character from file
if (ch == '\n') break; // end of line detected - breaking the loop
if( ch == EOF) {
*endOfLineDetected = 1;
break; // end of file detected - breaking the loop
}
line[len++] = ch; // store the character in the line buffer, increase character counter
if (len == lineSize){ // we reached the end of line buffer (no more room)
lineSize = lineSize + 64; // we have to increase the line size
line = realloc(line, sizeof(char)*(lineSize)); // line buffer has new size now
if (!line) return line; // if we fail to allocate memory we will return NULL
}
if( (len == 0) && *endOfLineDetected){ // empty file
*endOfLineDetected = 1;
break;
}
}
line[len++] ='\0'; // ending the string (notice there is no '\n' in the string)
*nrOfCharRead = len;
return line; // return the string
}
find.h:
#include "kmp.h"
char * getLineOfAnySize(FILE* fp, size_t typicalSize, int *endOfLineDetected,size_t *nrOfCharRead);
kmp.c:
#include "kmp.h"
fPosition *head = NULL;
fPosition *current = NULL;
// Function to implement KMP algorithm
int KMP(const char* X, const char* Y, int m, int n, int line, fPath *app){
int count = 0;
// next[i] stores the index of next best partial match
int next[n + 1];
for (int i = 0; i < n + 1; i++)
next[i] = 0;
for (int i = 1; i < n; i++){
int j = next[i + 1];
while (j > 0 && Y[j] != Y[i])
j = next[j];
if (j > 0 || Y[j] == Y[i])
next[i + 1] = j + 1;
}
for (int i = 0, j = 0; i < m; i++){
if (*(X + i) == *(Y + j)){
if (++j == n){
count = count + 1; //count the occurrences of the string in this file
fPosition *node = malloc (sizeof(fPosition));
node->line = line; //the current line
node->character = i - j + 1; //the shift in which occurs
node->next = NULL;
if(head == NULL){
current = head = node;
}else{
current = current->next = node;
}
app->position = current;
}
}
else if (j > 0) {
j = next[j];
i--; // since i will be incremented in next iteration
}
}
return count; //return the number of occurences found
}
//take the pointer back to the top of fPosition
fPosition * getHead(){
fPosition *app = head;
head = NULL;
return app;
}
kmp.h:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct filePath{
char *path; //the file path
struct filePath *next;
};
struct OccurrencesPosition{
int line; //line in which an occurrence is founded
int character; //shift at which the occurrences comes
struct filePath pathInfo;
struct OccurrencesPosition *next; //pointer to the next occurrences
};
struct fileWord{
char word[50]; //the string to search
int totalOccurences; //the total occurrences of the string
int fileOccurrences; //the occurrences of each file
struct OccurrencesPosition *position; //pointer to the linked list which tracks all the occurrences and their positions
struct fileWord *next; //pointer to the next word
};
typedef struct filePath fPath;
typedef struct fileWord fWord;
typedef struct OccurrencesPosition fPosition;
fPosition * getHead();
int KMP(const char* X, const char* Y, int m, int n, int line, fPath *app);
The problem is that when i run my program passing in input "abc" and "ac" it returns wrong value. More precisely, returns the value corresponding to "ac" in both cases. Here's the execution:
PS C:\Users\Utente\Desktop\find> gcc find.c kmp.c -o "find.exe"
PS C:\Users\Utente\Desktop\find> .\find.exe "path.txt"
Insert the word to search: abc
Do you want to insert another word? (Y/N): Y
Insert the word to search: ac
Do you want to insert another word? (Y/N): N
WORD abc
TOTAL 6
FILE C:\Users\Utente\Desktop\find\try.txt
OCCURENCES 4
3 0
4 0
5 0
6 0
FILE C:\Users\Utente\Desktop\find\try1.txt
OCCURENCES 4
0 0
1 0
2 0
3 0
WORD ac
TOTAL 8
FILE C:\Users\Utente\Desktop\find\try.txt
OCCURENCES 4
FILE C:\Users\Utente\Desktop\find\try1.txt
OCCURENCES 4
As you can see, the WORD and TOTAL are correct in both cases, but the occurrences not. They correspond to "ac" in both cases.
The correct output should be:
WORD abc
TOTAL 6
FILE C:\Users\Utente\Desktop\find\try.txt
OCCURENCES 3
0 0
0 1
0 2
FILE C:\Users\Utente\Desktop\find\try1.txt
OCCURENCES 3
4 0
5 0
6 0
WORD ac
TOTAL 8
FILE C:\Users\Utente\Desktop\find\try.txt
OCCURENCES 4
3 0
4 0
5 0
6 0
FILE C:\Users\Utente\Desktop\find\try1.txt
OCCURENCES 4
0 0
1 0
2 0
3 0
I think that the problem is with the fPosition pointers. Thanks to anyone who helps.
You have design issue.
The problem is occurrences info you are maintaining as part of filePath list.
struct filePath{
char *path; //the file path
int fileOccurrences; //the occurrences of each file
struct OccurrencesPosition *position; // here *****************
struct filePath *next;
};
And file path info you are maintaining as part of fileWord list.
struct fileWord{
char word[50]; //the string to search
int totalOccurences; //the total occurrences of the string
struct filePath *p; //pointer to the linked list of all the files
struct fileWord *next; //pointer to the next word
};
Since you only have one file path list, each word in fileWord list is actually pointing to same filepath list.
Every word is pointing to same file path list
fWord *app = malloc(sizeof(fWord));
printf("Insert the word to search: ");
scanf("%s", app->word);
app->p = head; //here
and you are updating the position info inside the filepath for every word.
w->p->position = getHead(); // //pointer back to the top of the fPosition structure
Thus filePath list is holding position info only for the latest word you search.
Update:
Your design should look as below.
struct filePath{
char *path; //the file path
struct filePath *next;
};
struct OccurrencesPosition{
int line; //line in which an occurrences is founded
int character; //shift at which the occurrences comes
struct filePath pathInfo;
struct OccurrencesPosition *next; //pointer to the next occurrences
};
struct fileWord{
char word[50]; //the string to search
int totalOccurences; //the total occurrences of the string
int fileOccurrences; //the occurrences of each file
struct OccurrencesPosition *position; //pointer to the linked list which tracks all the occurrences and their positions
struct fileWord *next; //pointer to the next word
};
Related
I'm running a program that creates a dictionary tree by reading in words from 'words.txt', and then can search to see if certain words are in the tree. Running this program on https://www.onlinegdb.com/online_c_compiler works perfectly, but I get a segmentation fault when I try to run it on my own Linux system. Any ideas as to why? Here is the code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
/* Node structure of trie */
struct node
{
struct node *next[27]; // 26 for a-z and last one(26th index) is for apostrophe
int end; // value as 1 denotes the end of the word.
};
/* This method is for creating a new node */
struct node *createNode()
{
struct node *newNode = (struct node *)malloc(sizeof(struct node));
newNode->end = 0; // set end as false i.e. 0
for (int i = 0; i < 27; i++) // set all children as NULL
newNode->next[i] = NULL;
return newNode;
}
/* This method is for inserting a word in the trie */
void insert(struct node *root, char *word)
{
struct node *curr = root;
for (int i = 0; i < strlen(word); i++) // iterating character by character
{
int index;
if (word[i] == '\'') // if character is apostrophe index is 26
index = 26;
else
index = tolower(word[i]) - 'a'; // else the index as the alphabet sequence number starting from 0.
// for a - 0, b - 1, ..... z - 25
if (!curr->next[index])
curr->next[index] = createNode(); // create node of that character if not created yet
curr = curr->next[index]; // then go for next character
}
curr->end = 1; // mark end as 1 to denote the ending of the word
}
/* This method is for searching a word in the trie */
int search(struct node *root, char *word)
{
struct node *curr = root;
for (int i = 0; i < strlen(word); i++) // iterating character by character
{
/* Getting index same as insert function */
int index;
if (word[i] == '\'')
index = 26;
else
index = tolower(word[i]) - 'a';
if (!curr->next[index]) // if node of current character not found means the word doesn't exist in trie.
return 0;
curr = curr->next[index];
}
if (curr != NULL && curr->end) // if iterated all the characters and end is 1 then the word exists.
return 1;
else
return 0; // otherwise doesn't exist.
}
int main()
{
/* Reading the file line by line */
FILE *file;
size_t len = 1000;
char *word = (char *)malloc(len);
file = fopen("word.txt", "r");
struct node *root = createNode();
while (fgets(word, len, file) != NULL) // iterating line by line
{
int len = strlen(word);
if (word[len - 1] == '\n') // removing the newline which is at the end of the every line
word[len - 1] = '\0';
insert(root, word); // inserting every word
}
int ans;
word = (char *)("error's"); // checking the existence of the word "error's"
ans = search(root, word);
if (ans == 1)
printf("\"%s\" found!\n", word);
else
printf("\"%s\" not found!\n", word);
word = (char *)("hilli");// checking the existence of the word "hilli"
ans = search(root, word);
if (ans == 1)
printf("\"%s\" found!\n", word);
else
printf("\"%s\" not found!\n", word);
return 0;
}
Here's code that should work. It does work on macOS 10.15.2 Catalina using GCC 9.2.0 and XCode 11.3.1 with the compiler set fussy and a number of memory debugging options enabled. It does not attempt to free the trie that it builds; it should (it is a good exercise to be able to free the structures you build).
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
/* Node structure of trie */
struct node
{
struct node *next[27]; // 26 for a-z and last one(26th index) is for apostrophe
int end; // value as 1 denotes the end of the word.
};
/* This method is for creating a new node */
static struct node *createNode(void)
{
struct node *newNode = (struct node *)malloc(sizeof(struct node));
newNode->end = 0; // set end as false i.e. 0
for (int i = 0; i < 27; i++) // set all children as NULL
newNode->next[i] = NULL;
return newNode;
}
/* This method is for inserting a word in the trie */
static void insert(struct node *root, char *word)
{
struct node *curr = root;
int length = strlen(word);
for (int i = 0; i < length; i++) // iterating character by character
{
int index;
if (word[i] == '\'') // if character is apostrophe index is 26
index = 26;
else
index = tolower(word[i]) - 'a'; // else the index as the alphabet sequence number starting from 0.
// for a - 0, b - 1, ..... z - 25
if (!curr->next[index])
curr->next[index] = createNode(); // create node of that character if not created yet
curr = curr->next[index]; // then go for next character
}
curr->end = 1; // mark end as 1 to denote the ending of the word
}
/* This method is for searching a word in the trie */
static int search(struct node *root, char *word)
{
struct node *curr = root;
int length = strlen(word);
for (int i = 0; i < length; i++) // iterating character by character
{
/* Getting index same as insert function */
int index;
if (word[i] == '\'')
index = 26;
else
index = tolower(word[i]) - 'a';
if (!curr->next[index]) // if node of current character not found means the word doesn't exist in trie.
return 0;
curr = curr->next[index];
}
if (curr != NULL && curr->end) // if iterated all the characters and end is 1 then the word exists.
return 1;
else
return 0; // otherwise doesn't exist.
}
int main(void)
{
/* Reading the file line by line */
FILE *file;
size_t len = 1000;
char *word = (char *)malloc(len);
const char filename[] = "word.txt";
file = fopen(filename, "r");
if (file == 0)
{
fprintf(stderr, "Failed to open file '%s' for reading\n", filename);
exit(EXIT_FAILURE);
}
struct node *root = createNode();
while (fgets(word, len, file) != NULL) // iterating line by line
{
//int len = strlen(word);
//if (word[len - 1] == '\n') // removing the newline which is at the end of the every line
// word[len - 1] = '\0';
word[strcspn(word, "\r\n")] = '\0';
printf("Word: [%s]\n", word);
insert(root, word); // inserting every word
}
int ans;
word = (char *)("error's"); // checking the existence of the word "error's"
ans = search(root, word);
if (ans == 1)
printf("\"%s\" found!\n", word);
else
printf("\"%s\" not found!\n", word);
word = (char *)("hilli");// checking the existence of the word "hilli"
ans = search(root, word);
if (ans == 1)
printf("\"%s\" found!\n", word);
else
printf("\"%s\" not found!\n", word);
return 0;
}
The code runs correctly given a data file containing a suitable subset of these lines:
enough
abracadabra
acid
test
hilli
error's
tests
testing
tested
tester
testosterone
acidly
acidic
It was tested with both DOS (CRLF) and Unix (NL or LF) line endings and was safe with both because it uses strcspn() to zap either sort of line ending:
word[strcspn(word, "\r\n")] = '\0';
If you had old Mac-style line endings (CR only), then you'd have problems with fgets() not recognizing the ends of lines — but if you fixed that (using POSIX getdelim() for example), it would work correctly with such lines too.
The changes made to your code are basically cosmetic, but allow the code to compile cleanly (source trie79.c; program trie79) using fairly stringent options:
$ gcc -O3 -g -std=c11 -Wall -Wextra -Werror -Wmissing-prototypes -Wstrict-prototypes \
> trie79.c -o trie79
$
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
The code is given. I need to count number of words that are non identical. In order to do that i need to compare them using stcrmp. By looking the code below, how i need to construct while or if statements to compare words in a file by using double linked list? I suppose this condition should be in the main to print it then. My condition doesn't work. Also, can you give some advice where and how to sort words by their length here?
To understand the code some explanation:
This program holds a doubly linked list that will read a file that is entered as a command line argument, read each line from file, tokenize each word from line and for each word will place it into a Word Length structure depending on its length and then will place it into a word_count structure dependent on the word's string and count each word's occurrence in a file.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define DELIM " ,.+-=!?:;\t"
#define MAXLINE 25000
typedef struct word_count {
char *word;
int count;
struct word_count *next;
struct word_count *prev;
} WORD;
typedef struct word_length_count {
int length;
int count;
WORD *words;
struct word_length_count *next;
struct word_length_count *prev;
} WLENGTH;
int splitIntoWords(char line[]);
void processLength(char *word);
void processWord(char *word, WORD *wordCount);
void printWordLength();
WLENGTH *createWordLength(char *word);
WORD *createWordCount(char *word);
WLENGTH *wordLength = NULL;
int main(unsigned int argc, unsigned char *argv[]) {
FILE *fpin;
char line[MAXLINE];
int totalWordCount = 0;
if ((fpin = fopen(argv[1], "r")) == NULL) {
printf("Can't open input file.\n");
exit(-1);
}
printf("This is the words all tokenized from the input!\n");
while (fgets(line, MAXLINE, fpin) != NULL) {
line[strcspn(line, "\n")] = '\0';
if (line[0] == '\0')
continue;
totalWordCount += splitIntoWords(line);
}
printf("Total number of words is: %d\n", totalWordCount);
printWordLength();
printf("\nFINISHED!");
}
int splitIntoWords(char line[]) {
char *word;
int count=0;
word = strtok(line, DELIM);
for (;word != NULL;) {
count++;
printf("%s\n", word);
processLength(word);
word = strtok(NULL, DELIM);
}
return count;
}
void processLength(char *word)
{
WLENGTH *wLCounter = NULL;
WLENGTH *wLLast = NULL;
if (wordLength == NULL) {
wordLength = createWordLength(word);
return;
}
wLCounter = wordLength;
while (wLCounter != NULL) {
if (strlen(word) == wLCounter->length) {
++wLCounter->count;
processWord(word, wLCounter->words);
return;
}
wLLast = wLCounter;
wLCounter = wLCounter->next;
}
wLLast->next = createWordLength(word);
}
void processWord(char *word, WORD *wordCount) {
WORD *wCounter = NULL;
WORD *wLast = NULL;
if (wordCount == NULL) {
wordCount = createWordCount(word);
return;
}
wCounter = wordCount;
while (wCounter != NULL) {
if (strcmp(word, wCounter->word) == 0) {
++wCounter->count;
return;
}
wLast = wCounter;
wCounter = wCounter->next;
}
wLast->next = createWordCount(word);
}
WLENGTH *createWordLength(char *word) {
WLENGTH *wLCounter = NULL;
wLCounter = (WLENGTH*)malloc(sizeof(WLENGTH));
wLCounter->words = createWordCount(word);
wLCounter->count = 1;
wLCounter->length = strlen(word);
wLCounter->next = NULL;
return wLCounter;
}
WORD *createWordCount(char *word) {
WORD *wCount = NULL;
wCount = (WORD*)malloc(sizeof(WORD));
wCount->word = (char*)malloc(strlen(word+1));
strcpy(wCount->word, word);
wCount->count = 1;
wCount->next = NULL;
return wCount;
}
void printWordLength() {
WLENGTH *temp = wordLength;
WORD *tempWORD = wordLength->words;
while (temp != NULL) {
WORD *tempWORD = wordLength->words;
tempWORD = temp->words;
printf("\nFor Word Length: %d : There are: %d occurances!\n", temp->length, temp->count);
while (tempWORD != NULL) {
printf("\t%s\toccurs:%d\n", tempWORD->word, tempWORD->count);
tempWORD = tempWORD->next;
}
}
}
You're missing this at the bottom of the outermost while loop of printWordLength():
temp = temp->next;
That's why it goes into an infinite loop (which you didn't tell us).
Now, to count distinct words you just need to count every WORD* in every WORDLENGTH*, which you can do while you're printing them in printWordLength():
void printWordLength()
{
WLENGTH * temp = wordLength;
WORD * tempWORD = wordLength->words;
unsigned int unique_words = 0;
while(temp != NULL)
{
WORD * tempWORD = wordLength->words;
tempWORD = temp->words;
printf("\nFor Word Length: %d : There are: %d occurences!\n",
temp->length, temp->count);
while(tempWORD != NULL)
{
printf("\t%s\toccurs:%d\n", tempWORD->word, tempWORD->count);
unique_words++;
tempWORD = tempWORD->next;
}
temp = temp->next;
}
printf("\nThere are %u unique words\n", unique_words);
}
I am trying to create a program that takes input from a file, puts each word into a "words" structure, and then outputs the results with the frequency of each word, but whenever I try to output the string it just prints something like ?k#?? where I would expect the string to be.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct s_words {
char *str; //stores the word; no pre-determined size
int count;
struct s_words* next;
} words;
words* create_words(char* word) {
//allocate space for the structure
words* newWord = malloc(strlen(word));
if (NULL != newWord){
//allocate space for storing the new word in "str"
//if str was array of fixed size, storage wud be wasted
newWord->str = (char *)malloc(strlen(word));
strcpy(newWord->str,word); //copy “word” into newWord->str
newWord->str[strlen(word)]='\0';
newWord->count = 1; //initialize count to 1;
newWord->next = NULL; //initialize next;
}
return newWord;
}
//If the word is in the list, add 1 to count.
words* add_word(words* wordList, char* word) {
int found=0;
words *temp=wordList;
// search if word exists in the list; if so, make found=1
while (temp!=NULL) {
// printf("looptest\n");
if (strcmp(word,temp->str) == 0) { //use strcmp command
//printf("looptest0\n");
found=1;
temp->count = temp->count + 1; //increment count;
return wordList;
//printf("looptest1\n");
}
else {
temp = temp -> next; //update temp
// printf("looptest2\n");
}
}
// printf("looptest3\n");
//new word
words* newWord = create_words(word);
// printf("looptest4\n");
if (NULL != newWord) {
// printf("looptest5\n");
newWord->next = wordList;
wordList = newWord;
//Insert new word at the head of the list
}
else{
// printf("looptest6\n");
temp = wordList;
while(temp->next != NULL){
// printf("looptest7\n");
temp = temp->next;
}
temp->next = newWord;
}
return newWord;
}
int main(int argc, char* argv[]) {
words *mywords; //head of linked list containing words
mywords=NULL;
FILE *myFile;
myFile = fopen(argv[1],"r"); //first parameter is input file
if (myFile==0) {
printf("file not opened\n");
return 1;
}
else {
printf("file opened\n");
}
//start reading file character by character;
//when word has been detected; call the add_word function
int ch, word = 0, k=0;
char thisword[100];
while ( (ch = fgetc(myFile)) != EOF )
{
// printf("%c",ch);
if (ch==' ' || ch==',' || ch==';' || ch==':' || ch == '.') //detect new word? Check if ch is a delimiter
{
// printf("\ncheck2\n");
if ( word ) //make sure previous character was not delimiter
{
// printf("check\n");
word = 0;
thisword[k] = '\0'; //make the kth character of thisword as \0
// printf("test2\n");
//now call add_word to add thisword into the list
mywords = add_word(mywords,thisword);
// printf("check3\n");
k=0;
}
// printf("test\n");
}
else
{
word = 1;
thisword[k] = ch; //make the kth character of thisword equal to ch
k++;
}
if(ch == EOF){
thisword[k] = '\0';
mywords = add_word(mywords,thisword);
}
}
printf("%s\n",mywords->str);
printf("printing list\n");
//Traverse list and print each word and its count to outputfile
//output file is second parameter being passed
//haven't started to deal with the output file
words* temp = mywords;
while(temp != NULL){
printf("%s\tcount: %i\n",temp->str,temp->count);
temp = temp->next;
}
printf("list complete\n");
return 0;
}
This is all my code, I can't figure out how to error test what the problem is since I can't figure out how to output the strings. I've only started programming in C this year so I assume there's something basic I'm missing.
newWord->str = (char *)malloc(strlen(word));
strcpy(newWord->str,word); //copy “word” into newWord->str
newWord->str[strlen(word)]='\0';
.. writes the null out-of-bounds.
Assuming that strlen() returns the desired value, you should malloc an extra char:
newWord->str = (char *)malloc(1+strlen(word));
Note Olaf comment re. casting in C. Also note that it's unlikely that this is your ONLY bug.
I open the input file
I read it
Store an 2D array
split into tokens
firslt strtok for "\n" and store it
secondly strtok for ":" ignore it
and then strtok for "," and store it
I want to search a word for every single line (which I stored it step 5)
For searching I use strstr but I can't do it.
I add my input file and code .
int
main ()
{
FILE *fp;
fp = fopen ("C:\\input.txt", "r");
char *name[10][10];
char row[100];
char *token, *tkn, *tk;
int h = 0, f = 0, l = 0;
for (h = 0; h < 9; h++)
{
for (f = 0; f < 9; f++)
name[h][f] = NULL;
}
while (fgets (row, sizeof (row), fp))
{
token = strtok (row, "\n");
name[l][0] = strdup (token);
//printf("%s",name[l][0]);
tkn = strtok (token, ":");
tk = strtok (tkn, ",");
isim[l][1] = strdup (tk);
if (strstr (name[l][1], name[l + 1][0]) == 0
|| strstr (name[l][1], name[l + 2][0]) == 0
|| strstr (name[l][1], name[l + 3][0]) == 0)
{
}
l++;
}
fclose (fp);
}
I want to insert a linked list wth this function.
struct AdjListNode{
char *courseName;
char *studentName;
struct AdjList *head;
struct AdjListNode *nextPtr;};
typedef struct AdjListNode node;
typedef struct AdjListNode* nodePtr;
typedef struct AdjListNode** nodePtrPtr;
nodePtr insertVertex(nodePtrPtr header,char *studentName,char *courseName){
nodePtr newNode, temp, prev;
// create node to insert and assign values to its fields
//newNode=createAdjListNode(studentName,courseName);
newNode=malloc(sizeof(node));
newNode->studentName=studentName;
newNode->courseName=courseName;
newNode->nextPtr=NULL;
// if LL empty
if (*header == NULL)
*header=newNode;
// if LL not empty
else {
temp=*header;
while (temp != NULL && (strcmp(temp->courseName,newNode->courseName)<0)) {
prev=temp;
temp=temp->nextPtr;
}
while (temp!=NULL && (strcmp(temp->courseName,newNode->courseName)==0)) {
printf("\n existent key \n");
return temp;
}
// insert node in a sorted fashion
if (temp!=NULL)
newNode->nextPtr=temp;
// if value to insert is the least in LL then have header point to node
if (temp==*header)
*header=newNode;
// otherwise insert node in correct position
else
prev->nextPtr=newNode;
}
return newNode;}
My input.txt file:
George :Math1,History2,Math2
ELizabeth :Math2,Germany1,spanish1
Adam :Germany1,History2,Math1
I want to create a graph with lecture names and I want to use adjancecy list. For adjancecy list I need the connection of two lectures but I'm stuck with this step. How can I search whole line and then store an array. For example I search Math1 . it is in 2 lines .And then I want to create an adj list Math1 ->History2->Math2->Germany1 for Math1 .Please help me
I'm in trouble with my code again.
I want to fscanf result.txt to structures with linked list, but it don't work;
I think the simply linked list must be enought;
The problem is: the program just write the first line, but nothing else.
result.txt format:
point name (for examples)
623 john
457 peter
312 chuck
etc.
The code:
#include <stdio.h>
#include <stdlib.h>
typedef struct ranklist {
int point;
char* name;
struct ranklist *next;
} ranklist;
int how_many_records(FILE *fp){
char ch;
int line=0;
int status;
rewind(fp);
while((status=fscanf(fp, "%*d %*[^\n]%c", &ch))==1)
++line;
if(status != EOF){
++line;
}
rewind(fp);
return line;
}
int how_many_letter(FILE *fp){
int letter = 0;
long pos = ftell(fp);
//fscanf(fp, " %*[^\n]%n", &letter);
fscanf(fp, " %*s%n", &letter);
fseek(fp, pos, SEEK_SET);
return letter;
}
int main(void){
FILE *fp = fopen("result.txt","r");
int name_length;
int lines = how_many_records(fp);
ranklist *r = malloc(lines * sizeof(*r));
ranklist *first = r;
for ( r=first ;r != NULL; r = r->next){
fscanf(fp, "%d", &(r->point));
name_length = how_many_letter(fp);
r->name = malloc(name_length + 1);
fscanf(fp,"%s", r->name);
}
fclose(fp);
for ( r=first ;r != NULL; r = r->next){
printf("%d %s\n", r->point, r->name);
}
free(r);
return 0;
}
fscanf(fp, "%d", &r[y].point);
Here, y is uninitialized.
You need to put y = 0, or, IMO, better to use &(r->point) [and the same goes for r[y].name also]
Suggestion: for reading and parsing whole lines better to use fgets()
You have multiple problems with the creation of the list.
Lets start with the loop:
for ( r=first ;r != NULL; r = r->next){
Nowhere in the loop do you initialize r->next, so after the first iteration you will make y point to totally random memory, leading to undefined behavior.
As mentioned in another answer you don't initialize the variable y, which is another cause of undefined behavior.
You also change r, so r will not point to the original memory you allocated so doing r[y] is a third cause of undefined behavior.
And after the loop you call free with the modified pointer y, which will also lead to undefined behavior. And you don't free the names you allocate in the loop, so have multiple memory leaks as well.
There is no need to pre-allocate the nodes at all, just allocate when needed.
Something like
ranklist *head = NULL;
FILE *fp = fopen(...);
// Read the file and create the list
char buffer[256];
while (fgets(buffer, sizeof(buffer), fp) != NULL)
{
ranklist *node = malloc(sizeof(ranklist));
node->name = malloc(strlen(buffer)); // Will allocate a little more than needed
sscanf(buffer, "%d %s", &node->point, node->name);
node->next = head;
head = node;
}
// Print the list
for (ranklist *n = head; n != NULL; n = n->next)
{
printf("%d %s\n", n->point, n->name);
}
// Free the list
while (head != NULL)
{
// Unlink the first node in the list
ranklist *n = head;
head = n->next;
// And free it
free(n->name);
free(n);
}
The code above doesn't have any error checking, it also have some overhead when allocating space for the name, but it will be safe, it will not handle unrealistically long names, and the list will actually be a stack (last item read will be first in the list).
Function to get the length of the name from the buffer read with fgets:
size_t get_name_length(char *buffer)
{
// Since the buffer was read with `fgets` we need to get rid
// of the newline at the end, if it's there
size_t length = strlen(buffer);
if (buffer[length - 1] == '\n')
buffer[length - 1] = '\0'; // "Remove" by terminating the string
// Find the space dividing the point and the name
char *space = strchr(buffer, ' ');
// Just in case there are multiple whitespace characters in the string
while (*space != '\0' && isspace(*space))
++space;
// Now `space` points to the first non-space letter in the name
// (or to the string terminator, if there's no name
// Then length of the name is the remainder of the string
return strlen(space);
}
FILE *fp = fopen("result.txt","r");
int name_length;
//Just create a link if you use as an array
//int lines = how_many_records(fp);
//ranklist *r = malloc(lines * sizeof(*r));
ranklist *first=NULL, *curr, *r;
int point;
while(1==fscanf(fp, "%d", &point)){
r = malloc(sizeof(*r));//allocate one record
r->next = NULL;
r->point = point;
name_length = how_many_letter(fp);
r->name = malloc(name_length + 1);
fscanf(fp, "%s", r->name);
//make link
if(first == NULL)
first = curr = r;
else
curr = curr->next = r;
}
fclose(fp);
for (r = first; r != NULL; r = r->next){
printf("%d %s\n", r->point, r->name);
}
for (r = first; r != NULL; ){
ranklist *tmp = r->next;//Save next for free(r)
free(r->name);
free(r);
r = tmp;
}
//output the list
void print(ranklist *first){
while(first != NULL){
printf("%d %s\n", first->point, first->name);
first = first->next;
}
}