C program for dijiktras shortest path not working [duplicate] - c

This question already has answers here:
What is a debugger and how can it help me diagnose problems?
(2 answers)
How Can I debug a C program on Linux?
(4 answers)
Closed 1 year ago.
I have to build a program which takes in the vertices and edges from a csv file and uses an adjacency matrix to store the distance from one vertex to another and calls the function shortest_path which uses the dijkstra's algorithm to find the shortest path and calls the printpath function to print the information of all the vertices it goes through to get from the origin to the end.The information about the vertices is stored in the array of structures arr[].
The problem is that the program stops working when main() call the shortest_path() and the return value is 3221225725
The shortest_path function runs on its own in another program I made but is not called in the main when I execute this program
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_BUFFER 100
#define MAX_NB 8000
#define INFINITY 9999
typedef struct edges edges;
struct edges{
int from,to,weight;
};
typedef struct stops stops;
struct stops {
int id;
float lat,lont;
char title[MAX_BUFFER];
};
stops* arr[MAX_NB]={0};
typedef struct Graph{
int vertices;
// int visited;
} Graph;
int visited[MAX_NB];
int amatrix[MAX_NB][MAX_NB];
int n;
Graph* create_graph(int num_nodes){
Graph* g = (Graph *)malloc(sizeof(struct Graph));
g->vertices=num_nodes;
int i,j;
for(i=0;i<num_nodes;i++){
for(j=0;j<num_nodes;j++){
amatrix[i][j]=0;
}
}
n=num_nodes;
return g;
}
Graph *graph;
int next_field( FILE *f, char *buf, int max ) {
int i=0, end=0, quoted=0;
for(;;) {
// fetch the next character from file
buf[i] = fgetc(f);
// if we encounter quotes then flip our state and immediately fetch next char
if(buf[i]=='"') { quoted=!quoted; buf[i] = fgetc(f); }
// end of field on comma if we're not inside quotes
if(buf[i]==',' && !quoted) { break; }
// end record on newline or end of file
if(feof(f) || buf[i]=='\n') { end=1; break; }
// truncate fields that would overflow the buffer
if( i<max-1 ) { ++i; }
}
buf[i] = 0; // null terminate the string
return end; // flag stating whether or not this is end of the line
}
void fetch_stops ( FILE *csv, struct stops *p) {
char buf[MAX_BUFFER];
next_field( csv, buf, MAX_BUFFER );
p->id = atoi(buf);
next_field( csv, p->title, MAX_BUFFER );
next_field( csv, buf, MAX_BUFFER );
p->lat = atof(buf);
next_field( csv, buf, MAX_BUFFER );
p->lont = atof(buf);
}
void fetch_edges ( FILE *csv, struct edges *p) {
char buf[MAX_BUFFER];
next_field( csv, buf, MAX_BUFFER );
p->from = atoi(buf);
next_field( csv, buf, MAX_BUFFER );
p->to = atoi(buf);
next_field( csv, buf, MAX_BUFFER );
p->weight = atoi(buf);
}
void print_stops( struct stops *p ) {
printf("%d \t \t %s \t %f %f\n",
p->id,p->title, p->lat, p->lont);
}/*
void print_edges( struct edges *p ) {
printf("%d \t \t %d \t %d\n",
p->from,p->to, p->weight);
}
*/
int load_vertices(char *fname){
FILE *f;
struct stops pArray[MAX_NB];
struct stops p;
f=fopen(fname,"r");
if(!f) {
printf("unable to open file\n");
return 0;
}
fetch_stops( f, &p ); // discard the header data in the first line
int ngames = 0;
while(!feof(f)) {
fetch_stops( f, &pArray[ngames]);
arr[ngames]=&pArray[ngames];
ngames++;
}
printf("loaded %d vertices\n",ngames);
fclose(f);
graph = create_graph(ngames);
return 1;
}
void add_edge(int from, int to, int weight){
amatrix[from][to]=weight;
amatrix[to][from]=weight;
}
int load_edges(char *fname/*,Graph *g*/){
FILE *f;
struct edges pArray[MAX_NB];
struct edges p;
f=fopen(fname,"r");
if(!f) {
printf("unable to open file\n");
return 0;
}
fetch_edges( f, &p ); // discard the header data in the first line
int nedges = 0;
int from,to,weight;
while(!feof(f)) {
fetch_edges( f, &pArray[nedges]);
nedges++;
}
int i;
for(i=0;i<nedges;i++){
add_edge(pArray[i].from,pArray[i].to,pArray[i].weight);
}
printf("loaded %d edges\n",nedges);
fclose(f);
return 1;
}
void printpath(int parent[], int u){
// Base Case : If j is source
if (parent[u] == - 1)
return;
printpath(parent, parent[u]);
printf("%d %s\n", arr[u]->id, arr[u]->title);
}
void shortest_path(int origin, int end){
printf("Works1");
int distance[MAX_NB];
int pred[MAX_NB];
int cost[MAX_NB][MAX_NB];
int count,minD,nextn,i,j;
pred[0]=-1;
int n=MAX_NB;
printf("Works2");
for (i = 0; i < n; i++){
for (j = 0; j < n; j++){
if (amatrix[i][j] == 0)
cost[i][j] = INFINITY;
else
cost[i][j] = amatrix[i][j];
}
}
for (i = 0; i <n; i++) {
distance[i] = cost[origin][i];
}
printf("Works1");
distance[origin] = 0;
printf("Works2");
visited[origin] = 1;
count = 1;
while (count < n - 1) {
minD = INFINITY;
for (i = 0; i < n; i++){
if ((distance[i] < minD) && (visited[i])!=1) {
minD = distance[i];
nextn = i;
}}
visited[nextn] = 1;
for (i = 0; i < n; i++)
if (!(visited[i]))
if (minD + cost[nextn][i] < distance[i]) {
distance[i] = minD + cost[nextn][i];
pred[i]=nextn;
}
count++;
}
printf("Works");
printpath(pred,end);
}
int main () {
load_vertices("vertices.csv");
load_edges("edges.csv")
printf("%d",amatrix[300][7490]);
shortest_path(300,253);
return EXIT_SUCCESS;
}

Related

How to Combine 2 Struct arrays in C

iv tried a lot of solutions to try to get this working (i.e using memcpy etc) I cant seem to find the issue, depending on what I try I either end up with gibberish or SEGV
iv spent a lot of time already googling and trying different ways, i still cant figure out why the arrays won't combine successfully
#include <stdio.h>
#include <stdint.h>
#include <dirent.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/syscall.h>
#include <unistd.h>
#define log_info printf
typedef struct
{
char* name;
//size_t size;
} entry_t;
/* qsort struct comparison function (C-string field) */
static int struct_cmp_by_name(const void* a, const void* b)
{
entry_t* ia = (entry_t*)a;
entry_t* ib = (entry_t*)b;
return strcmp(ia->name, ib->name);
/* strcmp functions works exactly as expected from comparison function */
}
entry_t* get_item_entries(const char* dirpath, int* count)
{
struct dirent* dent;
char buffer[512]; // fixed buffer
int dfd = 0,
n, r = 1; // item counter, rounds to loop
entry_t* p = NULL; // we fill this struct with items
loop:
n = 0;
printf("loop: %d, count:%d\n", r, *count);
// try to open dir
dfd = open(dirpath, O_RDONLY, 0);
if (dfd < 0)
{
printf("Invalid directory. (%s)\n", dirpath);
*count = -1;
return NULL;
}
else
{
printf("open(%s)\n", dirpath);
}
memset(buffer, 0, sizeof(buffer));
while (syscall(SYS_getdents, dfd, buffer, sizeof(buffer)) != 0)
{
dent = (struct dirent*)buffer;
while (dent->d_fileno)
{ // skip `.` and `..`
if (!strncmp(dent->d_name, "..", 2)
|| !strncmp(dent->d_name, ".", 1)) goto skip_dent;
// deal with filtering outside of this function, we just skip .., .
switch (r)
{ // first round: just count items
case 1:
{
// skip special cases
if (dent->d_fileno == 0) goto skip_dent;
break;
}
// second round: store filenames
case 0: p[n].name = strdup(dent->d_name); break;
}
n++;
skip_dent:
dent = (struct dirent*)((void*)dent + dent->d_reclen);
if (dent == (void*)&buffer[512]) break; // refill buffer
}
memset(buffer, 0, sizeof(buffer));
}
close(dfd);
// on first round, calloc for our list
if (!p)
{ // now n holds total item count, note it
p = calloc(n, sizeof(entry_t));
*count = n;
}
// first round passed, loop
r--; if (!r) goto loop;
// report count
printf("%d items at %p, from 1-%d\n", *count, (void*)p, *count);
/* resort using custom comparision function */
qsort(p, *count, sizeof(entry_t), struct_cmp_by_name);
// report items
//for (int i = 0; i < num; ++i) log_error( "%s", p[i].name);
return p;
}
int main(int argc, char* argv[])
{
int HDD_count = -1;
uint32_t total = -1;
int ext_count = -1;
entry_t* e = NULL;
entry_t *HDD = get_item_entries("/mnt/f/n", &HDD_count);
entry_t* ext = get_item_entries("/mnt/f/dls", &ext_count);
total = ext_count + HDD_count;
e = (entry_t*)malloc(sizeof *e * total);
if (e != NULL)
{
for (int i = 1; i < HDD_count; i++)
{
log_info("HDD[%i].name %s\n", i, HDD[i].name);
e[i].name = strdup(HDD[i].name);
}
for (int i = 1; i < ext_count; i++)
{
log_info("ext[%i].name %s\n", i, ext[i].name);
e[i + HDD_count].name = strdup(ext[i].name);
}
}
else
printf("Failed to Allocate the Array");
char tmp[256];
int i = 1, j;
for(j = 1; j <= total; j++)
{
snprintf(&tmp[0], 255, "%s", e[ j].name);
log_info("%i:%s\n", j , tmp);
}
return 0;
}
Here is a rewrite of a snippet of main() that I mentioned in my comment above:
#define CHECK(p, msg) if(!(p)) { printf("%s:%d: %s", __FILE__, __LINE__, msg); return 1;}
...
entry_t *HDD = get_item_entries("/mnt/f/n", &HDD_count);
CHECK(HDD, "HDD failed to get entries");
entry_t *ext = get_item_entries("/mnt/f/dls", &ext_count);
CHECK(ext, "ext failed to get entries");
uint32_t total = HDD_count + ext_count;
entry_t *e = malloc(total * sizeof(*e));
CHECK(e, "malloc failed");
for(int i = 0; i < HDD_count; i++) {
log_info("HDD[%i].name %s\n", i, HDD[i].name);
e[i].name = strdup(HDD[i].name);
}
// write a function instead of duplicating code?
for (int i = 0; i < ext_count; i++) {
log_info("ext[%i].name %s\n", i, ext[i].name);
e[HDD_count + i].name = strdup(ext[i].name);
}
It looks like a short lived program, but I would still free the values from strdup() and e itself.

Solving Maze Using BFS in C - Segmentation fault

I am attempting to solve a maze using BFS, but I am getting a segmentation fault. Can anyone help me figure out why this is happening? Also if you see anything else wrong with my code? my if statements are to check if the point exists in the maze and that there is a white space at the point. I also am solving the maze using DFS, but the seg fault happens during solve_bfs. Also, everything except solve.c was given to my professor, so the only thing I am suppose to edit is solve.c
Solve.c
#include <stdio.h>
#include <stdlib.h>
#include "maze.h"
#include "stack.h"
#include "queue.h"
int solve_bfs(maze * the_maze){
Queue Q= initQueue();
enqueue(Q, the_maze->entry);
while(!emptyQueue(Q)){
coord to_explore= dequeue(Q);
if(to_explore.row == the_maze->exit.row && to_explore.col == the_maze->exit.col){
print_maze(the_maze);
free(Q);
return 1;
}
else{
the_maze->data[to_explore.row][to_explore.col]= 'o';
if(to_explore.row-1 >= 0){
if(the_maze->data[to_explore.row-1][to_explore.col] == ' '){
coord new;
new.row= to_explore.row-1;
new.col= to_explore.col;
enqueue(Q, new);
}
}
if(to_explore.col+1 < the_maze->width){
if(the_maze->data[to_explore.row][to_explore.col+1]== ' '){
coord new;
new.row= to_explore.row;
new.col= to_explore.col+1;
enqueue(Q, new);
}
}
if(to_explore.row+1 < the_maze->height){
if(the_maze->data[to_explore.row+1][to_explore.col]== ' '){
coord new;
new.row= to_explore.row+1;
new.col= to_explore.col;
enqueue(Q, new);
}
}
if(to_explore.col-1 >= 0) {
if(the_maze->data[to_explore.row][to_explore.col-1]== ' '){
coord new;
new.row= to_explore.row;
new.col= to_explore.col-1;
enqueue(Q, new);
}
}
}
if(emptyQueue(Q)){
print_maze(the_maze);
free(Q);
return 0;
}
}
}
int solve_dfs(maze * the_maze){
Stack s= initStack();
push(s, the_maze->entry);
while(!emptyStack(s)){
coord to_explore= pop(s);
if(to_explore.row == the_maze->exit.row && to_explore.col == the_maze->exit.col){
print_maze(the_maze);
free(s);
return 1;
}
else{
if(to_explore.row-1 >= 0){
if(the_maze->data[to_explore.row-1][to_explore.col]== ' '){
coord new;
new.row= to_explore.row-1;
new.col= to_explore.col;
push(s, new);
}
}
if(to_explore.col+1 < the_maze->width){
if(the_maze->data[to_explore.row][to_explore.col+1]== ' '){
coord new;
new.row= to_explore.row;
new.col= to_explore.col+1;
push(s, new);
}
}
if(to_explore.row+1 < the_maze->height){
if(the_maze->data[to_explore.row+1][to_explore.col]== ' '){
coord new;
new.row= to_explore.row+1;
new.col= to_explore.col;
push(s, new);
}
}
if(to_explore.col-1 >= 0){
if(the_maze->data[to_explore.row][to_explore.col-1]== ' '){
coord new;
new.row= to_explore.row;
new.col= to_explore.col-1;
push(s, new);
}
}
}
if(emptyStack(s)){
print_maze(the_maze);
free(s);
return 0;
}
}
}
void print_maze(maze * the_maze){
the_maze->data[the_maze->entry.row][the_maze->entry.col]='S';
the_maze->data[the_maze->exit.row][the_maze->exit.col]='F';
for(int i=0; i<the_maze->width; i++){
for(int j=0; j<the_maze->height; j++){
printf("%s",the_maze->data[i][j]);
}
}
}
coord * make_coord(int r, int c){
coord * coord= malloc(sizeof(coord));
coord->row = r;
coord->col = c;
return coord;
}
void print_coord(coord c){
printf("(%d,%d)",c.row, c.col);
}
Maze.c
#include <stdio.h>
#include <stdlib.h>
#include "maze.h"
/**********************************************************
create_maze
creates a new maze from the input file characters
*********************************************************/
maze * create_maze(FILE *in) {
// create maze
maze * new_maze = (maze *) malloc(sizeof(maze));
// read first line of in
int start_row;
int start_col;
int end_row;
int end_col;
int num_rows;
int num_cols;
// start line
char * line = malloc(sizeof(char)*100); // start buffer out at 100
size_t num_read;
getline(&line, &num_read, in);
if(sscanf(line, "%d %d %d %d %d %d", &num_rows, &num_cols, &start_row, &start_col, &end_row, &end_col) != 6) {
fprintf(stderr, "Maze file format invalid. Top line must include 6 numbers.\n");
return NULL;
}
// if any are negative values, return NULL
if(start_row < 0 || start_col < 0 || end_row < 0 || end_col < 0 || num_rows < 0 || num_cols < 0) {
fprintf(stderr, "Maze file format invalid. Maze file numbers in first row must be non-negative.\n");
return NULL;
}
// make sure start_row is in bounds
if(start_row >= num_rows) {
fprintf(stderr, "Maze file format invalid. Start row must be < num rows in maze.\n");
return NULL;
}
// make sure end_row is in bounds
if(end_row >= num_rows) {
fprintf(stderr, "Maze file format invalid. End row must be < num rows in maze.\n");
return NULL;
}
// make sure start_col is in bounds
if(start_col >= num_cols) {
fprintf(stderr, "Maze file format invalid. Start col must be < num cols in maze.\n");
return NULL;
}
// make sure end_col is in bounds
if(end_col >= num_cols) {
fprintf(stderr, "Maze file format invalid. Start col must be < num cols in maze.\n");
return NULL;
}
// assign maze members
new_maze->entry.row = start_row;
new_maze->entry.col = start_col;
new_maze->exit.row = end_row;
new_maze->exit.col = end_col;
new_maze->width = num_cols;
new_maze->height = num_rows;
// allocate memory for maze data
new_maze->data = (char **) malloc(sizeof(char *)*num_rows);
int i;
for(i=0; i<num_rows; i++) {
new_maze->data[i] = (char *) malloc(sizeof(char)*num_cols);
}
// get characters from file, one line at a time
size_t num_vals_read = 0;
for(i=0; i<num_rows; i++) {
num_vals_read = getline(&line, &num_read, in);
if(num_vals_read != num_cols + 1) { //account for newline character
fprintf(stderr, "Maze file format invalid. Found %d chars on line %d and the width is %d.\n",
(num_vals_read-1), i, new_maze->width);
return NULL;
}
// parse out line
int j;
for(j=0; j<num_cols; j++) {
if(line[j] != ' ' && line[j] != '*') {
fprintf(stderr, "Maze file format invalid. Maze file data must contain spaces and stars. Read %c.\n", line[j]);
return NULL;
}
new_maze->data[i][j] = line[j];
}
}
// try to read more data
char c;
if((c = fgetc(in)) != EOF) {
fprintf(stderr, "Maze file format invalid. Too many characters past %d rows.\n", num_rows);
return NULL;
}
free(line);
return new_maze;
}
/******************************************************
free_maze
frees memory used by the_maze
******************************************************/
void free_maze(maze * the_maze) {
// first free the data
// need to free rows of data, then data
int i;
for(i = 0; i < the_maze->height; i++) {
free(the_maze->data[i]);
}
free(the_maze->data);
free(the_maze);
return;
}
Queue.c
#include <stdio.h>
#include <stdlib.h>
#include "queue.h"
/* initializes empty queue */
Queue initQueue() {
Queue q = malloc(sizeof(QueueType));
q->head = 0;
q->tail = 0;
return q;
}
/* returns 1 if queue is empty and 0 otherwise */
int emptyQueue(Queue Q) {
return (Q->head == Q->tail);
}
/* puts data item d into queue */
void enqueue(Queue Q, QueueData d) {
if(full(Q)) {
printf("Queue is full. Did not add item.\n");
return;
}
Q->tail++;
Q->tail = Q->tail % MAX_Q; // in case it goes off array
Q->data[Q->tail] = d;
}
/* removes data item from queue */
QueueData dequeue(Queue Q) {
if(emptyQueue(Q)) {
printf("Attempting to remove from empty queue\n");
exit(1);
}
Q->head++;
Q->head = Q->head % MAX_Q; // in case it goes off array
return Q->data[Q->head];
}
/* checks if queue is full */
int full(Queue Q) {
return (Q->tail + 1) % MAX_Q == Q->head;
}
/* freeQueue */
void freeQueue(Queue Q) {
free(Q);
}
Main.c
#include <stdio.h>
#include <stdlib.h>
#include "maze.h"
#define NUM_PARAMS 2
/* prototypes */
void usage(char * executable);
/***********************************************************************
* main
executable_name input_filename.txt
opens input_filename.txt for reading
creates maze object
runs the maze solver
frees maze
*********************************************************************/
// function completed for the CS 305 students: DO NOT MODIFY (Unless you find a bug)
int main(int argc, char * argv[]) {
if(argc != NUM_PARAMS) {
usage(argv[0]);
return EXIT_FAILURE;
}
// open file for reading
FILE *fp = NULL;
fp = fopen(argv[1], "r");
if(fp == NULL) {
fprintf(stderr, "Error opening input file %s. Exiting.\n", argv[1]);
return EXIT_FAILURE;
}
// create maze objects
// need 2 since we are running BFS on one (which modifies the
// maze with the path marker character)
// need clean copy of maze for DFS
maze * the_maze = create_maze(fp);
rewind(fp); // resets file pointer to beginning of file
maze * the_maze2 = create_maze(fp);
// done with file at this point
fclose(fp);
fp = NULL;
// check maze to see if it was created successfully
if(the_maze == NULL || the_maze2 == NULL) {
fprintf(stderr, "Error creating maze data structure\n");
return EXIT_FAILURE;
}
// run breadth-first-search on maze
printf("\nSolving using breadth-first search.\n");
int a = solve_bfs(the_maze);
// run depth-first-search on maze
printf("\nSolving using depth-first search:\n");
int b = solve_dfs(the_maze2);
printf("\ncan solve BFS: %d, can solve DFS: %d\n\n", a, b);
// free memory and exit
free_maze(the_maze);
free_maze(the_maze2);
return EXIT_SUCCESS;
}
/*********************************************************
usage
prints error message to user
**********************************************************/
void usage(char * executable) {
printf("Usage: \n%s maze_file.txt\n", executable);
}
stack.c
#include <stdio.h>
#include <stdlib.h>
#include "stack.h"
/* initializes a new stack */
Stack initStack() {
Stack s = (Stack) malloc(sizeof(StackType));
s->top = NULL;
return s;
}
/* empty returns 0 if S is empty and non-zero if S is not empty */
int emptyStack(Stack S) {
return (S->top == NULL);
}
/* pushes d to S */
void push(Stack S, StackData d) {
Node * n = (Node *)malloc(sizeof(Node));
n->data = d;
n->next = S->top;
S->top = n;
}
/* pops top item from S */
StackData pop(Stack S) {
if(emptyStack(S)) {
printf("Stack is empty. Attempting to pop an empty stack. Exiting program.\n");
exit(1); // exiting program
}
// there is data to pop
StackData toReturn = S->top->data;
Node * tmp = S->top; // in order to free this later
S->top = S->top->next; // move pointer to next item in stack
free(tmp);
return toReturn;
}
/* frees stack memory */
void freeStack(Stack S) {
while(!emptyStack(S)) {
pop(S);
}
free(S);
}
queue.h
#ifndef QUEUE_H
#define QUEUE_H
#include "maze.h"
#define MAX_Q 5000 // 1 more than what can be stored in the queue
// in this application, the mazes are on the small
// side
/* data to store into queue */
typedef coord QueueData; // putting coordinates into queue
/* queue data structure */
typedef struct QueueTag QueueType;
typedef struct QueueTag* Queue; // pointer to queue struct
// so when it is passed, the values
// can be updated in functions
struct QueueTag {
int head;
int tail;
QueueData data[MAX_Q]; // space for items in queue
};
/* function prototypes on queues */
Queue initQueue();
int emptyQueue(Queue Q);
void enqueue(Queue Q, QueueData d);
QueueData dequeue(Queue Q);
int full(Queue Q);
void freeQueue();
#endif
maze.h
#ifndef MAZE_H
#define MAZE_H
/* struct definition for coord */
typedef struct coord {
int row;
int col;
} coord;
/* struct definition for maze */
typedef struct maze {
coord entry;
coord exit;
int width;
int height;
char ** data;
} maze;
/* prototypes */
/* in maze.c */
maze * create_maze(FILE *in);
void free_maze(maze * the_maze);
/* in solve.c */
int solve_bfs(maze * the_maze);
int solve_dfs(maze * the_maze);
void print_maze(maze * the_maze);
coord * make_coord(int r, int c);
void print_coord(coord c);
#endif
stack.h
#ifndef STACK_H
#define STACK_H
#include "maze.h"
#define BAD {-1, -1} // coordinate off maze
/* data to store into stack */
typedef coord StackData;
/* stack data structures */
typedef struct NodeTag Node;
typedef struct StackTag StackType;
typedef struct StackTag* Stack;
/* linked list implementation of stacks */
struct NodeTag {
StackData data;
Node *next;
};
struct StackTag {
Node * top;
};
/* function prototypes on stacks */
Stack initStack();
int emptyStack(Stack S);
void push(Stack S, StackData d);
StackData pop(Stack S);
void freeStack(Stack S);
#endif
you need to fix your bound checking, assuming zero based indexing
# incorrect
to_explore.col+1 =< the_maze->width
# correct
to_explore.col+1 < the_maze->width
similar is the case for checking of to_explore.rowemphasized text
The error is in print_maze function.
void print_maze(maze * the_maze){
the_maze->data[the_maze->entry.row][the_maze->entry.col]='S';
the_maze->data[the_maze->exit.row][the_maze->exit.col]='F';
for(int i=0; i<the_maze->width; i++){
for(int j=0; j<the_maze->height; j++){
printf("%s",the_maze->data[i][j]);
}
}
data[i] represents ith row, so i should iterate over height.
data[i][j] represents jth element in ith row, so j should iterate over width. You need to swap height and width in the for loop.
void print_maze(maze * the_maze){
the_maze->data[the_maze->entry.row][the_maze->entry.col]='S';
the_maze->data[the_maze->exit.row][the_maze->exit.col]='F';
for(int i=0; i<the_maze->height; i++){
for(int j=0; j<the_maze->width; j++){
printf("%s",the_maze->data[i][j]);
}
}
}

Whats wrong when copying my nested struct?

I code C to get better in programming and study... and have program that should generate a static web-page. It also saves the project as a text-file. I have separate functions to make object (realloc and put a new struct...), and have extracted the problem-code to a short program for this occasion... It's just for reading the 'project'. When I run it says:
Segmentation fault (core dumped)
in the middle of the print_1_content
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define SELL_ITEM 1
#define PARAGRAPH_ITEM 2
struct SellItem {
char title[50];
int nr_of_img;
char ** image_files;//array of strings
};
struct ParagraphItem{
char * text;
};
union ContentItem{//one of the following only
struct SellItem s_item;
struct ParagraphItem p_item;
};
struct Content{
int type;//1=sellitem 2=paragraph
union ContentItem c_item;
};
int open_items_file(struct Content **, int *, char *);
int free_1_item(struct Content *);
struct Content import_1_content(char *);
void increase(struct Content**, int *);
void print_1_content(struct Content *);
struct Content import_1_content(char *);
int free_1_item(struct Content *);
int main (void)
{
struct Content * content;
int content_count=0;
open_items_file(&content, &content_count, "all_items.txt");
return 0;
}
int open_items_file(struct Content ** content, int * number_of_content, char * filename){
printf("open_items_file %s\n", filename);
FILE *fp = fopen(filename, "r");
char * line = NULL;
size_t len = 0;
ssize_t read;
int counter=0;
if(fp==NULL){
return 0;
}
//for each row
while ((read = getline(&line, &len, fp)) != -1) {
if((line[0]=='S' || line[0]=='P') && line[1]=='-'){
if(line[3]==':'){
if(line[2]=='I'){
increase(content, number_of_content);
*content[(*number_of_content)-1] = import_1_content(line);
}
else{
//not sell/paragraph item
}
}//end if line[3]==':'
}//end if line[0] =='S' eller 'P'
counter++;
}
free(line);
fclose(fp);
return counter;
}
void increase(struct Content** content, int *nr_of_content){
if((*nr_of_content)==0){
*content = malloc(sizeof(struct Content));
}
else{
*content = realloc(*content, (*nr_of_content+1) * sizeof(struct Content));
}
(*nr_of_content)++;
}
void print_1_content(struct Content * content){
//Print info
}
struct Content import_1_content(char * text_line){
struct Content temp_content_item;
char * line_pointer = text_line;
char c;
line_pointer += 4;
if(text_line[0]=='S'){
temp_content_item.type = SELL_ITEM;
temp_content_item.c_item.s_item.nr_of_img=0;
int i=0;
char * temp_text;
while(*line_pointer != '|' && *line_pointer != '\n' && i < sizeof(temp_content_item.c_item.s_item.title)-1){
temp_content_item.c_item.s_item.title[i] = *line_pointer;
i++;//target index
line_pointer++;
}
temp_content_item.c_item.s_item.title[i]='\0';
i=0;
//maybe images?
short read_img_counter=0;
if(*line_pointer == '|'){
line_pointer++; //jump over '|'
//img-file-name separ. by ';', row ends by '\n'
while(*line_pointer != '\n'){//outer image filename -loop
i=0;
while(*line_pointer != ';' && *line_pointer != '\n'){//steps thr lett
c = *line_pointer;
if(i==0){//first letter
temp_text = malloc(2);
}
else if(i>0){
temp_text = realloc(temp_text, i+2);//extra for '\0'
}
temp_text[i] = c;
line_pointer++;
i++;
}
if(*line_pointer==';'){//another image
line_pointer++;//jump over ';'
}
else{
}
temp_text[i]='\0';
//allocate
if(read_img_counter==0){//create array
temp_content_item.c_item.s_item.image_files = malloc(sizeof(char*));
}
else{//extend array
temp_content_item.c_item.s_item.image_files = realloc(temp_content_item.c_item.s_item.image_files, sizeof(char*) * (read_img_counter+1));
}
//allocate
temp_content_item.c_item.s_item.image_files[read_img_counter] = calloc(i+1, 1);
//copy
strncpy(temp_content_item.c_item.s_item.image_files[read_img_counter], temp_text, strlen(temp_text));
read_img_counter++;
temp_content_item.c_item.s_item.nr_of_img = read_img_counter;
}
}
else{
printf("Item had no img-files\n");
}
}
else{ // text_line[0]=='P'
temp_content_item.type = PARAGRAPH_ITEM;
temp_content_item.c_item.p_item.text = calloc(strlen(text_line)-4,1);
int i=0;
while(*line_pointer != '\0' && *line_pointer != '\n'){
temp_content_item.c_item.p_item.text[i] = *line_pointer;
i++;
line_pointer++;
}
}
print_1_content(&temp_content_item);
return temp_content_item;
}
int free_1_item(struct Content * item){
if(item->type==SELL_ITEM){
if(item->c_item.s_item.nr_of_img > 0){
//Freeing img-names
for(int i=0; i<item->c_item.s_item.nr_of_img; i++){
free(item->c_item.s_item.image_files[i]);
}
}
return 1;
}
else if(item->type==PARAGRAPH_ITEM){
//freeing p_item
free(item->c_item.p_item.text);
return 1;
}
else{
printf("error: unknown item\n");
}
return 0;
}
The text file to read (all_items.txt) is like this, ends with a new-line, for the two content types of "sell-item" and "paragraph-item":
S-I:Shirt of cotton|image1.jpg;image2.jpg;image3.jpg
P-I:A paragraph, as they are called.
S-I:Trousers, loose style|image4.jpg
So the problem as you've discovered is on this line:
*content[(*number_of_content)-1] = temp_content_item2;
It's because of operate precedence because *content[(*number_of_content)-1] is not the same as (*content)[(*number_of_content)-1], it's actually doing *(content[(*number_of_content)-1]). So your code is doing the array indexing and then de-referencing which is pointing at some random place in memory. Replace that line with this and that will fix the current problem.
(*content)[(*number_of_content)-1] = temp_content_item2;

How to split up a line in a text file into multiple variables in C

I have an array of structs with the same amount of indexes as lines in the text file, that contains the following variables:
char[] model, float version, int price, char[] color;
I am reading from a file that has lines where each line fills one struct. Here is an example of a couple lines from the file:
F150 5.4 28000 white
RAM1500 5.7 32000 orange
So if I'm reading the first line, I want to save F150 in char[] model, 5.7 in float version, 28000 in int price, and white in char[] color all in the struct stored in the first spot of the array.
I am unsure as to how to traverse the text file and assign the different variables to each struct in the array, any help would be greatly appreciated.
My current code for the accessing and reading of this file is here:
void accessFile(char *fn) {
struct vehicle *array;
int count = 0;
char line[100];
FILE *fp = fopen(fn, "r");
while(fgets(line, sizeof(line), fp) != 0) {
count++;
}
array = (struct vehicle *) malloc(count * sizeof(struct vehicle));
rewind(fp);
while(fgets(line, sizeof(line), fp) != 0) {
count++;
}
}
I ran through the file the first time to find the lines in the file in order to know how large to create the array. My plan is to assign each line with their corresponding variables in each struct, but I'm struggling with the syntax for how to differentiate between the individual parts of each line.
You can sscanf() to split the line.
Since I was bored, I did this:
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct
{
char* model;
float version;
int price;
char* color;
}
vehicle;
bool vehicle_create( vehicle* v, const char* model, float version, int price, const char* color )
{
v->model = strdup( model );
if (!(v->model)) return false;
v->version = version;
v->price = price;
v->color = strdup( color );
if (v->color) return true;
free( v->model );
return false;
}
void vehicle_destroy( vehicle* v )
{
if (!v) return;
if (v->model) free( v->model ); v->model = NULL;
if (v->color) free( v->color ); v->color = NULL;
}
bool read_vehicle( FILE* f, vehicle* v )
{
char model[ 50 ];
char color[ 50 ];
char line[ 200 ];
float version;
int price;
if (!fgets( line, sizeof(line), f ))
return false;
if (4 != sscanf( line, "%50s %f %d %50s", model, &version, &price, color ))
return false;
return vehicle_create( v, model, version, price, color );
}
size_t read_vehicle_inventory( FILE* f, vehicle* vs, size_t n )
{
size_t count = 0;
while (count < n
&& read_vehicle( f, vs + count ))
count += 1;
return count;
}
int main()
{
const size_t MAX_INVENTORY_SIZE = 100;
vehicle inventory[ MAX_INVENTORY_SIZE ];
size_t inventory_size = 0;
// Load inventory from file
inventory_size = read_vehicle_inventory( stdin, inventory, MAX_INVENTORY_SIZE );
printf( "inventory size = %d\n", (int)inventory_size );
// Display the inventory
for (size_t n = 0; n < inventory_size; n++)
printf( "%s %s %f is $%d\n",
inventory[ n ].color,
inventory[ n ].model,
inventory[ n ].version,
inventory[ n ].price );
// Free inventory
for (size_t n = 0; n < inventory_size; n++)
vehicle_destroy( inventory + n );
return 0;
}
Enjoy.

Segmentation Fault in multithreaded server implementation in C

So, I haven't used much C in quite some time, and was never very comfortable with malloc. I don't know if that is the source of the problem, but I'm getting a segmentation fault, and if anyone here sees anything obvious that might be wrong with it, it would save me a lot of trouble finding it, because I'm not even sure where to start.
information provided to main on launch re: thread limit, account limit, output file.
possible input
TRANS [acct id 1] [amount] [acct id 2] [amount] etc...
CHECK [acct id]
END
not much output, most information is provided to output file.
If this code is particularly difficult to understand or follow, let me know and I'll try to explain.
Edit: All memory errors from valgrind were resulting from calls to strtok(). I've messed with this, and still can't seem to fix it. How do I use strtok() from a scanned variable without causing these errors?
appserver.c
-main program
#include<stdlib.h>
#include<stdio.h>
#include<pthread.h>
#include<unistd.h>
#include<string.h>
#include "Bank.c"
#include "appserver.h"
struct account *accounts=NULL;
pthread_t *threads=NULL;
char *threadstatus=NULL;
int done=0;
char busywait=0;
FILE * f;
int main(int argc, char **argv){
int threadcount, banksize;
char* outputpath;
if(argc<4)
{
threadcount=1;
banksize=100;
outputpath="output.txt";
}
else
{
char *tstr=argv[1];
char *sstr=argv[2];
outputpath=argv[3];
threadcount=(int) strtol(tstr, NULL, 10);
banksize=(int) strtol(sstr, NULL, 10);
}
int reqID=0;
struct request *req1, *req2;
req1 = (struct request *) malloc( sizeof(struct request) );
char * in;
char *s;
initialize_status(threadcount);
threads = (pthread_t *) calloc( threadcount, sizeof(pthread_t) );
initialize_accounts(banksize);
initialize_mutex(banksize);
f=fopen(outputpath,"w");
int stringsize=1000;
int threadindex=0;
int i;
while(1)
{
printf("> ");
getline(&in, &stringsize, stdin);
s=strtok(in," ");
if( strcmp( (const char *) s, "CHECK") == 0 )
{
req2 = (struct request *) malloc( sizeof(struct request) );
reqID++;
req1->type = 'b';
s=strtok(NULL," ");
req1->balanceID = (int) strtol( s, NULL, 10);
req1->next = req2;
req1->requestID = reqID;
threadindex=nextthread(threadcount);
if(threadindex<0)
{
busywait=1;
while(busywait==1)
{
//do nothing, waiting for a thread to finish
}
threadindex=nextthread(threadcount);
}
req1->thread=threadindex;
pthread_create(&threads[threadindex], NULL, (void *)&workthread, &req1);
req1=req2;
}
else if( strcmp( (const char *) s, "TRANS") == 0 )
{
req2 = (struct request *) malloc( sizeof(struct request) );
i=0;
reqID++;
req1->type = 't';
while(s!=NULL&&i<10)
{
s = strtok(NULL," ");
req1->transIDs[i] = (int) strtol( s, NULL, 10);
if((s = strtok(NULL," "))==NULL)
{
printf("Bad input: \n");
break;
}
req1->transvals[i] = (int) strtol( s, NULL, 10);
i++;
}
req1->next = req2;
req1->requestID = reqID;
threadindex=nextthread(threadcount);
if(threadindex<0)
{
busywait=1;
while(busywait==1)
{
//do nothing
}
threadindex=nextthread(threadcount);
}
req1->thread=threadindex;
pthread_create(&threads[threadindex], NULL, (void *)&workthread, &req1);
req1=req2;
}
else if( strcmp( (const char *) s, "END") == 0)
{
req1->type = 'e';
threadindex=nextthread(threadcount);
if(threadindex<0)
{
busywait=1;
while(busywait==1)
{
//do nothing
}
threadindex=nextthread(threadcount);
}
req1->thread=threadindex;
pthread_create(&threads[threadindex], NULL, (void *)&workthread, &req1);
for( i = 0; i < threadcount; i++)
pthread_join( threads[i], NULL);
free(accounts);
free(threads);
break;
}
else
{
printf("Try again\n");
}
free(in);
}
return 0;
}
void *workthread(struct request *data)
{
threadstatus[data->thread]='b';
int value;
int i, balance;
printf("< ID %d\n",data->requestID);
while(1)
{
if(data->type == 't')
{
int transamt[10]={0,0,0,0,0,0,0,0,0,0};
int values[10]={0,0,0,0,0,0,0,0,0,0};
for(i=0;i<10;i++)
{
if(!data->transIDs[i])
break;
transamt[i]=data->transvals[i];
value=read_account(data->transIDs[i]);
if((values[i]=value+transamt[i])<0)
{
busywait = 0;
threadstatus[data->thread]='a';
fprintf(f,"%d ISF %d\n",data->requestID,data->transIDs[i]);
return;
}
}
if(translock(data->transIDs) == 1)
{
int ID;
for(i=0;i<10;i++)
{
ID=data->transIDs[i];
accounts[ID-1].value=values[i];
write_account(data->transIDs[i],values[i]);
}
}
transunlock(data->transIDs);
busywait=0;
threadstatus[data->thread]='a';
fprintf(f,"%d OK\n",data->requestID);
return;
}
else if(data->type == 'b')
{
int balance=read_account(data->balanceID);
fprintf(f,"%d BAL %d\n",data->requestID,balance);
threadstatus[data->thread]='a';
busywait=0;
return;
}
else if(data->type == 'e')
{
done=1;
return;
}
}
}
int transunlock(int ids[])
{
struct account *current;
int i=0;
for(i=9;i>=0;i--)
{
current=&accounts[ids[i]-1];
if(ids[i]<1)
continue;
pthread_mutex_unlock(&current->lock); //unlock previous account
}
return;
}
int translock(int ids[])
{
struct account *current;
int i=0;
for(i=0;i<10;i++)
{
current=&accounts[ids[i]-1];
if(ids[i]<1||pthread_mutex_trylock(&current->lock)!=0) //if lock attempt fails
{
while(--i>=0)
{
pthread_mutex_unlock(&current->lock); //unlock previous account
}
return 0;
}
current++;
}
return 1;
}
int initialize_mutex(int n)
{
accounts=(struct account *) malloc(sizeof(struct account) * n);
if(accounts==NULL)
return 0;
int i;
for(i=0;i<n;i++)
{
accounts[i].value=0;
}
return 1;
}
int initialize_status(int n)
{
threadstatus = (char *) malloc( sizeof(char) * n );
int k;
for(k=0;k<n;k++)
{
threadstatus[k]='a';
}
}
int nextthread(int n)
{
int i;
for(i=0;i<n;i++)
{
if(threadstatus[i]=='a')
return i;
}
return -1;
}
appserver.h
#include<pthread.h>
struct account{
pthread_mutex_t lock;
int value;
};
struct request{
char type; //'b' for balance check, 't' for transaction, 'e' for exit
int transIDs[10];
int transvals[10];
int balanceID;
struct request *next;
int requestID;
int thread;
};
void *workthread(struct request *data);
int transunlock(int ids[]);
int translock(int ids[]);
int initialize_mutex(int n);
int initialize_status(int n);
int nextthread(int n);
Bank.c
/** Do not modify this file **/
#include "Bank.h"
#include <stdlib.h>
int *BANK_accounts; //Array for storing account values
/*
* Intialize back accounts
* Input: int n - Number of bank accounts
* Return: 1 if succeeded, 0 if error
*/
int initialize_accounts( int n )
{
BANK_accounts = (int *) malloc(sizeof(int) * n);
if(BANK_accounts == NULL) return 0;
int i;
for( i = 0; i < n; i++)
{
BANK_accounts[i] = 0;
}
return 1;
}
/*
* Read a bank account
* Input: int ID - Id of bank account to read
* Return: Value of bank account ID
*/
int read_account( int ID )
{
usleep( 100000 );
return BANK_accounts[ID - 1];
}
/*
* Write value to bank account
* Input: int ID - Id of bank account to write to
* Input: int value - value to write to account
*/
void write_account( int ID, int value)
{
usleep( 100000 );
BANK_accounts[ID - 1] = value;
}
Bank.h
/** Do not modify this file **/
/*
* These functions do not provide any error checking.
* If an invalid input is supplied the behavior is
* undefined.
*/
/*
* Intialize n bank accounts with IDs from 1 to n and values of 0.
* Input: int n - Number of bank accounts, must be larger than 0
* Return: 1 if succeeded, 0 if error
*/
int initialize_accounts( int n );
/*
* Read a bank account
* Input: int ID - Id of bank account to read
* Return: Value of bank account ID
*/
int read_account( int ID );
/*
* Write value to bank account
* Input: int ID - Id of bank account to write to
* Input: int value - value to write to account
*/
void write_account( int ID, int value);
Like I said earlier, all errors on valgrind related to strtok() calls, as follows:
Conditional jump or move depends on uninitialised value(s)
Use of uninitialised value of size 8
Invalid read of size 1
Process terminating with default action of signal 11 (SIGSEGV)
In main() you wrote:
char * in;
...
while(1)
{
printf("> ");
scanf("%s",&in);
I think scanf() doesn't call malloc() for you.

Resources