Printing the structure of n-ary array in C - c

My homework for my c course is to implement a menu as a n-ary tree. I have to create a struct, populate it with data and print the data.
Although creating a struct and populating were relatively easy, I have found the struggle with printing. My goal is to print the structure in this manner:
1 File
1.1 Open
1.2 Save As
1.3 Save as Other
1.3.1 Text
1.3.2 Word or Excel Online
1.4 Send File
1.4.1 Attach to Email
1.4.2 Send & Track
1.5 Close
My struggle is that I can't find a way how to:
a) Add spaces after each child.
b) Add number for each child of the child.
My structure looks like this:
typedef struct node
{
long nodeID;
long parentNodeID;
char name[100];
struct node *next;
struct node *child;
} node;
My failed attempt to accomplish this :
void printMenu(node* root){
if(root == NULL) {
fprintf(stderr, "Root has not been initialised");
exit(1);
}
if(root->parentNodeID == 0){
printf("%ld %s",root -> nodeID,root -> name);
fflush(stdout);
printMenu(root->child);
}
if(root->child){
printf("%6ld.%ld %s",root->parentNodeID,root->nodeID - 1,root->name);
fflush(stdout);
printMenu(root->child);
}
printf("%5ld.%ld %s",root->parentNodeID,root->nodeID - 1,root->name);
fflush(stdout);
printMenu(root -> next);
}
Please send help :(

I would sugggest using recursion. Below is a coded up example of how that would work. You would need to call this function with spacing starting at 0. This also assumes that the parentID is the appropriate ID with the previous parent id's.
void printMenu(node* root, int spacing) {
if(root == NULL) {
return;
}
else {
for(int i =0; i < spacing; i++) {
printf(' ');
}
printf("%d.%d %s", root->parentNodeID, root->nodeID, root->name);
for(int i =0; i< sizeof(root->child); i++) {
printNodes(root->child[i], spacing+1);
}
}
}

Rather than long parentNodeID, use a pointer to the parent node:
typedef struct node
{
struct node *parent;
struct node *next;
struct node *child;
char *name;
long id;
} node;
The root level nodes (File, for example) have NULL parents.
This lets you use a simple recursive function to print the IDs. The only trick is that you need to recurse before printing:
void print_path(FILE *out, node *to)
{
if (to->parent) {
/* Non-root nodes */
print_path(out, to->parent);
fprintf(out, ".%ld", to->id);
} else
/* Root nodes */
fprintf(out, "%ld", to->id);
}
With this, printing the menu recursively is easy:
void print_menu(FILE *out, node *menu, int indent)
{
while (menu != NULL) {
/* Print indent first */
fprintf(out, "%*s", indent, "");
/* Current menu entry */
print_path(out, menu);
fprintf(out, " %s\n", menu->name);
/* Submenu? */
if (menu->child)
print_menu(out, menu->child, 3 + indent);
menu = menu->next;
}
}
If you have say node *all; that contains your menu tree, and you wanted to print it to standard output, just call print_menu(stdout, all, 0);.
Note that I like to explicitly specify the file handle used for output, rather than just assume it is always stdout. (fprintf(stdout, ..FOOBAR..) is equivalent to printf(..FOOBAR..).) This approach lets me use the exact same functions when printing to a file, you see.
Printing the indent via %*s is not magic. The * in the width field for the s conversion just means that printf() will take the width from an int parameter, before the actual string to be printed. Thus, printf("%*s", n, "") will print n spaces. It is often called a "trick", but really, it is just well-documented printf() behaviour.

Related

Hash table didn't return correct value by it's Index

I have this csv file contain people contact:
NAME, NUMBER, ADDRESS, EMAIL
Kevin Mahendra, +62 812-XXXX-XXXX, Jln.Anggrek Merah 3, kevinitsnovember#gmail.com
Adwi Lanang, +62 821-XXXX-XXXX, Jln.Ruhui Rahayu, adwilanang#gmail.com
Wasis Sirutama, +62 813-XXXX-XXXX, Jln.Pramuka 6 25, wasisnaruto#gmail.com
Alief Dean, +62 811-XXXX-XXXX, Jln.Padat Karya, aliefdean#gmail.com
Baharudin Nuri, +62 813-XXXX-XXXX, Jln.Ruhui Rahayu 1, baharudin008#yahoo.com
Yonggi Wijaya, +62 853-XXXX-XXXX, Jln.PM Noor Pondok S, yonggiwijaya#gmail.com
Artha Yoga, +62 822-XXXX-XXXX, Jln.A.Yani Gg.1, arthayoga97#gmail.com
Rusydi Nashier, +62 858-XXXX-XXXX, Jln.Perjuangan No.90, rusydinashier#gmail.com
Andre Pieters, +62 822-XXXX-XXXX, Jln.Villa Tamara No.1, azzahz#gmail.com
Paco Corleone, +62 816-XXXX-XXXX, Jln.Anggrek Merah 3, pacocorleone#gmail.com
And this is my C code:
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// Number of buckets for TABLE
#define N 26
#define MAX 50
typedef struct Contact
{
char name[MAX];
char number[MAX];
char address[MAX];
char email[MAX];
struct Contact* next;
}
Contact;
void searching_contact(FILE *file);
void load_hash_table(FILE **file);
unsigned int hash(const char *name);
// Hash table
Contact *table[N];
int main(void)
{
// OPEN CSV FILE AS append and read mode
FILE *file = fopen("contacts.csv", "r");
if (file == NULL)
{
printf("Error open file!\n");
return 1;
}
searching_contact(file);
fclose(file);
return 0;
}
void searching_contact(FILE *file)
{
char name[MAX];
printf("Search Name: ");
scanf("%[^\n]%*c", name);
fflush(stdin);
// Load csv file into hash table first
load_hash_table(&file);
// Get index number by calling hash function
int hashIndex = hash(name);
printf("\n\nIndex number we get from searching: %i\n", hashIndex);
// Point to table that may contain the person
Contact *cursor = table[hashIndex];
// This will always print the last person
printf("The name on the table: %s\n", cursor->name);
// Keep traversing linked list in table
while (cursor != NULL)
{
// If the person found, print the contact information
if (strcmp(name, cursor->name) == 0)
{
printf("%s %s %s %s", cursor->name, cursor->number, cursor->address, cursor->email);
}
else
{
// If not the person, but in the same table, go to the next linked list
cursor = cursor->next;
}
}
printf("Not found!\n");
}
// FUNCTION TO LOAD CSV FILE INTO HASH TABLE
void load_hash_table(FILE **file)
{
Contact *new = malloc(sizeof(Contact));
if (new == NULL)
exit(1);
/*
"%[^,], "
Empty space or space after above sign will remove spaces or newline (\n) on each string
Just because, when we try to use hash function, the spaces or newline will also include
And we want to remove them so when user searching by name it will produce same hash index
*/
while(fscanf(*file, "%[^,], %[^,], %[^,], %[^\n] ", new->name, new->number, new->address, new->email) == 4)
{
// Skip header from CSV file
if (strcmp("NAME", new->name) == 0)
continue;
// Get index number from hash function with People name as input
int index = hash(new->name);
// Try to print name and it's index in csv file for debugging
printf("%s\n", new->name);
printf("%i\n", index);
/*
Create linked list point to WHAT inside Table[index]
For very first struct, it points to NULL, then store it in Table
Next struct, with the same Index number, it will point the first one
*/
new->next = table[index];
table[index] = new;
// Malloc for next fscanf
Contact *new = malloc(sizeof(Contact));
if (new == NULL)
exit(1);
}
}
// Hash function that will return index number from Table
unsigned int hash(const char *name)
{
// TODO
unsigned long hash = 5381;
int c;
while ((c = toupper(*name++)))
{
hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
}
return hash % N;
}
So, Im trying to make a program where user can search people contact by name. And as you can see, i also want to exercise using hash table/hash function. So before searching, it will load all csv file into hash table (see load_hash_table()). But in the end, it always failed to found the person even though user already typing right name.
I try debugging using only printf.
First, at load_hash_table() function i print each name and it's index. And it's working correctly. It prints all the name in csv file and also correct index that produced by hash function.
Second, here's the problem. When i try to print inside searching() function. It produced correct and same index number. But when i print the name, it always print the last person on csv file, which is Paco Corleone. No matter what index number we put in Table[], it always print that last person name.
I don't understand. It seems like the hash table lost all the data that have been loaded before when while loop inside load_hash_table() function is over. Maybe you'll see the problem when you run the code i gave. Please help me, i'm new in C language, thanks!
Couple of problems:
The major problem is that there are two Contact *new = malloc(sizeof(Contact)); lines. One inside the loop and one outside. They are two different variables. The while loop condition is using the one outside the loop. Hence the fscanf is writing to the same memory for every loop. One way to fix that is to make the second instance just new = malloc(sizeof(Contact));. Note that this loop has a memory leak as the last allocated node is lost - left to you as an exercise to fix.
searching_contact has an infinete loop as the if (strcmp(name, cursor->name) == 0) block is missing a break.

C function that creates a linked list with "divisible by 3" numbers from another linked list

First, I need to create and show a list that ends with number 1000. That works well.
Then, I want to create another list with only the numbers that are divisible by 3 in the first list, but it doesn't work.
The worst thing is that it doesn't even tell me what's going on. It just gives error in the execution but the console doesn't say anything.
I will really appreciate any help.
I tried all.
#include <stdio.h>
#include <stdlib.h>
#include<time.h>
#define CANTIDAD_NUMEROS 13
#define CANTIDAD_NUMEROS2 6
#define DESDE 1
#define HASTA 10
typedef struct lista{
int num;
struct lista *sig;
}nodo;
void crear (nodo *pt, int, int);
void crear2 (nodo *pt, int, nodo *pt2);
void mostrar(nodo *pt);
int main()
{
int i=0;
int t=0;
nodo *prin;
nodo *prin2;
prin=(nodo*)malloc(sizeof(nodo));
prin2=(nodo*)malloc(sizeof(nodo));
crear(prin,i, t); //creates first list
mostrar (prin); //shows first list
crear2(prin,i, prin2); //gets 'divisible by 3' numbers
mostrar(prin2); // shows second list
return 0;
}
//creates list
void crear (nodo *registro, int cont, int t)
{
scanf("%d", &t);
registro->num = t;
if (registro->num == 1000)
registro->sig=NULL;
else
{
registro->sig=(nodo*)malloc(sizeof(nodo));
cont++;
crear (registro->sig,cont, t);
}
return;
}
//shows list
void mostrar (nodo *registro)
{
if (registro->sig !=NULL)
{
printf ("%d\n",registro->num);
mostrar (registro->sig);
}else{
printf("%d\n",registro->num);
}
return;
}
//creates second list with only numbers that are divisible by 3
void crear2 (nodo *registro, int cont, nodo *registroNuevo)
{
if ((registro->num % 3) == 0){
registroNuevo->num = registro->num;
registroNuevo->sig = (nodo*)malloc(sizeof(nodo));
}
if(registro->sig != NULL){
crear2(registro->sig,cont, registroNuevo->sig);
}else{
return;
}
}
I expect to have the 1st list shown (which it's happening) and also the 2nd list shown with the numbers that are divisible by 3, which doesn't happen.
First of all, I admire your dedication to recursion!
The problem is that in crear2, registroNuevo->sig is uninitialized which causes a segfault. I almost always start a function that operates on a recursive linked data structure by checking if the parameter node is null. If so, I can safely continue on with the body of the function. Following this logic of protecting against nulls, we need to pass the registroNuevo node along without touching it in the case when registro->num % 3 != 0 and ensure all of its fields are initialized.
Here's the corrected function:
void crear2(nodo *registro, int cont, nodo *registroNuevo)
{
if (registro) {
if (registro->num % 3 == 0) {
registroNuevo->num = registro->num;
registroNuevo->sig = NULL;
if (registro->sig) {
registroNuevo->sig = malloc(sizeof(nodo));
}
crear2(registro->sig, cont, registroNuevo->sig);
}
else {
crear2(registro->sig, cont, registroNuevo);
}
}
}
Having said that, this function is still a bit less than ideal for a couple reasons. First of all, the name is vague and could describe the behavior better. Also, if there are no items divisible by three, you've got a malloced node back in the calling scope that never gets initialized, so it's a bit brittle in that regard. Thirdly, even with a parameter, it feels like a highly specific function without much reusability factor that could be written iteratively inside the calling scope like:
#include <stdio.h>
#include <stdlib.h>
typedef struct nodo
{
int num;
struct nodo *sig;
} nodo;
nodo *crear(nodo *registro, int num)
{
nodo *n = malloc(sizeof(nodo));
n->num = num;
n->sig = registro;
return n;
}
void mostrar(nodo *registro)
{
if (registro)
{
printf("%d->", registro->num);
mostrar(registro->sig);
}
else puts("");
}
void free_lista(nodo *registro)
{
if (registro)
{
free_lista(registro->sig);
free(registro);
}
}
int main()
{
nodo *prin = NULL;
nodo *prin_div_3 = NULL;
for (int t; scanf("%d", &t) && t != 1000;)
{
prin = crear(prin, t);
}
nodo *tmp = prin;
while (tmp)
{
if (tmp->num % 3 == 0)
{
prin_div_3 = crear(prin_div_3, tmp->num);
}
tmp = tmp->sig;
}
mostrar(prin);
mostrar(prin_div_3);
free_lista(prin);
free_lista(prin_div_3);
return 0;
}
This isn't perfect--without tail nodes, adding to the list is a bit less than ideal, but dangling heads are eliminated, and hopefully it shows an alternate approach to organizing program logic and functions.
A few other remarks:
Always free memory that you've allocated. You can write a simple recursive routine to do so, like free_lista as shown in the above example.
Consider avoiding highly specific functions with hard-coded values like 3 and 1000. Make these parameters to maximize reusability.
crear2 never uses the cont member, and you have global constants that are unused. It's a good idea to clean these up to help clarify your debugging efforts and reduce visual clutter.
No need to cast the result of malloc.
if (registro->sig !=NULL) as the first line of a function is going to crash on a null. You don't need != NULL either. if (registro) { ... } is clearest and avoids problems with null parameters.
void crear2 (nodo *registro, int cont, nodo *registroNuevo) {
if ((registro->num % 3) == 0) {
registroNuevo->num = registro->num;
registroNuevo->sig = (nodo*)malloc(sizeof(nodo));
if (registro->sig != NULL)
crear2(registro->sig, cont, registroNuevo->sig);
}
else {
if (registro->sig != NULL)
crear2(registro->sig, cont, registroNuevo);
}
}
This is my approach, but you are still getting a final unexpected 0 at the last mostrar() call; and you still need to do the 'free' calls. I think you should avoid the recursive calls, there are easier ways to do it. Saludos.

Inserting at the end of queue in C

I am trying to insert node at the end of queue and facing below error . This is simple fundamental error while compiling the code but making my life hard.
#include<stdio.h>
#include<stdlib.h>
typedef struct UNIX {
char str[20];
struct UNIX *next;
}examp;
examp *head=NULL;
int insert_last(char *s)
{
examp *new,*slide;
slide=head;
new = (examp *)malloc(sizeof(examp));
if(!new)
return(EXIT_FAILURE);
while(slide->next!=NULL)
slide=slide->next;
slide->next=new;
new->str=s;
new->next=NULL;
if(head==NULL)
{ head=new;
return 1;
}
return 1;
}
void display (void);
int main()
{
insert_last("hello ");
insert_last("how ");
insert_last("have ");
insert_last("you ");
insert_last("been ");
insert_last("! ");
display();
}
void display(void)
{
examp *slide;
slide=head;
while(slide->next!=NULL)
{ printf("%s ",slide->str);
slide=slide->next;
}
}
Error :stack_queue.c:27:10: error: assignment to expression with array type
new->str=s;
Update : Using strncpy reolved the error , but code is not working as expected and stopping unexpectedly.
You can't assign to a static array like that. Consider using strcpy or strncpy to copy the contents of the character string instead.
You cannot assign a string to an array! An array have its own memory, you can write or read elements in the array, but cannot assign an address.
You can eventually copy the string s contents to the array:
strncpy(new->str, s, 19);
new->str[19] = '\0'; //Close the string in case of overflow.
We used strncpy to limit the copied characters to the array size (19 chars + the ending '\0').
You can try it. Only replace in new->str=s; to strcpy(new->str, s); (ie. s will be copy in to new->str)
#include<stdio.h>
#include<stdlib.h>
typedef struct UNIX {
char str[20];
struct UNIX *next;
}examp;
examp *head=NULL;
int insert_last(char *s)
{
examp *new,*slide;
slide=head;
new = (examp *)malloc(sizeof(examp));
if(!new)
return(EXIT_FAILURE);
while(slide->next!=NULL)
slide=slide->next;
slide->next=new;
strcpy(new->str, s);
new->next=NULL;
if(head==NULL)
{ head=new;
return 1;
}
return 1;
}
void display (void);
int main()
{
insert_last("hello ");
insert_last("how ");
insert_last("have ");
insert_last("you ");
insert_last("been ");
insert_last("! ");
display();
}
void display(void)
{
examp *slide;
slide=head;
while(slide->next!=NULL)
{ printf("%s ",slide->str);
slide=slide->next;
}
}
As already stated you will have to use strcpy (or strncpy) in order to assign the string.
Asides from that I wanted to mention two things:
Do not forget to free your memory allocated by malloc. Create a method to free a single node (examp) then you can also provide a method to destroy the whole list.
I would suggest to rename the variable new to avoid confusion (pure C compiler may deal with it, but C/C++ compiler will most likely get into trouble).
Considering your update:
Take a look at the following line
while(slide->next!=NULL)
At this time slide does not even exist (it is NULL), still you perform an operation on the pointer. This is the reason why the program crashes.
Your error is in the first call insert_last("hello "):
int insert_last(char *s)
{
examp *new,*slide;
slide=head;
new = (examp *)malloc(sizeof(examp));
if(!new)
return(EXIT_FAILURE);
while(slide->next!=NULL)
slide=slide->next;
when you call it first time, head is NULL, so slide becomes NULL, but you don't check it, and call it in
while(slide->next!=NULL)
Here slide is null for the frst function call

Unable to create Adjacency List for an undirected Graph using C

I'm faced with a problem which I've been unable to tackle for quite some time.
I've been given a graph as follows,in a M x N matrix:
2 2
a b
a c
Note
I've interpreted the graph above as a matrix,only consisting of non-diagonal edges.
Here the first line represents values of M and N respectively.
The graph is only connected either along vertical,or adjacent direction,i.e.,up,down,left and right. diagonal edges not present.
In order to find the adjacency list of the graph(the desired output here):
a-b-c
b-a-c
c-a-b
Steps followed by me in the code:
1.Read M x N matrix into a 2D array.
2.Created a list of unique vertices of the graph as Unode[arrmax].
3.For each element of the matrix,if the character matches with an element of the unique vertices list,I've called the modify Adjacency List procedure that searches the neighbours of the concerned matrix vertex and populates/appends to the the Adjacency list if distinct nodes are found.
It takes as arguments, i,j,M,N,AdjList,number of elements in the list and makes the changes.
5.I've kept the list of nodes to be global for easy modification.
6.Next I intend to use the adjacency list produced to use in DFS procedure and find the DFS forest.
The Problem statement:
the input consists of a grid of size M X N. Each cell in the grid
contain a lower case letter of the English alphabet.In a natural way,
the cells are of two types: boundary cells and internal cells. Each
internal cell in the grid has four neighbours in one of the left,
right, top, down directions. A string of characters can be formed by
starting at any cell and traversing the grid through the neighbours.
You have to print all the possible strings subject to the following
constraints:
**No two characters in a string can be same
**No two strings can be same in the final output
**The strings should be printed in alphabetically sorted order.
INPUT:
First line contains two integers M and N
Next M lines contains N space separated characters each
OUTPUT:
Print all possible strings in sorted order and obeying the above constraints.
INPUT SIZE:
1 <= M, N <= 20
SAMPLE INPUT:
2 2
a b
a c
SAMPLE OUTPUT:
a ab abc ac acb b ba bc bca c ca cb cba
[UPDATE]:
Completely redesigned the code,used structures for the graph nodes,and one for handling indices.
Yet the result I'm getting:
a--b-a
b--a
a
c--a
My code[Relevant Portion]:
#include <stdio.h>
#include<stdlib.h>
#include<string.h>
#define ADJMAX 20
#define arrmax 400
typedef struct uniq_node{
char ch;
char AdjList[ADJMAX];
int numofelem;
int visited;
}unode;
unode Ulist[arrmax];
int uniq_tot=0;
typedef struct index
{
int i,j;
}Ind;
Ind indx;
int charcomp(char sch,char arr[],int arrlim);
void adjModify(unode*,char*,int,int,Ind);
int chIndex(int,int,int,int);
int main(void) {
int mvar,nvar;
char str[15],*token;
long integer;
/*To scan the values of M & N*/
scanf("%d %d\n",&mvar,&nvar);
int iter,iterv,jterv;
/*To create the character matrix of M x N*/
char cmat[mvar][nvar];
/*Initializing the unique nodes list*/
/*To read-in the matrix from the stdin:-A LOT OF HARD WORK*/
for(iterv=0;iterv<mvar;iterv++)
{
fgets(str,50,stdin);
jterv=0;
token=strtok(str," ");
while(token)
{
/*Assigning value to the character matrix*/
cmat[iterv][jterv]=*token;
/*Code to populate the list of unique elements*/
if(charcomp(*token,Ulist[uniq_tot].AdjList,uniq_tot)==3)
{
Ulist[uniq_tot].ch=*token;
uniq_tot++;
Ulist[uniq_tot].numofelem=1;
Ulist[uniq_tot].AdjList[0]=*token;
//Ulist[uniq_tot].visited=0;
}
jterv++;
token = strtok(NULL, " ");
}
}
/*To populate the adjacency lists */
char ch;
for(iterv=0;iterv<mvar;iterv++)
{
for(jterv=0;jterv<nvar;jterv++)
{
ch=cmat[iterv][jterv];
indx.i=iterv;
indx.j=jterv;
for(iter=0;iter<uniq_tot;iter++)
{
if(ch==Ulist[iter].ch)
break;
}
adjModify(&Ulist[iter],(char*)cmat,mvar,nvar,indx);
}
}
/*for(iter=0;iter<uniq_tot;iter++)
{
printf("%c",Ulist[iter].ch);
printf("\n%s\n",Ulist[iter].AdjList);
for(iterv=0;iterv<Ulist[iter].numofelem;iterv++)
{
printf("-%c",Ulist[iter].AdjList[iterv]);
}
printf("\n");
}*/
return 0;
}
int chIndex(int i,int j,int mvar,int nvar)
{
return (i>=0 && i<mvar && j>=0 && j<nvar);
}
void adjModify(unode* Unode,char* mat,int mvar,int nvar,Ind mind)
{
int idum,jdum;
if(chIndex(mind.i,mind.j-1,mvar,nvar))
{
idum=mind.i;
jdum=mind.j-1;
if(charcomp(*(mat+idum*nvar+jdum),Unode->AdjList,Unode->numofelem)==3)
{
++Unode->numofelem;
Unode->AdjList[Unode->numofelem]=*(mat+idum*nvar+jdum);
printf("\nI'm here in coord:(%d,%d), with element: %c, and AdjList: %s for character: %c",idum,jdum,*(mat+idum*nvar+jdum),Unode->AdjList,Unode->ch);
}
}
if(chIndex(mind.i,mind.j+1,mvar,nvar))
{
idum=mind.i;
jdum=mind.j+1;
if(charcomp(*(mat+idum*nvar+jdum),Unode->AdjList,Unode->numofelem)==3)
{
++Unode->numofelem;
Unode->AdjList[Unode->numofelem]=*(mat+idum*nvar+jdum);
printf("\nI'm here in coord:(%d,%d), with element: %c, and AdjList: %s for character: %c",idum,jdum,*(mat+idum*nvar+jdum),Unode->AdjList,Unode->ch);
}
}
if(chIndex(mind.i-1,mind.j,mvar,nvar))
{
idum=mind.i-1;
jdum=mind.j;
if(charcomp(*(mat+idum*nvar+jdum),Unode->AdjList,Unode->numofelem)==3)
{
++Unode->numofelem;
Unode->AdjList[Unode->numofelem]=*(mat+idum*nvar+jdum);
printf("\nI'm here in coord:(%d,%d), with element: %c, and AdjList: %s for character: %c",idum,jdum,*(mat+idum*nvar+jdum),Unode->AdjList,Unode->ch);
}
}
if(chIndex(mind.i+1,mind.j,mvar,nvar))
{
idum=mind.i+1;
jdum=mind.j;
if(charcomp(*(mat+idum*nvar+jdum),Unode->AdjList,Unode->numofelem)==3)
{
++Unode->numofelem;
Unode->AdjList[Unode->numofelem]=*(mat+idum*nvar+jdum);
printf("\nI'm here in coord:(%d,%d), with element: %c, and AdjList: %s for character: %c",idum,jdum,*(mat+idum*nvar+jdum),Unode->AdjList,Unode->ch);
}
}
}
/*Comparison routine*/
int charcomp(char fchar,char arr[],int ucindex)
{
int ivar;
for(ivar=0;ivar<ucindex;ivar++)
{
if(arr[ivar]==fchar)
return;
}
return 3;
}
I think you can skip creating individual nodes for every element in the 2D array. Having the 2D array implies a structured connectivity. When it starts getting large, traversing all these elements may become cumbersome.
My recommended approach would be the following:
Scan of the matrix and pull unique nodes. i.e. start with a scan and have the simple list a,b,c (you'll need to sort them).
Create a struct for each unique node consisting the number of paths you currently have and an array of char arrays to store each one in. i.e. char** myArray={{a},{ab},{abc},{ac},{acb}} would be the one for a (This is of course unknown when you start).
Loop through your unique nodes, and one by one find the location in the 2D array. Don't save them, just go through them one by one and do a scan function to look for all their paths.
The scan function should be recursive so it can go as far as it needs to while checking every possible path (recursive will help you check every direction at every node you traverse). Keep track of where you've been, and at ever step check that you have not already encountered that character.
When you can't go any further, make sure the string has not already been included, if it has continue to the next path, if not add it to the list.
this is my code in c++ without any library that can work in c but you just have to use in c printf instead of cout and instead of class use struct that's all. I also write code for breadth first traversal see below.
and include the header file also
// #include <stdio.h>
//#include<stdlib.h>
#include<iostream
using namespace std;
class Node {
public:
int data;
Node* next;
Node(int data) {
this->data=data;
this->next=NULL;
// cout<<"from node file"<<endl;
}
};
class Queue {
Node * head;
Node * tail;
int length;
public:
Queue() {
head=NULL;
tail=NULL;
length=0;
}
bool isEmpty() {
return length==0;
}
int size() {
return length;
}
int front() {
if(head==NULL) {
cout<<"Empty Queue"<<endl;
return 0;
}
return head->data;
}
void enqueue(int element) {
Node * newNode =new Node(element);
if(head==NULL) {
head=newNode;
tail=newNode;
}else{
tail->next=newNode;
tail=newNode;
}
length++;
}
int dequeue() {
if(head==NULL) {
cout<<"Empty queue"<<endl;
return 0;
}
int output= head->data;
Node * temp=head;
head=head->next;
temp->next=NULL;
delete temp;
length--;
return output;
}
};
class AdjList{
public:
Node * head;
AdjList() {
head=NULL;
//cout<<"from adlist"<<endl;
}
void add (int data) {
Node * newNode=new Node(data);
if(head==NULL) {
head=newNode;
}else {
Node* temp=head;
while(temp->next!=NULL) {
temp=temp->next;
}
temp->next=newNode;
}
}
};
class Graph{
public:
int v;
AdjList* adjList;
Graph(int v) {
this->v=v;
adjList=new AdjList[v];
}
void addEdge(int src, int dest) {
adjList[src].add(dest);
///for bidrectional add below code
//adjList[dest].add(src);
}
void print(){
for(int i=0;i<v;i++){
Node *temp = adjList[i].head;
cout << i << " -> ";
while(temp != NULL)
{
cout << temp->data << " ";
temp = temp->next;
}
cout << endl;
}
}
void bfs(int src) {
// using a queue also in this file how to add queue structure
Queue q;
bool* visited=new bool [v]{0};
q.enqueue(src);
visited[src]=true;
while(!q.isEmpty()) {
int node= q.front();
cout<<node<<" ";
q.dequeue();
Node *temp = adjList[node].head;
while(temp!=NULL){
if(!visited[temp->data]) {
q.enqueue(temp->data);
visited[temp->data]=true;
}
// cout<<"data "<<temp->data;
temp=temp->next;
/// how to traverse
}
}
}
};
int main(){
Graph g(6);
g.addEdge(0, 1);
g.addEdge(0, 2);
g.addEdge(1, 3);
g.addEdge(2, 3);
g.addEdge(3,4);
g.addEdge(4,5);
g.bfs(0);
// g.print();
return 0;
}

Inserting in Linked List

I'm having a small difficulty inserting a full sentence containing all characters in my string when I'm building a Linked List.
I would like to be able to insert a string like: word_#_2003_#_definition
But when I'm running my code in my main() method it continues repeating the choices to do like it never stops asking me to enter an option. Hope it's clear.
Here's my struct:
struct node
{
char data[100];
struct node *previous; // Points to the previous node
struct node *next; // Points out to the next node
} *head, *last;
Here's my function to insert a node:
void insert_beginning(char words[99])
{
struct node *var, *temp;
var=(struct node *)malloc(sizeof(struct node)); //explination about the (node *)
strncpy(var->data, words,99);
if (head==NULL)
{
head=var;
head->previous=NULL;
head->next=NULL;
last=head;
}
else
{
temp=var;
temp->previous=NULL;
temp->next=head;
head->previous=temp;
head=temp;
}
}
And this is in my main() method:
int main()
{
char loc[99];
char words[99];
int i, dat;
head=NULL;
printf("Select the choice of operation on link list");
printf("\n1.) Insert At Begning\n2.) Insert At End\n3.) Insert At Middle");
printf("\n4.) Delete From End\n5.) Reverse The Link List\n6.) Display List\n7.)Exit");
while(1)
{
printf("\n\n Enter the choice of operation you want to do ");
scanf("%d",&i);
switch(i)
{
case 1:
{
printf("Enter a word you want to insert in the 1st node ");
scanf(" %s",words);
insert_beginning(words);
display();
break;
}
Any ideas on how to do it?
The code is highly questionable:
return codes are never checked. You must check return codes,
especially if you are using scanf
You need to empty the whole buffer with scanf otherwise you will continue
reading old contents for the next command
A better alternative is to use sscanf
You must initialize your variables, for instance last, but there are additional
cases of variables that do not get initialized
Your data types are not consistently defined, this will create security problems
sometimes 99 characters and sometimes 100.
insert_beginning should not return void, the memory allocation can fail
Your code in main() should probably look more like:
int main()
{
char loc[99];
char words[99];
int i, dat;
head = NULL;
printf("Select the choice of operation on link list");
printf("\n1.) Insert At Beginning\n2.) Insert At End\n3.) Insert At Middle");
printf("\n4.) Delete From End\n5.) Reverse The Link List\n6.) Display List\n7.) Exit\n");
while(1)
{
printf("\nEnter the choice of operation you want to do: ");
if (scanf("%d", &i) != 1)
{
fprintf(stderr, "Failed to read a number: exiting\n");
return 1;
}
switch(i)
{
case 1:
{
printf("Enter a word you want to insert in the 1st node: ");
if (scanf("%98s", words) != 1)
{
fprintf(stderr, "Failed to read words; exiting\n");
return 1;
}
insert_beginning(words);
display();
break;
}
...
}
...
}
...
}
return 0;
}
As discussed in the comments, you are not checking the return status from scanf(), so you don't know when it is failing, and when it fails to read a number, it leaves the argument (i) alone, so you go back to the same option again, and rinse and repeat.
Elementary debugging techniques (not shown):
Print the values you get from your inputs. Print the value of i after the scanf() error checking. Print the value of words after the scanf() error checking.
Step through with a debugger.
Create a function to dump (print) your key data structures:
static void dump_data_structure(FILE *fp, char const *tag, data_structure const *data)
{
...code to dump the structure to the specified file stream,
...identified by tag (so you can tell which call it is you are looking at)
}
Use the structure dumper extensively while debugging. Keep it for use later when modifying the code. If done right, it can be enormously helpful.

Resources