Unexpected error in testing and learning about graphs in C - c

I have recently started to study this particular book for algorithms and data structure SkienaTheAlgorithmDesignManual.pdf, from which I've heard a lot of praise not only on the Internet,but from my Algorithms Design teacher as well at college,and I ended up having some errors with some code used from the book on page 153(on the book itself) or 165(pdf format).
Here's the code:
#include<stdio.h>
#include<stdbool.h>
#include<stdlib.h>
#define MAXV 1000
typedef struct {
int y;
int weight;
struct edgenode *next;
}edgenode;
typedef struct {
edgenode *edges[MAXV + 1];
int degree[MAXV + 1];
int nvertices;
int nedges;
bool directed;
}graph;
void initialize_graph(graph *g, bool directed);
void read_graph(graph *g, bool directed);
void insert_edge(graph *g, int x, int y, bool directed);
void print_graph(graph *g);
void initialize_graph(graph *g, bool directed) {
int i;
g->nvertices = 0;
g->nedges = 0;
g->directed = directed;
for (i = 1; i <= MAXV; i++) {
g->degree[i] = 0;
g->edges[i] = NULL;
}
}
void read_graph(graph *g, bool directed) {
int i;
int m;
int x, y;
initialize_graph(g, directed);
scanf("%d %d", &(g->nvertices), &m);
for (i = 1; i <= m; i++) {
scanf("%d %d", &x, &y);
insert_edge(g, x, y, directed);
}
}
void insert_edge(graph *g, int x, int y, bool directed) {
edgenode *p;
p = malloc(sizeof(edgenode));
p->weight = NULL;
p->y = y;
p->next = g->edges[x];
g->edges[x] = p;
g->degree[x]++;
if (directed == false)
insert_edge(g, y, x, true);
else
g->nedges++;
}
void print_graph(graph *g) {
int i;
edgenode *p;
for (i = 1; i <= g->nvertices; i++) {
printf("%d ", i);
p = g->edges[i];
while (p != NULL) {
printf(" %d", p->y);
p = p->next;
}
printf("\n");
}
}
main() {
bool directed = true;
graph *g;
read_graph(g, directed);
print_graph(g);
system("pause");
}
Here are the errors:
1>c:\users\dragos\source\repos\learninggraph\learninggraph\main.c(47): warning C4047: '=': 'int' differs in levels of indirection from 'void *'
1>c:\users\dragos\source\repos\learninggraph\learninggraph\main.c(49): warning C4133: '=': incompatible types - from 'edgenode *' to 'edgenode *'
1>c:\users\dragos\source\repos\learninggraph\learninggraph\main.c(65): warning C4133: '=': incompatible types - from 'edgenode *' to 'edgenode *'
1>c:\users\dragos\source\repos\learninggraph\learninggraph\main.c(73): error C4700: uninitialized local variable 'g' used
1>Done building project "LearningGraph.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
I think that the main problem is the "incompatible types",but I may be as very well be wrong.

In insert_edge
p->weight = NULL;
is invalid because weight is an int but NULL a pointer (typically (void*)0)
In insert_edge
p->next = g->edges[x];
is invalid because next is the undefined type struct edgenode * but edges[x] is edgenode *. To solve that you have to replace
typedef struct {
int y;
int weight;
struct edgenode *next;
}edgenode;
by
typedef struct edgenode {
int y;
int weight;
struct edgenode *next;
}edgenode;
The reason is the same in print_graph line
p = p->next;
Explicitly set the return type of main as int
In main you call read_graph with g never set/initialized so when it is dereferenced in read_graph the behavior is undefined, and this is also the case in print_graph. Just replace
graph *g;
read_graph(g, directed);
print_graph(g);
by
graph g;
read_graph(&g, directed);
print_graph(&g);
Full modified version :
#include <stdlib.h>
#include<stdio.h>
#include<stdbool.h>
#define MAXV 1000
typedef struct edgenode {
int y;
int weight;
struct edgenode *next;
}edgenode;
typedef struct {
edgenode *edges[MAXV + 1];
int degree[MAXV + 1];
int nvertices;
int nedges;
bool directed;
}graph;
void initialize_graph(graph *g, bool directed);
void read_graph(graph *g, bool directed);
void insert_edge(graph *g, int x, int y, bool directed);
void print_graph(graph *g);
void initialize_graph(graph *g, bool directed) {
int i;
g->nvertices = 0;
g->nedges = 0;
g->directed = directed;
for (i = 1; i <= MAXV; i++) {
g->degree[i] = 0;
g->edges[i] = NULL;
}
}
void read_graph(graph *g, bool directed) {
int i;
int m;
int x, y;
initialize_graph(g, directed);
scanf("%d %d", &(g->nvertices), &m);
for (i = 1; i <= m; i++) {
scanf("%d %d", &x, &y);
insert_edge(g, x, y, directed);
}
}
void insert_edge(graph *g, int x, int y, bool directed) {
edgenode *p;
p = malloc(sizeof(edgenode));
p->weight = 0;
p->y = y;
p->next = g->edges[x];
g->edges[x] = p;
g->degree[x]++;
if (directed == false)
insert_edge(g, y, x, true);
else
g->nedges++;
}
void print_graph(graph *g) {
int i;
edgenode *p;
for (i = 1; i <= g->nvertices; i++) {
printf("%d ", i);
p = g->edges[i];
while (p != NULL) {
printf(" %d", p->y);
p = p->next;
}
printf("\n");
}
}
int main() {
bool directed = true;
graph g;
read_graph(&g, directed);
print_graph(&g);
system("pause");
}
Compilation :
pi#raspberrypi:/tmp $ gcc -pedantic -Wall -Wextra g.c
pi#raspberrypi:/tmp $

You never allocated any memory for graph *g.
There's no need for this to be a pointer, make it a normal variable and pass its address to the functions.
int main() {
bool directed = true;
graph g;
read_graph(&g, directed);
print_graph(&g);
system("pause");
}

Related

Breadth First Search or BFS for a Graph

Based on the BFS algorithm, I am required to write a function SD() to find the shortest distance from vertex $v$ to $w$, in an undirected graph. Vertices ranged from 1 to $|V|$. The distance is measured by the number of edges. If there is no path from $v$ to $w$, then -1 is returned. You may assume that the input graph is always valid (no duplicate or any invalid link, etc.). The function prototype is given as follows:
int SD (Graph G, int v, int w);
For the sample input and output below, my code outputs 1 instead of 2 and I don't know what I'm doing wrong, more like I don't know what I am doing at this point, help would be appreciated thank you! (Please refer to the int SD(Graph g, int v, int z) section of the code below).
#include <stdio.h>
#include <stdlib.h>
typedef struct _listnode
{
int vertex;
struct _listnode *next;
} ListNode;
typedef struct _graph{
int V;
int E;
int *visited;
int **matrix;
}Graph;
typedef ListNode QueueNode;
typedef struct _queue{
int size;
QueueNode *head;
QueueNode *tail;
} Queue;
int SD (Graph G, int v, int w);
void printGraphMatrix(Graph );
// You should not change the prototypes of these functions
void enqueue(Queue *qPtr, int item);
int dequeue(Queue *qPtr);
int getFront(Queue q);
int isEmptyQueue(Queue q);
void removeAllItemsFromQueue(Queue *qPtr);
int main()
{
Graph g;
int i,j;
printf("Enter the number of vertices:\n");
scanf("%d",&g.V);
g.E = 0;
g.matrix = (int **)malloc(g.V*sizeof(int *));
for(i=0;i<g.V;i++)
g.matrix[i] = (int *)malloc(g.V*sizeof(int));
for(i=0;i<g.V;i++)
for(j=0;j<g.V;j++)
g.matrix[i][j] = 0;
g.visited = (int *) malloc(sizeof(int)*g.V);
for(i=0;i<g.V;i++) g.visited[i] = 0;
int V1, V2;
printf("Enter two vertices which are adjacent to each other:\n");
while(scanf("%d %d",&V1,&V2)==2)
{
if(V1>0 && V1<=g.V && V2>0 && V2<=g.V)
{
g.matrix[V1-1][V2-1] = 1;
g.matrix[V2-1][V1-1] = 1;
g.E++;
}
else
break;
printf("Enter two vertices which are adjacent to each other: (press a to stop)\n");
}
scanf("%*c");
// printGraphMatrix(g);
printf("Enter two vertices for finding their shortest distance: (press a to stop)\n");
scanf("%d %d", &i, &j);
int d = SD(g,i,j);
if(d==-1)
printf("%d and %d are unconnected.\n",i,j);
else
printf("The shortest distance is %d\n",d);
return 0;
}
int SD(Graph g, int v, int z){
int * distance;
distance = (int *) malloc(sizeof(int)*g.V);
// Initialize distances
for(int i = 0; i < g.V; i++)
{
distance[i] = -1;
}
// queue to do BFS.
Queue q;
q.size = 0;
q.head = NULL;
q.tail = NULL;
int w;
int i;
enqueue(&q,v);
distance[v-1] = distance[v-1] + 1;
g.visited[v-1] = 1;
while(isEmptyQueue(q)==0){
w = dequeue(&q);
for(i=0;i<g.V;i++)
{
if(g.matrix[w-1][i] == 1 && g.visited[i]==0)
{
g.visited[i]=1;
distance[i] = distance[i] + 3;
enqueue(&q,i+1);
}
}
}
if(z <= g.V) return distance[z-1];
return -1;
}
void printGraphMatrix(Graph g)
{
int i,j;
for(i=0;i<g.V;i++){
for(j=0;j<g.V;j++)
printf("%d\t",g.matrix[i][j]);
printf("\n");
}
}
void enqueue(Queue *qPtr, int item) {
QueueNode *newNode;
newNode = malloc(sizeof(QueueNode));
if(newNode==NULL) exit(0);
newNode->vertex = item;
newNode->next = NULL;
if(isEmptyQueue(*qPtr))
qPtr->head=newNode;
else
qPtr->tail->next = newNode;
qPtr->tail = newNode;
qPtr->size++;
}
int dequeue(Queue *qPtr) {
if(qPtr==NULL || qPtr->head==NULL){ //Queue is empty or NULL pointer
return 0;
}
else{
int headValue = qPtr->head->vertex;
QueueNode *temp = qPtr->head;
qPtr->head = qPtr->head->next;
if(qPtr->head == NULL) //Queue is emptied
qPtr->tail = NULL;
free(temp);
qPtr->size--;
return headValue;
}
}
int getFront(Queue q){
return q.head->vertex;
}
int isEmptyQueue(Queue q) {
if(q.size==0) return 1;
else return 0;
}
void removeAllItemsFromQueue(Queue *qPtr)
{
while(dequeue(qPtr));
}

Issue with linked list and truth table

So I'm trying to print the truth table of a gate with n inputs using linked lists. I tried the following but I'm running into a problem. If I use the for loops with bincombs, to print all possible combinations and to calculate the result, on both report and myandlst as shown below, it crashes. The problem is easily fixed if I print everything in myandlst but I want to avoid it. Here is my code so far:
#include <stdio.h>
#include <stdlib.h>
typedef struct data
{
int value;
struct data * next;
} Data;
typedef Data * DataList;
typedef int (*CallBack)(DataList *inlist, int n);
int report(CallBack f, int n);
int getbit(int x, int p);
void bincombs(int * x, int n);
int myandlst(DataList *list, int n);
int main( )
{
CallBack f ;
report(myandlst, 4);
return 0;
}
int getbit(int x, int p)
{
return (x & (1<<p))!=0;
}
void bincombs(int * x, int n)
{
static int state = 0 ;
int i;
for (i=0; i<n; i++)
{
*x = getbit (state, i);
x++;
}
state ++;
return;
}
Data * createData( int value)
{
Data * dataptr;
dataptr = malloc(sizeof (Data));
dataptr->value = value;
dataptr->next = NULL;
return dataptr;
}
void appendData(DataList *lstptr, Data *newptr)
{
if (*lstptr==NULL)
{
*lstptr = newptr;
return;
}
appendData( &((*lstptr)->next), newptr);
return;
}
int myandlst (DataList *inlist, int n)
{
int i,j,k;
int * x = malloc (n*sizeof(int));
k=1;
for (i=0; i< (1<<n) ; i++)
{
bincombs(x, n);
for (j=n-1; j>=0; j--)
{
k*=x[j];
}
appendData(inlist,createData(k));
k=1;
}
return 0;
}
int report(CallBack f, int n)
{
DataList temp ;
int * x = malloc (n*sizeof(int));
int i,j;
f(&temp, n);
for (i=0; i< (1<<n) ; i++)
{
bincombs(x, n);
for (j=n-1; j>=0; j--)
printf("%d ", x[j]);
printf("%d\n", temp -> value);
temp = temp->next;
}
printf("\n");
return 0;
}
P.S This is an assignment and therefore the structure of the program is standard. I can't avoid using linked lists or changing the format of the functions too much.

Unexpected output of function in C

With an input of an integer 4, for example, I'm trying to get the following output w/ the initializePoly function.
(0, 0)
(-1, 1)
(-2, 4)
(-3, 9)
Instead, I'm getting all 0s in the outputs' second value when I run the code. Any feedback much appreciated.
#include <stdio.h>
#include <stdlib.h>
struct point{
int x;
int y;
};
void printPoint(struct point);
void printPoly(struct point *, int);
void initializePoly(struct point *, int);
int main(void) {
// Fill in your main function here
struct point * polygon;
int num;
scanf("%d", &num);
polygon = (struct point *) malloc(num * sizeof(struct point));
initializePoly(polygon, num);
printPoly(polygon, num);
free(polygon);
}
void printPoint(struct point pt) {
printf("(%d, %d)\n", pt.x, pt.y);
}
void printPoly(struct point *ptr, int N) {
int i;
for (i=0; i<N; i++) {
printPoint(ptr[i]);
}
}
// Write your initializePoly() function here
void initializePoly(struct point *pt, int num){
int i;
for(i=0;i<num;i++)
pt[i].x = -i;
pt[i].y = i*i;
}
void initializePoly(struct point *pt, int num){
int i;
for(i=0;i<num;i++)
pt[i].x = -i;
pt[i].y = i*i;
}
same as
void initializePoly(struct point *pt, int num){
int i;
for(i=0;i<num;i++) {
pt[i].x = -i;
}
pt[i].y = i*i;
}
Use {} to iterate both assignments.
void initializePoly(struct point *pt, int num){
int i;
for(i=0;i<num;i++) {
pt[i].x = -i;
pt[i].y = i*i;
}
}

Struct of Matrices C

I have this struct:
typedef struct {
int n;
bool **a;
bool **b;
bool **c;
} matrices_struct;
Then I want to assign a matrix a for a given struct:
void multiplyMatrix(int n, int numOfThreads, bool a[n][n], bool b[n][n], bool c[n][n]){
...
matrices_struct *ms = malloc(sizeof(*ms));
ms->a = a; //doesn't work
...
}
Is it possible to achieve this?
Ok, so I have managed to solve this problem like this:
struct:
typedef struct {
int n;
bool *a;
bool *b;
bool *c;
} matrices_struct;
function:
void multiplyMatrix(int n, int numOfThreads, bool *a, bool *b, bool *c){
...
for(int i = 0; i < numOfThreads; i++){
matrices_struct *ms = malloc(sizeof(*ms));
ms->n = n;
ms->a = a;
ms->b = b;
ms->c = c;
...
}
}
}
function call:
...
bool a[size][size];
bool b[size][size];
bool c[size][size];
fillMatrix(size, a);
fillMatrix(size, b);
multiplyMatrix(size, numOfThreads, *a, *b, *c);
...

C: Value of variable changing without re-assignment

I am implementing Kruskal's algorithm.
After I call graph() in the following code, the value of nodes change. I'm not quite sure why -- if anyone could clear this up I would greatly appreciate it. I'm not accessing the value of nodes from within graph, and both nodes & edges, the array being accessed, are allocated outside of the stack!
struct node {
int parent, rank;
};
typedef struct node node;
struct edge {
int fromvertex, tovertex;
float weight;
};
typedef struct edge edge;
node* nodes;
edge* edges;
typedef enum {Unvisited, Visited} vertexstate;
int main (int argc, char const *argv[])
{
void getcount(int*, int*);
void graph(int, int);
void makeset(int);
int hasspantree(int, int, int);
void kruskal(int, int);
int printmcst(int);
int nodecount, edgecount, i, totalcost=0;
getcount(&nodecount, &edgecount);
for (i = 1; i <= nodecount; i++)
makeset(i);
printf("%d \t %d\n", nodes[6].parent, nodes[6].rank );
graph(nodecount, edgecount);
printf("%d \t %d\n", nodes[6].parent, nodes[6].rank );
printf("Has a spanning tree?");
if(hasspantree(1, nodecount, edgecount)) {
printf("\t Yes.\n");
kruskal(nodecount, edgecount);
printf("MCST found:\n\n");
totalcost = printmcst(nodecount);
printf("\nCost: %d", totalcost);
}
else {
printf("No.");
exit(0);
}
return 0;
}
void graph(int nodecount, int edgecount)
{
for (int i = 0; i < edgecount; i++) {
scanf("%d", &edges[i].fromvertex);
scanf("%d", &edges[i].tovertex);
scanf("%f", &edges[i].weight);
}
}
void getcount(int *nodecount, int *edgecount)
{
scanf("%d", nodecount);
scanf("%d", edgecount);
nodes = malloc(*nodecount * sizeof(node));
edges = malloc(*edgecount * sizeof(edge));
}
void makeset(int x)
{
nodes[x].parent = x;
nodes[x].rank = 0;
}
one obvious error is accessing the nodes array starting at index 1 instead of 0 and this would cause buffer overrun when you access the last element
for (i = 1; i <= nodecount; i++) <-- here i should start at 0 and access only up to nodecount-1
makeset(i);

Resources