I can't open file in C - c

When executed my code in Codeblocks , there is a problem like "error opening file" and I'm sure that there is a file as named "Names". Should I transport my .txt file to another file or something?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct node {
char *word;
int count;
struct node *left;
struct node *right;
};
// Function to create a new node
struct node* createNode(char *word) {
struct node *newNode = malloc(sizeof(struct node));
newNode->word = strdup(word);
newNode->count = 1;
newNode->left = NULL;
newNode->right = NULL;
return newNode;
}
// Function to insert a new node into the binary search tree
struct node* insert(struct node *root, char *word) {
if (root == NULL) {
// Create a new node if the tree is empty
return createNode(word);
} else if (strcmp(word, root->word) < 0) {
// Insert the word in the left subtree if it is less than the root node's word
root->left = insert(root->left, word);
} else if (strcmp(word, root->word) > 0) {
// Insert the word in the right subtree if it is greater than the root node's word
root->right = insert(root->right, word);
}
// Increment the count if the word already exists in the tree
else {
root->count++;
}
return root;
}
// Function to find the depth of the binary search tree
int findDepth(struct node *root) {
if (root == NULL) {
return 0;
} else {
// Calculate the depth of the left and right subtrees
int leftDepth = findDepth(root->left);
int rightDepth = findDepth(root->right);
// Return the maximum of the left and right depths
if (leftDepth > rightDepth) {
return leftDepth + 1;
} else {
return rightDepth + 1;
}
}
}
// Function to count the number of nodes in the binary search tree
int main() {
// Open the text file for reading
FILE *file = fopen("C:\C\Names.txt", "r");
if (file == NULL) {
printf("Error opening file\n");
return 1;
}
// Initialize the root node to NULL
struct node *root = NULL;
char word[50];
int wordCount = 0;
// Read each word from the file and add it to the tree
while (fscanf(file, "%s", word) != EOF) {
root = insert(root, word);
wordCount++;
}
static int count = 0;
int countnodes(struct node *root) {
if (root != NULL) {
countnodes(root->left);
count++;
countnodes(root->right);
}
return count;
}
// Close the file
fclose(file);
printf(
"In total %d words were read from the file and saved in the binary search tree.\n",
wordCount);
printf("Number of nodes in the binary search tree: %d\n", countnodes(root));
printf("The depth of the binary search tree: %d\n", findDepth(root));
}
I tried to change my opening text codeblocks with another codes from internet. But it doesn't work again.

Your filepath should be written as "C:\\C\\Names.txt" or "C:/C/Names.txt".

Your fopen("C:\C\Names.txt", "r") should instead be fopen("C:\\C\\Names.txt", "r").
In the C language, the backslash character has a special meaning in string literals: It is used as an "escape character" to allow representing some common characters that are not found on most keyboards. A list of escape sequences can be found here on cppreference.
Taking a look at that list on cppreference, you'll see that to enter a single literal backslash in the interpreted value of a string literal, you must put two consecutive backslash characters in the source-code for the string literal, like "\\". The first one begins the "escape sequence", and the second one specifies that the escape sequence represents a literal backslash character.
Curiously, cppreference says that:
ISO C requires a diagnostic if the backslash is followed by any character not listed here
And your \C and \N are not in the list, so for your compiler to not have warned you, I'm guessing it must have been in a non-ISO-compliant mode, in which case you can search your compiler's documentation to see how to switch to an ISO-compliant mode.

Related

C - sorted linked list with words and frequencies

I'm having some issues finalizing my code for my programming course (I'm an absolute beginner in C). The aim is to read words from standard input (runfile < input.c), count their frequencies, and sort the list alphabetically (capitalized words first), example output:
Image Sample output
I found pieces of codes here on Stack, which I adapted, and so far it produces the output with words and their frequencies. However, I can't figure out how to get the list sorted as in the sample above. Our teacher suggests, that if a new word is found, it should be inserted sorted straight away into the linked list, he gave us following code sample (it is an excerpt from this program):
void addSorted(link *n, int x) {
if (*n == NULL || x < (*n)->data) {
*n = cons(x, *n);
} else {
addSorted(&((*n)->next), x);
}
}
As far as I understand it, 'link *n' should be the pointer to the next node, 'data' is holding integers in that case, and 'cons' should be a function within this code to construct a new node or link, not sure about 'int x', my guess it's the current integer for comparison.
As I said, I'm having trouble adapting this last bit into my code. I tried to adapt my addWord() function, but it doesn't work out for me.
Below you find the working code I have so far:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
//=============== STRUCTURE ==================
typedef struct word {
char *mywords; // list node with word pointer
int freq; // Frequency count
struct word *pNext; // Pointer to next node in linked list
} Word;
//======= INITIATION OF FUNCTIONS ===========
int readWord(char *temp_word, int temp_size); // Given function to get words
void addWord(char *pWord); // Adds a word to the list or updates exisiting word
void printmywords(Word *pListNodes); // Output list of words and frequencies
Word* construct(char *word); // Constructs list nodes
//============GLOBAL VARIABLES================
Word *pFirst = NULL; // Pointer to first node in linked list
//================ MAIN ======================
int main () {
char temp_word[32]; // temporary buffer to hold words
int size = 10000;
Word *pNode = NULL; // pointer to word counter
while (readWord(temp_word, size)) { // Read all words from standard input
addWord(temp_word); // Add word to list
}
// List the words and their counts
pNode = pFirst;
while(pNode != NULL)
{
printmywords(pNode);
pNode = pNode->pNext;
}
printf("\n");
// Free the allocated memory
pNode = pFirst;
while(pNode != NULL)
{
free(pNode->mywords);
pFirst = pNode;
pNode = pNode->pNext;
free(pFirst);
}
return 0;
}
//================ FUNCTIONS =================
void printmywords(Word *pListNodes)
{
printf("\n%-20s %5d", pListNodes->mywords,pListNodes->freq); // output word and frequency
}
void addWord(char *word)
{
Word *pNode = NULL;
Word *pLast = NULL;
if(pFirst == NULL)
{
pFirst = construct(word);
return;
}
// Update frequency, if word in list
pNode = pFirst;
while(pNode != NULL)
{
if(strcmp(word, pNode->mywords) == 0)
{
++pNode->freq;
return;
}
pLast = pNode;
pNode = pNode->pNext;
}
// Add new word, if not in list
pLast->pNext = construct(word);
}
Word* construct(char *word)
{
Word *pNode = NULL;
pNode = (Word*)malloc(sizeof(Word));
pNode->mywords = (char*)malloc(strlen(word)+1);
strcpy(pNode->mywords, word);
pNode->freq = 1;
pNode->pNext = NULL;
return pNode;
}
int readWord(char *temp_word, int temp_size) {
char *p = temp_word;
char c;
// skip all non-word characters
do {
c = getchar();
if (c == EOF)
return 0;
} while (!isalpha(c));
// read word chars
do {
if (p - temp_word < temp_size - 1)
*p++ = c;
c = getchar();
} while (isalpha(c));
// finalize word
*p = '\0';
return 1;
}
Any help is appreciated.
Okay, try these two functions:
Word *cons(char *word, Word *next) {
Word *result = construct(word);
if (result) {
result->pNext = next;
}
else {
printf("Out of memory in cons\n");
exit(1);
}
return result;
}
void addSorted(Word **nodeRef, char *word) {
Word *node = *nodeRef;
/* strcmp will do a binary comparison, which suits your purpose
because you want capitalized words before lower-case; the order
of the arguments is important - <0 means the first argument should
come before the second argument. */
if ((node == NULL) || (strcmp(word, node->mywords) < 0)) {
*nodeRef = cons(word, node);
}
else if (strcmp(word, node->mywords) == 0) {
++node->freq;
}
else {
/* there's not really any point to using recursion on a linked
list, except for the fact that it's really easy to use recursion
on a linked list. On a vary large list, iteration would most likely
be faster; however, professors really like to show how clever they
are, so you're better off using it anyway. */
addSorted(&node->pNext, word);
}
}
A couple of other points:
char temp_word[32]; // temporary buffer to hold words
int size = 10000;
You've got a 31 character buffer, but you're telling your readWord function that it is 10K characters?
Also, don't cast the return value from malloc().

Binary search tree output file is not the expected output data

Okay so I am creating a Binary Search Tree that reads in strings and stores them in the tree. I am trying to confirm that each string has it's own node and each string is actually being read in. When my program is run, I believe it is creating seven nodes, one for each of the strings in the input file. So I created an Output file that prints the string that was just read to make sure each string is being stored in a node. There are seven strings in my input file :
bring
awake
anger
carry
global
fixed
halt
Here is the code for my program:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXLEN 15
typedef struct treeNode{
char string[MAXLEN+1];
struct treeNode *left;
struct treeNode *right;
}treeNode;
treeNode * insert(treeNode *node, char s[MAXLEN]){
puts("running insert");
if(node == NULL){
node = (treeNode *)malloc(sizeof(treeNode));
strncpy(node -> string, s, MAXLEN);
node -> left = NULL;
node -> right = NULL;
}
else if(strcmp(node->string, s)>0){
node -> right = insert(node->right, s);
}
else if(strcmp(node->string, s)<0){
node -> left = insert(node->left, s);
}
else if(strcmp(node->string, s) == 0){
node -> left = insert(node->left, s);
}
return node;
}
int main(int argc, char *argv[]){
treeNode *root = NULL;
FILE *ifp;
FILE *ofp;
char s[MAXLEN+1];
if(argc != 3){
fprintf(stderr, "Usage: %s file\n", argv[1]); exit(1);
}
if((ifp = fopen(argv[2], "r")) == NULL){
fprintf(stderr, "Could not open file: %s\n", argv[2]); exit(1);
}
ofp = fopen("output.txt", "w+");
while(fscanf(ifp, "%s\n", &s) != EOF){
root = insert(root, s);
fprintf(ofp, "%s\n", root->string);
}
return 0;
}
And this is what the output file looks like after running the program:
bring
bring
bring
bring
bring
bring
bring
Now there are seven strings in each file so i am assuming each one is read. But how can I know if my program successfully created a node for each string?
How can I fix the problem? Any help would be appreciated! Thanks!
FULL CODE repaired : http://pastebin.com/5BTnxTcd
OTHER optimizing code , leave it to you.
It seem your problem is return. It need to be like this, because you need to return root of tree->
treeNode * insert(treeNode *node, char s[MAXLEN]){
puts("running insert");
if(node == NULL){
node = (treeNode *)malloc(sizeof(treeNode));
strncpy(node -> string, s, MAXLEN);
node -> left = NULL;
node -> right = NULL;
}
else if(strcmp(node->string, s)>0){
node -> right = insert(node->right, s);
}
else if(strcmp(node->string, s)<0){
node -> left = insert(node->left, s);
}
else if(strcmp(node->string, s) == 0){
node -> left = insert(node->left, s);
}
return node;
}
**EDIT: ** It seem you have problem also with argv, argv[0] is name of program
fprintf(stderr, "Usage: %s file\n", argv[1]); exit(1);
need to be
fprintf(stderr, "Usage: %s file\n", argv[0]); exit(1);
EDITEDIT :
You need function to do recursive process to tree, and output first left side then right and it will be:
void treeprint( treeNode *node , FILE *OUTPUT_FILE)
{
if ( node != NULL)
{
treeprint(node->left , OUTPUT_FILE);
fprintf(OUTPUT_FILE , "%s" , node->string);
treeprint(node->right, OUTPUT_FILE);
}
}
and call after while loop , and call function like treeprint(root, ofp);.
The issue is with how you are printing. In your insert algorithm, you never modify the string in the node. But, when you print, you are printing the root each time. So, you have a couple of choices:
Use a debugger as #JoachimPileborg suggested.
print the input string s to see if it was read from the input properly.
Write another function to traverse your tree and print out the string in each node as you go. This is the most involved, but is likely to be useful later.
Lets come to the issue you are facing:
You want to know if your program successfully created a node for each string or not. There are more than one ways to tackle this problem. The easiest way is to print out the value of the node when it is actually being created. Thus your code will look something like:
treeNode * insert(treeNode *node, char s[MAXLEN]){
puts("running insert");
if(node == NULL){
node = (treeNode *)malloc(sizeof(treeNode));
strncpy(node -> string, s, MAXLEN);
node -> left = NULL;
node -> right = NULL;
**printToFile( root->string );**
}
else if(strcmp(node->string, s)>0){
node -> right = insert(node->right, s);
}
else if(strcmp(node->string, s)<0){
node -> left = insert(node->left, s);
}
else if(strcmp(node->string, s) == 0){
node -> left = insert(node->left, s);
}
return node;
}
Here is helper function for printing into file:
File* ofp; // Need to be declared globally or pass in functions as parameters
void openWritableFile()
{
ofp = fopen("output.txt", "w+");
}
void printToFile( char* data )
{
fprintf(ofp, "%s\n", data );
}
Another approach would be to travel the whole tree using tree traversal algorithms such as in-order, post-order or pre-order, but only after creation of the complete tree.
Here is how you can do inorder traversal by using your root element and thus printing contents of the tree:
void inorder(struct root* node)
{
if (root == NULL)
return;
inorder(root->left)
printToFile( root->string );
inorder(root->right);
}
You can learn about tree traversal here: Tree Traversal

Binary Tree segmentation fault after implementing search function

i am trying to write a program that will do the following
-read a file from std in
-read each line, and add each line to a binary tree
*if name is already in binary tree,dont add the name to the tree again but update its count of repititions
-print out the binary tree
the file being read in looks something like
dylan
bob
dylan
randall
randall
so when i print out the binary tree i would like it to print out
bob 1
dylan 2
randall 2
i was able to successfully print out the names without worrying about repetitions. I have commented out the blocks of code that mess my program up which is anything interacting with my search function that i added after the fact to take care of repetitions. The code builds a binary tree with each "leave" being a structure of 4 parts,the name,thecount,and the pointers to left and right childs.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct node {
char* name;
int count;
struct node* left;
struct node* right;
};
struct node* addNode(char* string);
void insert(struct node *root, char* stringgg);
void preorder(struct node *root);
int search(struct node* leaf,char* string2find);
int main()
{
char buffer[20];
struct node *root = NULL;
while( fgets(buffer, sizeof(buffer), stdin) != NULL )
{
if(root == NULL)
root = addNode(buffer);
else
insert(root,buffer);
}
preorder(root);
}
struct node* addNode(char* string)
{
struct node *temp = malloc(sizeof(struct node));
temp->name = malloc(strlen(string) + 1);
strcpy(temp->name,string);
temp->left = NULL;
temp->right = NULL;
return temp;
}
void insert(struct node *root, char* stringgg)
{
/* int flag = 5;
flag = search(root,stringgg);
if(flag == 1)
return; */
if(strcmp(stringgg,root->name) < 0)
{
if(root->left == NULL)
root->left = addNode(stringgg);
else
insert(root->left, stringgg);
}
else
{
if(root->right == NULL)
root->right = addNode(stringgg);
else
insert(root->right,stringgg);
}
}
/*int search(struct node* leaf,char* string2find)
{
if(strcmp(string2find,leaf->name) == 0)
{
leaf->count = leaf->count + 1;
return 1;
}
else if(strcmp(string2find,leaf->name) < 0)
{
return search(leaf->left,string2find);
}
else
{
return search(leaf->right,string2find);
}
return 0;
} */
void preorder(struct node *root)
{
if(root == NULL)
return;
printf("%s",root->name);
preorder(root->left);
preorder(root->right);
}
the above code prints out all the names even if there already in a tree. I was hoping that someone would be able to point out my search function errors so that it wont cause a segmentation fault when printing. Possible causes may be my inappropriate use of the return function in which i am trying to return to main if flag == 1 which means match was found so dont addnodes. but if flag does not equal 1 no match was found so go about adding nodes.
at main
while( fgets(buffer, sizeof(buffer), stdin) != NULL ){
char *p = strchr(buffer, '\n');
if(p) *p=0;//remove '\n'
at addNode
temp->count = 1;//initialize counter
return temp;
at insert
void insert(struct node *root, char* stringgg){
int cmp_stat = strcmp(stringgg,root->name);
if(cmp_stat == 0)
root->count++;
else if(cmp_stat < 0) {
if(root->left == NULL)
root->left = addNode(stringgg);
else
insert(root->left, stringgg);
} else {
if(root->right == NULL)
root->right = addNode(stringgg);
else
insert(root->right,stringgg);
}
}
at preorder
printf("%s %d\n",root->name, root->count);
The error is in searching for the very first item in the empty tree — you call
search(root, stringgg)
but root is NULL, so in search() you call
strcmp(string2find, leaf->name)
with leaf == NULL and the program crashes.
A cure: do not search BEFORE you update your tree, but rather search TO update it.
struct node* update(struct node* nd, const char* str)
{
int cmp;
// (sub)tree is empty? - create a new node with cnt==1
if(nd == NULL)
return CreateNode(str);
// test if the node found
cmp = strcmp(str, nd->name);
if(cmp == 0) // YES
nd->count ++; // update the counter
else if(cmp < 0) // NO - search in a subtree
nd->left = update(nd->left, str);
else
nd->right = update(nd->right, str);
return nd; // return the updated subtree
}
Then in main() you just update the tree and store it:
root = update(root, buffer);
Actually, the root value will change only once, on the first call, and all subsequent assignments will not change its value. However that makes the code much more readable.

Circular Doubly Linked List, Print Function

I need to create a circular doubly linked list with a sentinel node which is supposed to read data from a file and insert it in the list, than perform some operations with it. For now I'm stuck on a simple print function which won't print from a list for some reason. The data in the file is in the form of strings,
example: "Popular Sorting Algorithms,
Bubble Sort, Merge Sort, "empty line", etc
Here is my code so far:
Header file contains:
typedef struct NODE {
struct NODE *prev;
char *value;
struct NODE *next;
} NODE;
typedef struct LIST {
int count;
struct NODE *next;
struct NODE *prev;
} LIST;
int InsertEnd(NODE *head, char * value, int *lineCount);
void printLines(int *lineCount);
void Traverse(NODE *head);
Main contains:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include "header.h"
int main()
{
int lineCount = 0;
NODE *head;
head = (NODE *)malloc(sizeof(NODE)); /* creates head node dynamically */
head->next = NULL; /* points to first element */
head->prev = NULL; /* points to last element */
head->value = "HEAD"; /* not needed, but it was pretty useful when debugging */
//*********BEGIN OF OPEN FILE FUNCTION
FILE* fp;
char *fname = NULL;
fname = (char *)malloc(200); <<<<<===== I would prefer to set the size dynamically adjusting but I dont know how
printf("Reading file input.txt\n");
//Checks if the file us unable to be opened, then it shows the error message
if ( !(fp = fopen("input.txt", "r")))
{
printf("\nError, Unable to open the file for reading \n");
exit(100);
}
//*********BEGIN OF READ FROM FILE FUNCTION
while (!feof(fp))
{
fgets(fname, 150, fp); //reads the file and stores in buffer
fname[strlen(fname) - 1] = '\0'; // reduces empty strings for input
if (fname != '\0')
{
InsertEnd(head, fname, &lineCount);
//printf("%s\n", head->next->value); <<<<==== If uncomment this print function would work properly but only in this context
}
else
{
printf("Error'\n"); // For debugging
}
}
Traverse(head); // Print Function Should Be Working in Here
printf("Debugging print\n");
printLines(&lineCount); // Shows Line Count
return 0;
}
// Function inserts a new node at the end of the LIST
int InsertEnd(NODE *head, char * value, int* lineCount)
{
int lineCounter = *lineCount;
/* create new node */
NODE *newnode;
newnode = (struct NODE *)malloc(sizeof( struct NODE));
newnode->value = value;
/* placing new node in LIST */
if (head->next == NULL) /* LIST was empty */
{
newnode->next = head;
newnode->prev = head;
head->next = newnode;
head->prev = newnode;
lineCounter++; // Increment line counter
}
else /* LIST wasn't empty */
{
newnode->next = head;
newnode->prev = head->prev;
head->prev->next = newnode; /* adjust node that was previously last */
head->prev = newnode; /* adjust head node */
lineCounter++; // Increment line counter
}
*lineCount = lineCounter;
return lineCount;
}
// This function prints how many lines there are in the LIST, but I need to get rid of the empty spaces
void printLines(int *lineCount)
{
printf("Line counter is %d", *lineCount); // Shows the number of lines, but doesn't skip empty ones.
}
void Traverse(NODE *head)
{
NODE *current = head;
printf("Forward:");
while (current!= head->prev)
{
printf("%s \n", current->value);
current = current->next;
}
printf("\n");
}
Therefore, I have several problems so far:
1) I need to get rid of empty strings in my list most likely. What would be a better approach, to get rid of them while reading or just not displaying when printing? How would I do this exactly?
2) How can I fix my print(traverse) function and whats wrong there?
3) Additionally all of this should be going on through the menu manager which would prompt for a command ( I got this right I think). But there are some functions that I don't know how to implement. For example when used hits "I" it should call Insert functions and prompt the user to enter two more values and , and later insert at the appropriate . How would I do that? Example "I 1 8"
4) Similarly to the previous one, there should be List function which should print lines between specific values. User input format should be "L to " list inclusively. Example "L 2 5"
5) Similarly to previous there should be a delete function with the format "D " inclusively. Example "D 3 7"
6) And the very last is the Save function in the format "S " Example "S output.txt"
Thank You for the help!
I see at least these issues in your code,
In main()
if (fname != '\0')
this should be
if (fname[0] != '\0')
In InsertEnd()
newnode->value = value;
should be
newnode->value = strdup(value);
In you code there should be some correctness which is very help full first as per your request you need to allocate buffer dynamically but not know file length so it can be achived by this one
int sz;
printf("Reading file input.txt\n");
//Checks if the file us unable to be opened, then it shows the error message
if ( !(fp = fopen("sample.txt", "r")))
{
printf("\nError, Unable to open the file for reading \n");
exit(100);
}
fseek(fp, 0L, SEEK_END);
sz = ftell(fp);
printf("size of file %d\n",sz);
fname = (char *)malloc(sz);
rewind(fp);
Now for reading content from file you checked fname to \0 which is not correct i corrected your while..loop.
while (!feof(fp))
{
if(fgets(fname,256, fp) != 0)
{
fname[strlen(fname) - 1] = '\0'; // reduces empty strings for input
InsertEnd(head, fname, &lineCount);
}
else
{
printf("Error'\n"); // For debugging
}
}

Inserting a string into a Binary Search Tree C

I need to insert strings into a binary search tree but each run through my insert function updates all the nodes and not just the appropriate one.
Its required that each word placed in the binary search tree has the exact amount of memory allocated for it (+1 for the NULL pointer).
Here's the struct being used:
typedef struct node_t{
char *word;
struct node_t *left, *right;
} node_t;
Here's how I am passing in the word:
for(i=0; i< original_words -1; i++)
{
fscanf(ifp, "%s", y);
head = insert(head, y);
}
And here's my insert function:
node_t *insert(struct node_t *head, char *word)
{
if(strcmp(head->word, word) > 0)
{
if(head->left == NULL)
{
head->left = create_node(word);
}
else
{
head->left = insert(head->left, word);
}
}
else
{
if(head->right == NULL)
{
head->right = create_node(word);
}
else
{
head->right = insert(head->right, word);
}
}
return head;
}
EDIT: Heres an example of the input file.
4
-------
bravo
-------
alpha
-------
gamma
-------
delta
Your answer (the insert function) assumes that head has already been defined on first call, it should start with the line:
if (head == null) return create_node(word);
This will also save you from the need for the null lines in the code. I'm not sure that this is the issue, but it is one.
Perhaps more important: how does create_node set up word? If it's something like:
new_node->word = word
Then all you are doing is creating a collection of pointers to the word pulled out of the file. It is quite possible that each reading of a word from the file reads the word into the same piece of memory, so all you are doing is collecting a tree of pointers to the same place in memory. It should be something like:
new_node->word = malloc(strlen(word)+1);
if (new_note->word == null) {FAIL MEMORY LOSS}
strcpy(new_node->word, word);

Resources