Segmentation Fault in multithreaded server implementation in C - 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.

Related

Problem with reload data function and save data function

I'm learning about disjoint dynamic memory, so I'm trying to make my own program. I need someone to help me see my problems and show me how to fix them.
I'm almost done with my program, but still have some problems in my program.
My problem:
my saveData() function and reload() function do not work correctly.
I'm not sure whether the saveData() function does get all the data I need
my reload() function just output it has brought back data from the bin file (in saveData() function) and then exit program with some weird code (ex: 8500241654)
Without the above problem, my program works well. Please check the 3 problems in my program in .h file and .c file
C Program Description:
"You will write a program that will store the information about automobiles. The information is about make, mode, yearBuilt, and cost (use struct). The user will choose from menu what they want to do (add auto, display auto with orders of cost or make, use switch).
When the program begins, if there was a previous data file of automobile information it will be loaded automatically. The program will begin where the user last left off. If there is no previous data file, then the program will ask the user how many automobiles record will be needed and the program will start fresh.
When the program ends, all data will be saved to a bin file. All memory will be released from the heap. "
P/s: thank you so much, and appreciate your help.
<Here is my .h file>
// FUNCTION PROTOTYPES
typedef struct {
char make[50]; // ex: Ford, Honda, Toyota
char model[50]; // ex: Corolla, Camry
int yearBuilt; // ex: 2001, 2022
int cost; // ex: 20500, 8999, 15000
} AUTOMOBILE; // 108 bytes
void addAuto(AUTOMOBILE* a[], int* eSize, int size);
int compareChars(const void* a, const void* b);
void displayAuto(AUTOMOBILE* autos[], int eSize);
void displayMenu();
void freeMemory(AUTOMOBILE* autos[], int size);
int getInt(char m[]);
int getCh(char m[]);
void quitProgram(int* temp);
AUTOMOBILE** reload(AUTOMOBILE* a[], int* eSize, int* size);
void saveData(AUTOMOBILE *a[], int eSize, int size);
void sortByCost(AUTOMOBILE* autos[], int eSize);
void sortByMake(AUTOMOBILE* autos[], int eSize);
// FUNCTIONS
void addAuto (AUTOMOBILE *a[], int* eSize, int size) {
char again = 'N';
char autoMake[50];
char autoModel[50];
do {
if (*eSize == size) {
printf("No room to add more automobile...it is full!\n");
system("pause");
return;
}
printf("\nAdding a new automobile to the array of items\n");
// add make
printf("What is the automobile's make (uppercase first letter, ex: Honda)? ");
scanf("%s", a[*eSize]->make);
// add model
printf("What is the automobile's model (uppercase first letter, ex: Camry)? ");
scanf("%s", a[*eSize]->model);
// add year built
a[*eSize]->yearBuilt = getInt("When was the automobile built (ex: 2022)? ");
// add cost
a[*eSize]->cost = getInt("How much does the automobile cost (ex: 45500)? ");
*eSize += 1;
printf("\nWould you like to add another item? [Y/N]: ");
scanf(" %c", &again);
} while (toupper(again) == 'Y');
} // end addAuto
int compareChars(const void* a, const void* b) {
const char* arg1 = *(const char**) a;
const char* arg2 = *(const char**) b;
return strcmp(arg1, arg2);
} // end compareChars
void displayAuto(AUTOMOBILE *autos[], int eSize) {
char option;
printf("\nChoose your desired order");
printf("\n[C]ost low to high");
printf("\n[M]ake ascending order");
option = getCh("\nEnter option: ");
if (option == 'C' || option == 'c')
sortByCost(autos, eSize);
else if (option == 'M' || option == 'm')
sortByMake(autos, eSize);
} // end displayAuto
void displayMenu() {
printf("\n[A]dd one automobile");
printf("\n[D]isplay all automobiles by");
printf("\n\t[C]ost low to high");
printf("\n\t[M]ake ascending order"); // ascending order: A-Z
printf("\n[Q]uit program\n");
} // end displayMenu
void freeMemory(AUTOMOBILE* autos[], int size) {
for (int i = 0; i < size; i++) {
free(autos[i]);
}
free(autos);
} // end freeMemory
int getCh(char m[]) {
char result;
char badValue = 'F';
// loop until get integer value
do {
badValue = 'F';
printf("%s", m);
scanf(" %c", &result);
// if "result" isn't an alphabet, do the loop again
if (isalpha(result) == 0) {
printf("\nYou must enter a valid character!\n");
badValue = 'T';
} // end If
} while (badValue == 'T');
return result;
} // end getCh
int getInt(char m[]) {
int result = 0;
char badValue = 'F';
// loop until get integer value
do {
badValue = 'F';
printf("%s", m);
if (scanf("%i", &result) != 1) {
printf("\nYou must enter a valid real numeric value!\n");
badValue = 'T';
} // end If
} while (badValue == 'T');
return result;
} // end getInt
void quitProgram(int *temp) {
printf("\nThank you for using program!\n");
*temp = 1;
} // end quitProgram
AUTOMOBILE** reload(AUTOMOBILE* a[], int* eSize, int* size) {
*eSize = 0;
FILE* fp = fopen("binaryDocument.bin", "rb");
if (fp == NULL) {
printf("\nNo information has been reload!\n");
system("pause");
return a;
} // end if
printf("\nI have brought back the previous saved data into the array!\n");
system("pause");
// get the size
fread(size, sizeof(int), 1, fp);
// memory allocation for [size] pointers, [size] * 4 bytes of space
// use the size to allocate the space for the pointer array
a = calloc(*size, sizeof(AUTOMOBILE*));
if (a == NULL) {
printf("Allocation of memory failed...\n");
exit(-1);
}
// go through each one of them, and allocate 108 bytes each and allow these pointers to refer to it
for (int i = 0; i < size; i++) {
a[i] = calloc(1, sizeof(AUTOMOBILE));
if (a[i] == NULL) {
printf("Allocation of memory at autos[%i] failed...\n", i);
exit(-1);
}
}
// get the eSize and use the eSize to reload the array
fread(eSize, sizeof(int), 1, fp);
fread(a, sizeof(AUTOMOBILE*), *eSize, fp);
fclose(fp);
return a;
} // end reload
void saveData(AUTOMOBILE *a[], int eSize, int size) { // PROBLEM HERE
FILE* fp = fopen("binaryDocument.bin", "wb");
if (fp == NULL) {
printf("\nCould not save the information to a binary file\n");
system("pause");
return;
} // end if
fwrite(&size, sizeof(int), 1, fp);
fwrite(&eSize, sizeof(int), 1, fp);
fwrite(a, sizeof(AUTOMOBILE*), eSize, fp);
fclose(fp);
} // end saveData
void sortByCost(AUTOMOBILE *autos[], int eSize) {
int temp = 0;
int autoCost[1000];
for (int i = 0; i < eSize; i++) {
autoCost[i] = autos[i]->cost;
}
for (int i = 0; i < eSize; ++i) {
for (int j = i + 1; j < eSize; ++j) {
if (autoCost[i] > autoCost[j]) {
temp = autoCost[i];
autoCost[i] = autoCost[j];
autoCost[j] = temp;
}
}
}
printf("\nAutomobiles are displayed from low to high in term of cost: \n");
for (int l = 0; l < eSize; l++) {
for (int k = 0; k < eSize; k++) {
if(autoCost[l] == autos[k]->cost)
printf("%i\t%s\t%s\t%i\n", autoCost[l], autos[k]->make, autos[k]->model, autos[k]->yearBuilt);
}
}
} // end sortByCost
void sortByMake(AUTOMOBILE *autos[], int eSize) {
qsort(autos, eSize, sizeof(AUTOMOBILE*), compareChars);
printf("\nAutomobiles are displayed A-Z: \n");
for (int i = 0; i < eSize; i++) {
printf("%s\t%s\t%i\t%i\n", autos[i]->make, autos[i]->model, autos[i]->yearBuilt, autos[i]->cost);
}
} // end sortByMake
<Here is my .c file>
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "DJDMHeader.h"
//****************************************************
// MAIN FUNCTION
int main() {
int size = 0;
int eSize = 0;
AUTOMOBILE** autos = NULL; // create the variable to make the array of automobile pointers
int i, temp = 0;
char choice;
// reload data
autos = reload(autos, &eSize, &size);
// case: nothing to reload, start fresh
if (size == 0) {
// get integer value for variable size
size = getInt("How many automobiles will you have at the most: ");
// memory allocation for [size] pointers, [size] * 4 bytes of space
autos = calloc(size, sizeof(AUTOMOBILE*));
if (autos == NULL) {
printf("Allocation of memory failed...\n");
exit(-1);
}
// go through each one of them, and allocate 108 bytes each and allow these pointers to refer to it
for (i = 0; i < size; i++) {
autos[i] = calloc(1, sizeof(AUTOMOBILE));
if (autos[i] == NULL) {
printf("Allocation of memory at autos[%i] failed...\n", i);
exit(-1);
}
}
}
while (temp == 0) {
displayMenu();
choice = getCh("What is your choice?: ");
// switch
switch (choice) {
case 'a':
case 'A':
addAuto(autos, &eSize, size);
break;
case 'd':
case 'D':
displayAuto(autos, eSize);
break;
case 'q':
case 'Q':
quitProgram(&temp);
break;
default:
printf("\nPlease choose the existed choices!\n");
}
}
// Save data
saveData(autos, eSize, size);
// Free memory
freeMemory(autos, size);
return 0;
}
If anything about my program or my question make you unhappy (or something like that), please tell me, I will edit again. So much thanks.
You either operate on an array:
#include <stdio.h>
typedef struct {
char make[50]; // ex: Ford, Honda, Toyota
char model[50]; // ex: Corolla, Camry
int yearBuilt; // ex: 2001, 2022
int cost; // ex: 20500, 8999, 15000
} AUTOMOBILE;
// array
void saveData(AUTOMOBILE *a, int eSize, int size) {
FILE *fp = fopen("binaryDocument.bin", "wb");
if (!fp) {
printf("\nCould not save the information to a binary file\n");
return;
}
fwrite(&size, sizeof(int), 1, fp);
fwrite(&eSize, sizeof(int), 1, fp);
fwrite(a, sizeof(*a), eSize, fp);
fclose(fp);
}
int main() {
AUTOMOBILE a[] = {
{ "Ford", "Model T", 1908, 1000 },
{ "Honda", "Accord", 2022, 20000 }
};
saveData(a, sizeof(a) / sizeof(*a), 42);
}
or as an array of pointers:
#include <stdio.h>
typedef struct {
char make[50]; // ex: Ford, Honda, Toyota
char model[50]; // ex: Corolla, Camry
int yearBuilt; // ex: 2001, 2022
int cost; // ex: 20500, 8999, 15000
} AUTOMOBILE; // 108 bytes
// array of pointers
void saveData(AUTOMOBILE *a[], int eSize, int size) {
FILE *fp = fopen("binaryDocument.bin", "wb");
if (!fp) {
printf("\nCould not save the information to a binary file\n");
return;
}
fwrite(&size, sizeof(int), 1, fp);
fwrite(&eSize, sizeof(int), 1, fp);
for(unsigned i = 0; i < eSize; i++) {
fwrite(a[i], sizeof(**a), 1, fp);
}
fclose(fp);
}
int main() {
AUTOMOBILE *a[] = {
&(AUTOMOBILE) { "Ford", "Model T", 1908, 1000 },
&(AUTOMOBILE) { "Honda", "Accord", 2022, 20000 }
};
saveData(a, sizeof(a) / sizeof(*a), 42);
}
What you call size is usually referred to as max_size or capacity. eSize vs size is confusing. In either case, size is an artifact of your in memory representation so you don't need to persist that.
Prefer unsigned types when the value cannot be negative.
Types (AUTOMOBILE) are not by convention upper case (which is used for constants like enums and defined symbols).

C program for dijiktras shortest path not working [duplicate]

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;
}

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.

simple patient managing program using queue

I'm making simple patient managing program using circular queue but q.rear always have "0" value while executing exit_hos()
I thought that addq() makes variable "rear" different, but It doesn't work.
is_empty() always return front and rear is same.
I think I'm misunderstanding some codes and memory concepts.
how can I fix these functions?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_SIZE 50
#define MAX_QUEUE_SIZE 6
typedef struct {
char** value;
int front;
int rear;
} Queue;
void init_queue(Queue* q) {
q->value = (char**)malloc(sizeof(char*) * MAX_QUEUE_SIZE);
q->front = 0;
q->rear = 0;
}
int is_full(Queue* q) {
if (((q->rear +1) % MAX_QUEUE_SIZE) == q->front)
return 1;
else
return 0;
}
int is_empty(Queue* q) {
if (q->front == q->rear)
return 1;
else
return 0;
}
void addq(Queue* q, char* value) {
q->rear = (q->rear+1) % MAX_QUEUE_SIZE;
q->value[q->rear] = value;
printf("addq: %s", value);
return;
}
char* deleteq(Queue* q) {
q->front = (q->front + 1) % MAX_QUEUE_SIZE;
return q->value[q->front];
}
void arrive(Queue q) {
int input;
char name[MAX_SIZE];
printf("\n");
printf("1. submit\n");
printf("2. cancel\n");
scanf("%d", &input);
if (input == 1) {
if (is_full(&q) == 1) {
printf("Service is not available\n");
}
else {
printf("name: ");
scanf("%s", name);
addq(&q, name);
}
}
else if (input == 2) {
return;
}
else {
printf("input error\n");
return;
}
return;
}
void exit_hos(Queue q) {
char patient[MAX_SIZE];
if (is_empty(&q) == 1)
{
printf("There is no patient waiting\n");
}
else {
strcpy(patient, deleteq(&q));
printf("patient: %s", patient);
}
return;
}
int main() {
int input;
Queue q;
init_queue(&q);
while (1)
{
printf("\nINPUT\n");
printf("1. Arrive hostpital\n");
printf("2. Exit hospital\n");
printf("3. service exit\n");
scanf("%d", &input);
if (input == 1)
arrive(q);
else if (input == 2) {
exit_hos(q);
}
else if (input == 3) {
printf("exit\n");
return 0;
}
else {
printf("input error\n");
}
}
free(q.value);
return 0;
}
I think that this line is wrong:
q->value = (char**)malloc(sizeof(char*) * MAX_QUEUE_SIZE);
I think that it should be:
char * _value = (char*)malloc(sizeof(char*) * MAX_QUEUE_SIZE);
q->value = &_value;
malloc is going to return a pointer to a char array. q->value is a pointer to a pointer to a char array. So you want to set it to the address of the char array that malloc is created for you.
Change you init_queue code to this and it will work:
void init_queue(Queue* q) {
char * _value = (char*)malloc(sizeof(char*) * MAX_QUEUE_SIZE);
q->value = &_value;
q->front = 0;
q->rear = 0;
}
Output:
Chris#DESKTOP-BCMC1RF ~
$ ./main.exe
INPUT
1. Arrive hostpital
2. Exit hospital
3. service exit
1
1. submit
2. cancel
1
name: fred
addq: fred
INPUT
1. Arrive hostpital
2. Exit hospital
3. service exit
2
If you already have a max queue size and a max size, you are better off pre-allocating the whole thing as an array, reducing memory headaches. As a general rule, avoid headaches unless they provide a feature you want.
Note: This method of keeping track of and re-using memory is called a circular buffer (not to be confused with the linked list types that are more commonly called queues).
#define MAX_SIZE 50
#define MAX_QUEUE_SIZE 6
typedef struct {
char value [MAX_QUEUE_SIZE][MAX_SIZE + 1]; //+1 to hold extra null termination
unsigned int front;
unsigned int size; //size is a clearer than rear, which could have meant end item or end+1 and needed special empty queue handling
} Queue;
void init_queue(Queue* q) {
memset(q,0,sizeof(Queue)); //just zero it all
//more info on this and some situation-dependent alternatives https://stackoverflow.com/questions/11152160/initializing-a-struct-to-0
}
int is_full(const Queue* q) {
return q->size >= MAX_QUEUE_SIZE;
}
int is_empty(const Queue* q) {
return q->size == 0;
}
//sometimes called a push operation
//return 0 if failed
int addq(Queue* q, const char* value) {
//error check, abort, error handling section:
//full queue -> abort
if(is_full(q)) return 0;
//long value -> truncate handled via strncpy
//actual operation
const unsigned int destination = (q->front + q->size) % MAX_QUEUE_SIZE;
strncpy(q->value[destination],value,MAX_SIZE);
q->size = q->size + 1;
printf("addq: %s", q->value[destination]);
return q->size;
}
//sometimes called a pop operation
//return value may not persist if addq is called, but fine for your use of copying on call
const char* deleteq(Queue* q) {
if(is_empty(q)) return 0;
const char * retval = q->value[q->front];
q->front = (q->front + 1) % MAX_QUEUE_SIZE;
q->size = q->size - 1;
return retval;
}
also remember to use either MAX_SIZE + 1 or strncpy with MAX_SIZE - 1 since "No null-character is implicitly appended at the end of destination if source is longer than num."
(and strcpy and scanf as you sling them onto arrays is unsafe)

why does C code pauses after i give ./a.out?

#include<stdlib.h>
#include<stdio.h>
#include<string.h>
//This program is a sorting application that reads a sequence of numbers
//from a file and prints them on the screen . The reading from the file here,
//is a call back function .
typedef int (*CompFunc)(const char* , const char* );
typedef int (*ReadCheck)(char nullcheck);
char array[100];
//Let this function be done in the library itself . It doesn't care as to
//where the compare function and how is it implemented . Meaning suppose
//the function wants to do sort in ascending order or in descending order
//then the changes have to be done by the client code in the "COMPARE" function
//who will be implementing the lib code .
void ReadFile(FILE *fp,ReadCheck rc)
{
char a;
char d[100];
int count = 0,count1=0;
a=fgetc(fp);
while(1 != (*rc)(a))
{ if(a=='\0')
{
//d[count1]='\0';
strcpy(&array[count],d);
count=count+1;
}
else
{
d[count1]=a;
count1=count1+1;
}
}
}
void Bubblesort(char* array , int size , int elem_size , CompFunc cf)
{ int i,j;
int *temp;
for( i=0;i < size ;i++)
{
for ( j=0;j < size -1 ; j++)
{
// make the callback to the comparision function
if(1 == (*cf)(array+j*elem_size,array+ (j+1)*elem_size))
{
//interchanging of elements
temp = malloc(sizeof(int *) * elem_size);
memcpy(temp , array+j*elem_size,elem_size);
memcpy(array+j*elem_size,array+(j+1)*elem_size,elem_size);
memcpy(array + (j+1)*elem_size , temp , elem_size);
free(temp);
}
}
}
}
//Let these functions be done at the client side
int Compare(const char* el1 , const char* el2)
{
int element1 = *(int*)el1;
int element2 = *(int*)el2;
if(element1 < element2 )
return -1;
if(element1 > element2)
return 1 ;
return 0;
}
int ReadChecked(char nullcheck)
{
if (nullcheck=='\n')
return 1;
else
return 0;
}
int main()
{
FILE *fp1;
int k;
fp1=fopen("readdata.txt","r");
ReadFile(fp1,&ReadChecked);
Bubblesort((char*)array,5,sizeof(array[0]),&Compare);
printf("after sorting \n");
for (k=0;k<5;k++)
printf("%d",array[k]);
return 0;
}
Just perhaps the program is taking a little while to run... just perhaps.
Here's a possible issue: What happens when fgetc returns EOF (-1) ?
while(1 != (*rc)(a))

Resources