How to show time in millisecond using C - c

I am joining two files after sorting them and to evaluate the timing I need to get the average time. But according to my coding it is showing in seconds, so the execution is fast enough to give the result in 1 second, so there is nothing to take to get the average. That is why I want to print the time in milliseconds so that I can take those and calculate the average timing. Here is my code -
#include <sys/stat.h> // S_IRUSR
#include <time.h> // time_t time
#include "mergesort.h"
typedef struct {
int fd; //file description ID
int type; //the schema type of file
page_t *page; //page buffer which use to store records
} file_t;
/*! \fn file_t *file_init(char *file_path, int type, int page_size)
* \brief initialize the file structure with inputted parameters
* \param file_path the path of need to handled file
* \param type the type of file.
* 1 means the file formated with characters schema
* 2 means the file formated with guilds schema
* \param page_size the size of page, the page will use to buffer the
* record which read from file
* \return not NULL the file structure
* NULL means cannot construct the file structure
*/
file_t *file_init(char *file_path, int type, page_t *page)
{
file_t *file = calloc(1, sizeof(file_t));
char sorted_file[1024] = {0};
snprintf(sorted_file, 1023, "%s.sorted", file_path);
file->fd = open(sorted_file, S_IRUSR);
file->type = type;
file->page = page;
return file;
}
int merge_sort(pass_t *pass, int page_size, int page_num, char *file)
{
int ret = OK;
if (pass->pages == NULL)
{
pass->pages = calloc(pass->page_num, sizeof(page_t));
}
// parse input
pass->page_size = page_size;
pass->page_num = page_num;
pass->input_file = file;
pass->output_file = "/tmp/merge_tmp";
pass->type = 1;
if (strstr(pass->input_file, "guilds") != NULL)
{
pass->type = 2;
}
// pass 0: split the original into sorted file pieces
pass_0(pass);
// pass n: merge the file pieces into a sorted unique file
return pass_n(pass);
}
/*! \fn int main(int argc, char *argv[])
* \brief the entry of program
* \param argc the number of input parameters
* \param argv the list of input parameters
* 1st is program name
* 2nd is the optional flag to indicate ouput matched record to screen
* 2nd or 3rd is the record size of page
* 3rd or 4th is the page size
* 4th or 5th is one file which need to be merged
* 5th or 6th is another file which need to be merged
* \return 0 indicate the operation is success
* other indicate the operation is failed
*/
int main(int argc, char *argv[])
{
if (argc < 4)
{
fprintf(stderr,
"Usage: bin/sortmerge [-o] <pagesize> <buffers> <path>\n");
exit(1);
}
int param_id = 1;
int out_flag = 0;
if (strcmp(argv[param_id], "-o") == 0)
{
out_flag = 1;
param_id++;
}
int page_size = atoi(argv[param_id++]);
int page_num = atoi(argv[param_id++]);
int total_buf = page_size * page_num;
int ret = OK;
int tuples_num = 0;
time_t start = time(NULL);
pass_t file1_pass = {0};
merge_sort(&file1_pass, page_size, page_num, argv[param_id++]);
pass_t file2_pass = {0};
// reuse the allocated buffer
file2_pass.pages = file1_pass.pages;
merge_sort(&file2_pass, page_size, page_num, argv[param_id++]);
// open sorted file
file_t *chars_file = NULL;
file_t *guilds_file = NULL;
if (strstr(file1_pass.input_file, "guilds") != NULL)
{
chars_file = file_init(file2_pass.input_file, 1, &file2_pass.pages[0]);
guilds_file = file_init(file1_pass.input_file, 2, &file1_pass.pages[1]);
}
else
{
chars_file = file_init(file1_pass.input_file, 1, &file1_pass.pages[0]);
guilds_file = file_init(file2_pass.input_file, 2, &file2_pass.pages[1]);
}
record_t *guild_record = NULL;
record_t *char_record = NULL;
PAGE_BEFORE(chars_file->page, page_size);
PAGE_BEFORE(guilds_file->page, page_size);
do
{
// load and popup record from guilds
page_load(guilds_file->fd, guilds_file->page, guilds_file->type,
guilds_file->type);
guild_record = page_pop_record(guilds_file->page);
if (guild_record == NULL)
{
//no record then exit
break;
}
do
{
// load popup record from characters
page_load(chars_file->fd, chars_file->page, chars_file->type,
chars_file->type);
char_record = page_pop_record(chars_file->page);
if (char_record != NULL
&& guild_record->guild_id == char_record->guild_id)
{
// records matched with guild_id
tuples_num++;
if (out_flag == 1)
{
// output matched record information
printf("%d,%s,%d,%d,%d,%s\n", char_record->guild_id,
char_record->info.character.cname,
char_record->info.character.team,
char_record->info.character.level,
char_record->info.character.cid,
guild_record->info.guild.gname);
}
}
// if not find bigger than guild tuple record,
// continuously popup record from characters
}
while (char_record != NULL
&& guild_record->guild_id >= char_record->guild_id);
}
while (guild_record != NULL && char_record != NULL);
printf("Number of tuples: %d\nTime: %d seconds\n",
tuples_num, (time(NULL) - start));
return 0;
}

Use clock() instead of time(). You should be able to just change time(NULL) to clock(). clock_t can replace time_t as well.

Related

Creating an array of structs by adding dynamically some struct-elements

I've been struggling with C pointers for hours now. I'm trying to create a C program which manages flights. A flight contains the following:
flight-number, from, to, date, price
OS772,Vienna,New York,15.12.2018,638.00
Therefore, I'm reading a textfile of this given structure. On every line read, I need to create another struct and add it to my array or "list" of structs.
The struct looks like:
typedef struct flights {
char *flnum;
char *from;
char *to;
char *date;
float price;
struct person *fPerson;
}flights;
My problem: Inside the function, the array of structs is created properly. But back in the main-function, the pointer to the array called 'flights **flight_list' is still NULL.
Here is the code (only the necessary parts):
int main(void) {
flights **flight_list = NULL;
int numFlights = 0;
if (!(numFlights = load_flights(flight_list)))
return EXIT_FAILURE;
/* value of flight_list = 0x0000 -> unchanged! */
/* ... */
Function short load_flights(flights **flight_list):
short load_flights(flights **flight_list) {
FILE *fp = NULL;
char file_buffer[256] = {};
int i = 0;
if (fp = fopen("flights.txt", "r")) {
/* create array of structs */
flight_list = (flights **)calloc(1, sizeof(int));
while (!feof(fp)) {
/* read current line of flight from textfile */
fgets(file_buffer, sizeof(file_buffer), fp);
/* create a new struct and add it to the array */
if ((flight_list[i] = (flights *)calloc(1, sizeof(flights))) != NULL) {
/* create every variable of the struct */
flight_list[i]->flnum = (char *)calloc(1, strlen(ptr)+1);
/* ... */
}
i++;
}
}
else return 0;
/* values of the struct-array are properly set; look in attached picture */
return i;
}
This image was taken while debugging the array-creation process before return i;:
And here outside the function; inside main:
So, why is my array of structs gone in the main-function?
You need to pass the address of a pointer variable to load_flights. Then load_flights needs to indirect through the variable to modify the caller's variable.
To handle the dynamic size of the input, you need to use realloc() each time through the loop to grow the array.
int main(void) {
flights **flight_list = NULL;
int numFlights = 0;
if (!(numFlights = load_flights(&flight_list)))
return EXIT_FAILURE;
/* ... */
}
short load_flights(flights ***flight_list) {
FILE *fp = NULL;
char file_buffer[256] = {};
int i = 0;
if (fp = fopen("flights.txt", "r")) {
/* create array of structs */
flight_list **temp_flight_list = NULL;
/* read current line of flight from textfile */
while (fgets(file_buffer, sizeof(file_buffer), fp)) {
// Grow the flight list array
flights **new_flight_list = realloc(*flight_list, (i+1) * sizeof(flight_list *));
if (new_flight_list == NULL) { // allocation failed, throw everything away
for (int j = 0; j < i-1; j++) {
free(temp_flight_list[i]->flnum);
free(temp_flight_list[i]->from);
/* ... */
free(temp_flight_list[i]);
}
free(temp_flight_list);
return 0;
}
temp_flight_list = new_flight_list;
/* create a new struct and add it to the array */
if ((temp_flight_list[i] = calloc(1, sizeof(flights))) != NULL) {
// Parse the buffer ...
/* create every variable of the struct */
temp_flight_list[i]->flnum = calloc(1, strlen(ptr)+1);
/* ... */
} else { // allocation failed, throw everything away
for (int j = 0; j < i-1; j++) {
free(temp_flight_list[i]->flnum);
free(temp_flight_list[i]->from);
/* ... */
free(temp_flight_list[i]);
}
free(temp_flight_list);
return 0;
}
i++;
}
// Store new flight list in caller's variable
*flight_list = temp_flight_list;
return i;
}
else return 0;
}
See also
Do I cast the result of malloc?
and
Why is “while (!feof(file))” always wrong?

How do I return a pointer to location in a buffer? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I'm currently working on a project in C which I'm required to create a buffer program. For the most part my program is finished but I'm just missing one required function: a location function to return the distance between the head (beginning of array) to the desired location designated by short loc_offset.
Given what I already have, how do I return a pointer to an index or location from my short?
Here is my given and created code:
Main (plat_bt.c):
/* File name: platy_bt.c
* Purpose:This is the main program for Assignment #1, CST8152
* Version: 1.18.1
* Author: Svillen Ranev
* Date: 16 January 2018
*/
/* The #define _CRT_SECURE_NO_WARNINGS should be used in MS Visual Studio projects
* to suppress the warnings about using "unsafe" functions like fopen()
* and standard sting library functions defined in string.h.
* The define directive does not have any effect on other compiler projects (gcc, Borland).
*/
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <limits.h>
#include "buffer.h"
/* constant definitions */
#define INIT_CAPACITY 200 /* initial buffer capacity */
#define INC_FACTOR 15 /* increment factor */
/*check for ANSI C compliancy */
#define ANSI_C 0
#if defined(__STDC__)
#undef ANSI_C
#define ANSI_C 1
#endif
/* Declaration of an error printing function with
* variable number of arguments
*/
void err_printf(char *fmt, ...);
/* Declaration of a buffer contents display function */
void display (Buffer *ptr_Buffer);
long get_filesize(char *fname);
int main(int argc, char **argv){
pBuffer ptr_Buffer; /* pointer to Buffer structure */
FILE *fi; /* input file handle */
int loadsize = 0; /*the size of the file loaded in the buffer */
int ansi_c = !ANSI_C; /* ANSI C compliancy flag */
/* Check if the compiler option is set to compile ANSI C */
/* __DATE__, __TIME__, __LINE__, __FILE__, __STDC__ are predefined preprocessor macros*/
if(ansi_c){
err_printf("Date: %s Time: %s",__DATE__, __TIME__);
err_printf("ERROR: Compiler is not ANSI C compliant!\n");
exit(1);
}
/* missing file name or/and mode parameter */
if (argc <= 2){
err_printf("\nDate: %s Time: %s",__DATE__, __TIME__);
err_printf("\nRuntime error at line %d in file %s\n", __LINE__, __FILE__);
err_printf("%s\b\b\b\b%s%s",argv[0],": ","Missing parameters.");
err_printf("Usage: platybt source_file_name mode");
exit(1);
}
/* create a source code input buffer */
switch(*argv[2]){
case 'f': case 'a': case 'm': break;
default:
err_printf("%s%s%s",argv[0],": ","Wrong mode parameter.");
exit(1);
}
/*create the input buffer */
ptr_Buffer = b_allocate(INIT_CAPACITY,INC_FACTOR,*argv[2]);
if (ptr_Buffer == NULL){
err_printf("%s%s%s",argv[0],": ","Cannot allocate buffer.");
exit(1);
}
/* open the source file */
if ((fi = fopen(argv[1],"r")) == NULL){
err_printf("%s%s%s%s",argv[0],": ", "Cannot open file: ",argv[1]);
exit (1);
}
/* load a source file into the input buffer */
printf("Reading file %s ....Please wait\n",argv[1]);
loadsize = b_load (fi,ptr_Buffer);
if(loadsize == RT_FAIL1)
err_printf("%s%s%s",argv[0],": ","Error in loading buffer.");
/* close the source file */
fclose(fi);
/*find the size of the file */
if (loadsize == LOAD_FAIL){
printf("The input file %s %s\n", argv[1],"is not completely loaded.");
printf("Input file size: %ld\n", get_filesize(argv[1]));
}
/* display the contents of the input buffer */
display(ptr_Buffer);
/* compact the buffer
* add end-of-file character (EOF) to the buffer
* display again
*/
if(!b_compact(ptr_Buffer,EOF)){
err_printf("%s%s%s",argv[0],": ","Error in compacting buffer.");
}
display(ptr_Buffer);
/* free the dynamic memory used by the buffer */
b_free(ptr_Buffer);
/* make the buffer invalid
It is not necessary here because the function terminates anyway,
but will prevent run-time errors and crashes in future expansions
*/
ptr_Buffer = NULL;
/*return success */
return (0);
}
/* error printing function with variable number of arguments*/
void err_printf( char *fmt, ... ){
/*Initialize variable list */
va_list ap;
va_start(ap, fmt);
(void)vfprintf(stderr, fmt, ap);
va_end(ap);
/* Move to new line */
if( strchr(fmt,'\n') == NULL )
fprintf(stderr,"\n");
}
void display (Buffer *ptr_Buffer){
printf("\nPrinting buffer parameters:\n\n");
printf("The capacity of the buffer is: %d\n",b_capacity(ptr_Buffer));
printf("The current size of the buffer is: %d\n",b_limit(ptr_Buffer));
printf("The operational mode of the buffer is: %d\n",b_mode(ptr_Buffer));
printf("The increment factor of the buffer is: %lu\n",b_incfactor(ptr_Buffer));
printf("The current mark of the buffer is: %d\n", b_mark(ptr_Buffer, b_limit(ptr_Buffer)));
/*printf("The reallocation flag is: %d\n",b_rflag(ptr_Buffer));*/
printf("\nPrinting buffer contents:\n\n");
b_rewind(ptr_Buffer);
b_print(ptr_Buffer);
}
long get_filesize(char *fname){
FILE *input;
long flength;
input = fopen(fname, "r");
if(input == NULL){
err_printf("%s%s","Cannot open file: ",fname);
return 0;
}
fseek(input, 0L, SEEK_END);
flength = ftell(input);
fclose(input);
return flength;
}
That main file has no errors or warnings, it was given to me to be used as my main.
Here is my edited source file (buffer.c):
/* File name: buffer.c
* Purpose: This is the main program for Assignment #01, CST8152
* Version: 1.0.3
* Author: Jack Loveday
* Date: 7 Febuary, 2018
*/
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <limits.h>
#include "buffer.h"
/* b_allocate: Creates new buffer on heap
Tries to allocate memory for:
- one Buffer (calloc)
- one dynamic character buffer (char array) (malloc)
Sets buffer operational mode and inc factor
Copies given init_capacity into Buffer capacity val */
Buffer * b_allocate(short init_capacity, char inc_factor, char o_mode) {
Buffer *pBuffer;
if (init_capacity < 0 || (unsigned char)inc_factor < 0)
return NULL;
pBuffer = (Buffer *)calloc(1, sizeof(Buffer));
if (!pBuffer) {
free(pBuffer);
return NULL;
}
pBuffer->cb_head = (char *)malloc(init_capacity);
if (o_mode == 'f' || (unsigned char)inc_factor == 0) {
pBuffer->mode = 0;
pBuffer->inc_factor = 0;
}
else if (o_mode == 'a') {
pBuffer->mode = ADD_MODE;
pBuffer->inc_factor = (unsigned char)inc_factor;
}
else if (o_mode == 'm' && (unsigned char)inc_factor <= 100) {
pBuffer->mode = MULTI_MODE;
pBuffer->inc_factor = (unsigned char)inc_factor;
}
else {
free(pBuffer->cb_head);
free(pBuffer);
return NULL;
}
pBuffer->capacity = init_capacity;
return pBuffer;
}
/* b_addc: resets r_flag to 0 & tries to add symbol to char array pointed by pBD */
pBuffer b_addc(pBuffer const pBD, char symbol) {
char *tBuffer;
short aSpace = 0, newInc = 0, newCapacity = 0;
if (!pBD)
return NULL;
pBD->r_flag = 0;
if ((short)(pBD->addc_offset * sizeof(char)) < pBD->capacity) {
pBD->cb_head[pBD->addc_offset] = symbol;
pBD->addc_offset++;
}
else if ((short)(pBD->addc_offset * sizeof(char)) == pBD->capacity) {
if (pBD->mode == 0)
return NULL;
else if (pBD->mode == 1) {
newCapacity = pBD->capacity + (unsigned char)pBD->inc_factor * sizeof(char);
if (newCapacity <= 0)
return NULL;
pBD->capacity = newCapacity;
}
else if (pBD->mode == -1) {
if (pBD->capacity == SHRT_MAX)
return NULL;
else {
aSpace = SHRT_MAX - pBD->capacity;
newInc = (short)((aSpace * pBD->inc_factor) / 100);
if (!newInc)
newInc = NEW_ONE;
newCapacity = (short)((pBD->capacity + newInc));
if (newCapacity <= 0)
newCapacity = SHRT_MAX;
}
}
tBuffer = (char *)realloc(pBD->cb_head, newCapacity);
if (tBuffer != pBD->cb_head)
pBD->r_flag = SET_R_FLAG;
pBD->cb_head = tBuffer;
pBD->cb_head[pBD->addc_offset] = symbol;
pBD->addc_offset++;
pBD->capacity = newCapacity;
}
return pBD;
}
/* b_clear: retains memory space currently allocated to buffer, but
re-initializes all appropriate members of given Buffer */
int b_clear(Buffer * const pBD){
if (!pBD)
return RT_FAIL1;
pBD->capacity = 0;
pBD->addc_offset = 0;
pBD->getc_offset = 0;
pBD->eob = 0;
return 1;
}
/* b_free: de-allocates memory for char array & Buffer struct */
void b_free(Buffer * const pBD) {
if (pBD) {
free(pBD->cb_head);
free(pBD);
}
}
/* b_isfull: returns 1 if buffer is full, otherwise returns 0, if rt error return -1 */
int b_isfull(Buffer * const pBD) {
if (!pBD)
return RT_FAIL1;
if ((short)(pBD->addc_offset * sizeof(char)) == pBD->capacity)
return 1;
else
return 0;
}
/* b_limit: returns current limit of buffer, return -1 on error */
short b_limit(Buffer * const pBD) {
if (!pBD)
return RT_FAIL1;
return pBD->addc_offset;
}
/* b_capacity: returns current capacity of buffer, return -1 on error */
short b_capacity(Buffer * const pBD) {
if (!pBD)
return RT_FAIL1;
return pBD->capacity;
}
/* b_mark: sets markc_offset to mark, must be between 0 and addc_offset, return -1 on error */
short b_mark(pBuffer const pBD, short mark) {
if (!pBD || mark < 0 || mark > pBD->addc_offset)
return RT_FAIL1;
pBD->markc_offset = mark;
return pBD->markc_offset;
}
/* b_mode: returns value of mode, or -1 on error */
int b_mode(Buffer * const pBD) {
if (!pBD)
return RT_FAIL1;
return pBD->mode;
}
/* b_infactor: returns non-negative value of inc_factor, return 0x100 (256) */
size_t b_incfactor(Buffer * const pBD) {
if (!pBD)
return NEW_FULL;
return (unsigned char)pBD->inc_factor;
}
/* b_load: returns value of mode */
int b_load(FILE * const fi, Buffer * const pBD) {
char c;
int cNum = 0;
if (!fi || !pBD)
return RT_FAIL1;
for (;;) {
c = (char)fgetc(fi);
if (feof(fi))
break;
if (!b_addc(pBD, c))
return LOAD_FAIL;
++cNum;
}
fclose(fi);
return cNum;
}
/* b_isempty: if addc_offset is 0 return 1, otherwise return 0, return -1 on error */
int b_isempty(Buffer * const pBD) {
if (!pBD)
return RT_FAIL1;
if (!pBD->addc_offset)
return 1;
else
return 0;
}
/* b_eob: returns eob (end of buffer), returns -1 on error */
int b_eob(Buffer * const pBD) {
if (!pBD)
return RT_FAIL1;
return pBD->eob;
}
/* b_getc: checks logic, if not valid returns -2, if getc_offset and addc_offset
are equal, set eob to 1 and returns -1, otherwise set eob to 0 */
char b_getc(Buffer * const pBD) {
char returner;
if (!pBD || !pBD->cb_head)
return RT_FAIL2;
if (pBD->getc_offset == pBD->addc_offset) {
pBD->eob = 1;
return RT_FAIL1;
}
else {
pBD->eob = 0;
}
returner = *(pBD->cb_head + pBD->getc_offset);
pBD->getc_offset++;
return returner;
}
/* b_print: used for diagnostic purposes only, returns -1 on error */
int b_print(Buffer * const pBD) {
int numOfChars = 0;
char c;
if (!pBD->addc_offset) {
printf("The Buffer is empty.\n");
return numOfChars;
}
pBD->getc_offset = 0;
while (1) {
c = b_getc(pBD);
if (b_eob(pBD))
break;
printf("%c", c);
++numOfChars;
}
numOfChars = pBD->getc_offset;
pBD->getc_offset = 0;
printf("\n");
return numOfChars;
}
/* b_compact: shrinks buffer to new capacity, before returning to a pointer add symbol
to the end of buffer, must set r_flag appropriatley */
Buffer * b_compact(Buffer * const pBD, char symbol) {
char *tempBuffer;
short tempCap;
if (!pBD)
return NULL;
tempCap = (pBD->addc_offset + 1) * sizeof(char);
if (tempCap == SHRT_MAX)
return pBD;
tempBuffer = (char *)realloc(pBD->cb_head, (unsigned short)tempCap);
if (tempCap == 0)
return NULL;
if (tempBuffer != pBD->cb_head)
pBD->r_flag = SET_R_FLAG;
pBD->cb_head = tempBuffer;
pBD->capacity = tempCap;
return pBD;
}
/* b_rflag: returns r_flag, returns -1 on error */
char b_rflag(Buffer * const pBD) {
if (!pBD)
return RT_FAIL1;
return pBD->r_flag;
}
/* b_retract: decrements getc_offset by 1, returns -1 on error, otherwise returns getc_offset */
short b_retract(Buffer * const pBD) {
if (!pBD)
return RT_FAIL1;
pBD->getc_offset--;
return pBD->getc_offset;
}
/* b_reset: sets getc_offset to current markc_offset, returns -1 on error and getc_offset otherwise */
short b_reset(Buffer * const pBD) {
if (!pBD)
return RT_FAIL1;
pBD->getc_offset = pBD->markc_offset;
return pBD->getc_offset;
}
/* b_getcoffset: returns getc_offset, or returns -1 on error */
short b_getcoffset(Buffer * const pBD) {
if (!pBD)
return RT_FAIL1;
return pBD->getc_offset;
}
/* b_rewind: set getc_offset and markc_offset to 0, return -1 on error and 0 otherwise */
int b_rewind(Buffer * const pBD) {
if (!pBD)
return RT_FAIL1;
pBD->addc_offset = 0;
pBD->markc_offset = 0;
return 0;
}
/* b_location: returns a pointer to location indicated by loc_offset, returns null on error */
char * b_location(Buffer * const pBD, short loc_offset) {
if (!pBD)
return NULL;
return *loc_offset;
}
And finally my buffer.h:
/*File Name: buffer.h
* Version: 1.18.1
* Author: S^R
* Date: 16 January 2018
* Preprocessor directives, type declarations and prototypes necessary for buffer implementation
* as required for CST8152-Assignment #1.
* The file is not completed.
* You must add your function declarations (prototypes).
* You must also add your constant definitions and macros,if any.
*/
#ifndef BUFFER_H_
#define BUFFER_H_
/*#pragma warning(1:4001) *//*to enforce C89 type comments - to make //comments an warning */
/* standard header files */
#include <stdio.h> /* standard input/output */
#include <malloc.h> /* for dynamic memory allocation*/
#include <limits.h> /* implementation-defined data type ranges and limits */
/* constant definitions */
/* You may add your own constant definitions here */
#define RT_FAIL1 -1 /* fail return value */
#define RT_FAIL2 -2 /* fail return value */
#define LOAD_FAIL -2 /* load fail error */
#define SET_R_FLAG 1 /* realloc flag set value */
#define ADD_MODE 1; /* named constant for additive mode */
#define MULTI_MODE -1; /* named constant for multiplicative mode */
#define NEW_ONE 1; /* generic named constant value of 1 */
#define NEW_FULL 256; /* generic named constant value of 256 */
/* user data type declarations */
typedef struct BufferDescriptor {
char *cb_head; /* pointer to the beginning of character array (character buffer) */
short capacity; /* current dynamic memory size (in bytes) allocated to character buffer */
short addc_offset; /* the offset (in chars) to the add-character location */
short getc_offset; /* the offset (in chars) to the get-character location */
short markc_offset; /* the offset (in chars) to the mark location */
char inc_factor; /* character array increment factor */
char r_flag; /* reallocation flag */
char mode; /* operational mode indicator*/
int eob; /* end-of-buffer flag */
} Buffer, *pBuffer;
/* function declarations */
/*
Place your function declarations here.
Do not include the function header comments here.
Place them in the buffer.c file
*/
Buffer * b_allocate(short init_capacity, char inc_factor, char o_mode);
pBuffer b_addc(pBuffer const pBD, char symbol);
int b_clear(Buffer * const pBD);
void b_free(Buffer * const pBD);
int b_isfull(Buffer * const pBD);
short b_limit(Buffer * const pBD);
short b_capacity(Buffer * const pBD);
short b_mark(pBuffer const pBD, short mark);
int b_mode(Buffer * const pBD);
size_t b_incfactor(Buffer * const pBD);
int b_load(FILE * const fi, Buffer * const pBD);
int b_isempty(Buffer * const pBD);
int b_eob(Buffer * const pBD);
char b_getc(Buffer * const pBD);
int b_print(Buffer * const pBD);
Buffer * b_compact(Buffer * const pBD, char symbol);
char b_rflag(Buffer * const pBD);
short b_retract(Buffer * const pBD);
short b_reset(Buffer * const pBD);
short b_getcoffset(Buffer * const pBD);
int b_rewind(Buffer * const pBD);
char * b_location(Buffer * const pBD, short loc_offset);
#endif
So again, I need to find the location of loc_offset in my b_location function and return it as a pointer. Thanks in advance!
char * b_location(Buffer * const pBD, short loc_offset) {
if (!pBD)
return NULL;
/* Make sure loc_offset doesn't go beyond the length of the array */
if( ! in_bounds )
return NULL;
return &(pBD->cb_head[loc_offset]);
}

Copy char array into array of character pointers

I am having problems trying to copy the contents of a char array into an array of char pointers in C. My code is listed below:
# include<stdio.h>
# include<stdlib.h>
# include<string.h>
# define RECORD_SIZE 300
# define BUFFER_SIZE 3
/* Structure for representing a single
* password entry */
typedef struct Record {
char * sitename;
char * username;
char * password;
struct Record * next;
} Record;
/* Declare function prototypes */
int isCorrectKey(char *,char *);
int isValidOperation(char);
int isValidSyntax(char *);
void getFields(char *,char * []);
void listEntries();
int updateEntries(char *);
int deleteEntries(char *);
int entryExists(char *);
void init(char *,char *,char *);
void readDB();
void writeToDB(char *);
void encrypt(char *,char * [],char *);
void decrypt(char *,char * [],char *);
/* Declare global variables */
char * database;
Record * records;
// Pre-condition: A character pointer to plaintext
// A character pointer to an empty buffer,
// A character pointer to the user input key
// Post-condition: The plaintext is encrypted and
// inserted into the buffer
void encrypt(char * text,char * buffer[BUFFER_SIZE],char * key) {
int i = 0;
for(;i < strlen(text);i++) {
buffer[i] = ((char *) (text[i]+3));
}
buffer[i] = 0;
}
// Pre-condition: A character pointer to ciphertext
// A character pointer to an empty buffer
// A character pointer tothe user input key
// Post-condition: The ciphertext is decrypted and
// inserted into the buffer
void decrypt(char * text,char * buffer[BUFFER_SIZE],char * key) {
int i = 0;
for(;i < strlen(text);i++) {
buffer[i] = ((char *) (text[i]-3));
}
buffer[i] = 0;
}
// Pre-condition: The database variable must be set
// The records variable must exist
// Post-condition: The value in database variable is
// used as filename to read the data. The data that
// is read and used to initialize the records variable
void readDB() {
// Open the file in read-only mode
FILE * f = fopen(database,"r");
char buffer[BUFFER_SIZE];
int index = 0;
if(f == NULL) {
// Print error if file is invalid
printf("Sorry. Unable to find password database.");
} else {
char c = 0;
// Read the file
while((c = fgetc(f)) != EOF) {
if(c != '\n') {
buffer[index++] = c;
} else {
buffer[index] = 0; // terminate each entry with null
index = 0;
}
}
fclose(f); // Close the file handle
}
}
// Pre-condition: The database variable must be set
// A character pointer to some text must be provided
// as input
// Post-condition: The value in database variable is
// used as filename to write the data.
void writeToDB(char * text) {
// Open the file in append mode
FILE * f = fopen(database,"a");
int index = 0;
if(f == NULL) {
// Print error if file is invalid
printf("Sorry. Unable to find password database.");
} else {
fputs(text,f); // Write to the file
fclose(f); // Close the file handle
}
}
// Pre-condition: A character pointer to the user input key
// A character pointer to the actual key
// The records variable must be set
// Post-condition: Returns 1 if the key value in the records variable
// has been properly decrypted.
// Returns 0 otherwise.
int isCorrectKey(char * uKey,char * mkey) {
return strcmp("ThisIsTheSecretKey",records->password);
}
// Pre-condition: A character indicating an operation value
// Post-condition: Returns 1 if the operation value is supported
// Returns 0 otherwise.
int isValidOperation(char operation) {
return operation == 'L' || operation == 'U' || operation == 'D';
}
// Pre-condition: A character pointer to a user input command string
// Post-condition: Returns 1 if the syntax of the command is correct
int isValidSyntax(char * command) {
return 0;
}
// Pre-condition: A character pointer to a comma delimited string
// Post-condition: The string is split into segments and stored into the buffer
void getFields(char * record,char * buffer[BUFFER_SIZE]) {
int i = 0;
int buffer_i = 0;
int record_len = strlen(record);
char tmp_buffer[RECORD_SIZE+1];
int tmp_i = 0;
for(;i < record_len;i++) {
if(record[i] != ',') {
tmp_buffer[tmp_i++] = record[i];
} else {
tmp_buffer[tmp_i] = 0;
strcpy(buffer[buffer_i++],tmp_buffer);
tmp_i = 0;
}
}
}
int main(int argc,char * argv[]) {
//database = "test.txt";
//readDB();
char * buffer[BUFFER_SIZE];
getFields("google,geek,pass123",buffer);
int i = 0;
for(;i<BUFFER_SIZE;i++) {
printf(buffer[i]);
printf("\n");
}
return 0;
}
From what I see, the offending line is in the getFields() function:
strcpy(buffer[buffer_i++],tmp_buffer);
I am trying to copy the contents of tmp_buffer into the indexes of buffer. My program just keeps crashing. I don't know why. Could someone please help me? Thanks.
You're not initializing the char *buffer to point to anything, e.g. buffer[0] = malloc(SIZE).
You need to allocate memory for each of the three entries into buffer. As it stands now, you are copying strings into the void.
You need something like this:
for(i=0;i<BUFFER_SIZE;i++) {
buffer[i] = malloc(MAX_STR_SIZE);
}
And then free them when you are done at the end:
for(i=0;i<BUFFER_SIZE;i++) {
free(buffer[i]);
}

Hash Table Project in C ... dereferencing pointer to incomplete type errors [closed]

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
I seem to be going in circles with this project! I get so many errors of 'dereferencing pointer to incomplete type', and have quite a few others. it seems like when I fix one another one will pop up to take its place!
It's my first time using hash tables, and I admit that I am rather lost but I think I made a very good start at least. Any input as to how to solve my 'dereferencing pointer to incomplete type' problems would be amazing!
htable.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "htable.h"
struct htablerec {
int size;
int num_entries;
hashing_t method;
char **keys;
int *freqs;
int *stats;
};
void *emalloc(size_t s) {
void *result = malloc(s);
if (NULL == result) {
fprintf(stderr, "Memory allocation failed!\n");
exit(EXIT_FAILURE);
}
return result;
}
/*moves pointer to point to something appropriate*/
htable htable_new(int capacity) {
int i;
htable ht = emalloc(sizeof *ht);
ht->size = size;
ht->method = method;
ht->num_keys = 0;
ht->keys = emalloc(size * sizeof ht->keys[0]);
ht->freqs = emalloc(size * sizeof ht->freqs[0]);
ht->stats = emalloc(size * sizeof ht->stats[0]);
for(i = 0; i<size; i++){
ht->keys[i] = NULL;
ht->freqs[i] = 0;
ht->stats[i] = 0;
}
return ht;
}
static unsigned int htable_step(htable h, unsigned int i_key){
return 1 + (i_key % (h->size - 1));
}
static unsigned int htable_wtoi(char *word){
unsigned int result = 0;
while(*word != '\0') result = (*word++ +31 * result);
return result;
}
static unsigned int htable_hash(htable h, unsigned int i_key){
return i_key % h->size;
}
void htable_free(htable h) {
int i;
for(i = 0; i<h->size; i++){
if(h->keys[i] != NULL){
free(h->keys[i]);
}
}
if(h->keys != NULL){
free(h->keys);
}
if(h->freqs != NULL){
free(h->freqs);
}
free(h);
}
static unsigned int htable_word_to_int(char *word) {
unsigned int result = 0;
while (*word != '\0') {
result = (*word++ + 31 * result);
}
return result;
}
int htable_insert(htable h, char *str) {
int num_collisions = 0;
int i_key = htable_wtoi(key);
int pos = htable_hash(h, i_key);
int step = 1;
if(h->method == DOUBLE)
step = htable_step(h, i_key);
while(h->keys[pos]!=NULL &&
strcmp(h->keys[pos],key)!=0 &&
num_collisions < h->size ){
pos = htable_hash(h, pos + step);
num_collisions++;
}
if(h->keys[pos] == NULL){
h->keys[pos] = emalloc((strlen(key)+1) * sizeof h->keys[0][0]);
strcpy(h->keys[pos],key);
h->stats[h->num_keys] = num_collisions;
h->num_keys++;
}
if(num_collisions >= h->size) /* We must be full, so return zero.*/
return 0;
return ++(h->freqs[pos]);
}
static int htable_search(htable h, char *key){
int num_collisions = 0;
int i_key = htable_wtoi(key);
int pos = htable_hash(h, i_key);
int step = 1;
if(h->method == DOUBLE)
step = htable_step(h, i_key);
while(h->keys[pos]!=NULL &&
strcmp(h->keys[pos],key)!=0 &&
num_collisions < h->size ){
pos = htable_hash(h, pos + step);
num_keys++;
}
if(num_keys >= h->size)
return 0;
else
return h->freqs[pos];
}
void htable_print(htable h, FILE *stream){
int i;
for(i = 0; i<h->size; i++){
if(h->keys[i] != NULL)
fprintf(stream, "%d\t%s\n",i, h->freqs[i], h->keys[i]);
}
}
void htable_print_entire_table(htable h, FILE *stream) {
int i;
for (i=0; loop < h->capacity; i++) {
if (h->key[i] != NULL) {
fprintf("%d\t%s\n", h->freqs[i], h->key[i]);
}
}
}
/**
* Prints a line of data indicating the state of the hash table when
* it is a given percentage full.
*
* The data is printed out right justified (with the given field widths,
* and decimal places) in this order:
*
* - How full the hash-table is as a percentage (4)
* - How many keys are in the hash-table at that point (11)
* - What percentage of those keys were placed 'at home' (12, 1 dp)
* - The average number of collisions per key placed (12, 2 dp)
* - The maximum number of collisions while placing a key (12)
*
* #param h the hash-table to get data from.
* #param stream the place to send output to.
* #param percent_full the point at which to print the statistics.
* If the hashtable is less full than that, then
* nothing will be printed.
*/
static void print_stats_line(htable h, FILE *stream, int percent_full) {
int current_entries = h->capacity * percent_full / 100;
double average_collisions = 0.0;
int at_home = 0;
int max_collisions = 0;
int i = 0;
if (current_entries > 0 && current_entries <= h->num_keys) {
for (i = 0; i < current_entries; i++) {
if (h->stats[i] == 0) {
at_home++;
}
if (h->stats[i] > max_collisions) {
max_collisions = h->stats[i];
}
average_collisions += h->stats[i];
}
fprintf(stream, "%4d%11d%12.1f%12.2f%12d\n", percent_full,
current_entries, at_home * 100.0 / current_entries,
average_collisions / current_entries, max_collisions);
}
}
void htable_print_stats(htable ht, FILE *stream, int num_stats) {
int i;
fprintf(stream, "Percent Current Percent Average Maximum\n");
fprintf(stream, " Full Entries At Home Collisions Collisions\n");
fprintf(stream, "-----------------------------------------------------\n");
for (i = 1; i <= num_stats; i++) {
print_stats_line(ht, stream, 100 * i / num_stats);
}
fprintf(stream, "-----------------------------------------------------\n\n");
}
htable.h
#ifndef HTABLE_H
#define HTABLE_H
#include <stdio.h>
typedef struct hashtable *htable;
typedef enum hashing_e { LINEAR, DOUBLE } hashing_t;
extern htable htable_new(int size);
extern void htable_destroy(htable ht);
extern int htable_insert(htable h, char *key);
extern int htable_search(htable h, char *key);
extern void htable_print(htable h, FILE *stream);
extern void htable_print_stats(htable ht, FILE *stream, int num_stats);
#endif
main.c (given by tutor for project to fit)
/**
* #file main.c
* #author Iain Hewson
* #date August 2012
*
* This program is written to test the hash table ADT specified in
* Cosc242 assignment two. It creates a hash table which can use
* linear-probing or double-hashing as a collision resolution
* strategy. Various options are provided which make it possible to
* examine a hash table as well as see how it performs while being
* filled.
*/
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include "mylib.h"
#include "htable.h"
/* A boolean type which can be TRUE or FALSE */
typedef enum bool_e {FALSE, TRUE} bool_t;
/* function declarations */
static void usage(char *progname);
static void setup(int argc, char **argv, bool_t *double_hashing,
bool_t *entire_table, bool_t *print_stats,
int *snapshots, int *tablesize);
/**
*
* Creates a hash-table and inserts words into it read from stdin.
* Arguments on the command line alter the behaviour of the program
* as follows:
* - -d Use double hashing (linear probing is the default)
* - -e Display entire contents of hash-table on stderr
* - -n NUM Show NUM statistics snapshots (if -p is used)
* - -p Print stats info instead of frequencies & words
* - -s SIZE Use the first prime >= SIZE as htable size
* - -h Display this message
*
* By default each word and it's frequency are printed to stdout.
*
* #param argc the number of command-line arguments.
* #param argv an array of strings containing the command-line arguments.
*
* #return EXIT_SUCCESS if the program is successful.
*/
int main(int argc,char **argv) {
bool_t entire_table = FALSE, double_hashing = FALSE, print_stats = FALSE;
int tablesize = 0, snapshots = 0;
char word[256];
htable ht;
setup(argc, argv, &double_hashing, &entire_table, &print_stats,
&snapshots, &tablesize);
ht = htable_new(tablesize, (double_hashing) ? DOUBLE_H : LINEAR_P);
while (getword(word, sizeof word, stdin) != EOF) {
htable_insert(ht, word);
}
if (entire_table) {
htable_print_entire_table(ht, stderr);
}
if (print_stats) {
htable_print_stats(ht, stdout, snapshots);
} else {
htable_print(ht, stdout); /* print words and frequencies */
}
htable_free(ht);
return EXIT_SUCCESS;
}
/**
* Prints out a usage message to stderr outlining all of the options.
* #param prog_name the name of the program to include in usage message.
*/
static void usage(char *prog_name) {
fprintf(stderr, "Usage: %s [OPTION]... <STDIN>\n\n%s%s", prog_name,
"Perform various operations using a hash-table. By default read\n"
"words from stdin and print them with their frequencies to stdout.\n\n"
" -d Use double hashing (linear probing is the default)\n"
" -e Display entire contents of hash-table on stderr\n",
" -n NUM Show NUM stats snapshots (if -p is used)\n"
" -p Print stats info instead of frequencies & words\n"
" -s SIZE Use the first prime >= SIZE as htable size\n\n"
" -h Display this message\n\n");
}
/**
* Handle options given on the command-line by setting a number of
* variables appropriately. May call usage() if incorrect arguments
* or -h given.
*
* #param argc the number of command-line arguments.
* #param argv an array of strings contain the command-line arguments.
* #param double_hashing set to TRUE if -d given
* #param entire_table set to TRUE if -e given
* #param snapshots set to NUM if -n NUM given and NUM > 0 else set to 10
* #param print_stats set to TRUE if -p given
* #param tablesize set to SIZE if -t SIZE given and SIZE > 0 else set to 113
*/
static void setup(int argc, char **argv, bool_t *double_hashing,
bool_t *entire_table, bool_t *print_stats,
int *snapshots, int *tablesize) {
const char *optstring = "dehpn:s:";
char option;
while ((option = getopt(argc, argv, optstring)) != EOF) {
switch (option) {
case 'd':
*double_hashing = TRUE;
break;
case 'e':
*entire_table = TRUE;
break;
case 'p':
*print_stats = TRUE;
break;
case 'n':
*snapshots = atoi(optarg);
break;
case 's':
*tablesize = atoi(optarg);
break;
case 'h':
default:
usage(argv[0]);
exit(EXIT_SUCCESS);
}
}
/* set default values if nothing sensible entered */
if (*tablesize < 1) *tablesize = 113;
if (*snapshots < 1) *snapshots = 10;
}
mylib.c
#include <stdlib.h>
#include "mylib.h"
/**************************
* *
* emalloc *
* *
**************************
Used to handle new memory allocation to a pointer and handle exceptions
which may arrise if memory allocation fails, which happens all the time
when you try and enter negative values.
PARAMETERS: s = calculated size of required memory.
RETURN VALUE: a pointer of any type.
*/
void *emalloc(size_t s){
void *result = malloc(s);
if(NULL == result){
fprintf(stderr, "Memory allocation failed!\n");
exit(EXIT_FAILURE);
}
return result;
}
/**************************
* *
* erealloc *
* *
**************************
Handles the reallocation of an updated amount of memory to an existing
with existing data attached.
PARAMETERS: p = the existing pointer we would like additional memory
allocated to.
s = calculated size of required memory.
RETURN VALUE: a pointer of any type.
*/
void *erealloc(void *p, size_t s){
void *result = realloc(p,s);
if(NULL == result){
fprintf(stderr, "Memory allocation failed!\n");
exit(EXIT_FAILURE);
}
return result;
}
/**************************
* *
* getword *
* *
**************************
Is used to read input from the designated file stream (standard in for the
assignment). Getword removes white space with the first while loop. And only
returns one word. Maintaining continous input is therefore the responsibility
of the calling function.
PARAMETERS: s = the pointer to the character array.
limit = the maximum size a word can be.
stream = where to read from.
RETURN VALUE: the integer value of the character at s[0]. The string s does
not need to be returned, since it is an array and is passed as
a memory address. If no chars were read into the string s, then
s[0] would have the '\0' [NULL] value which equates to 0 if used
in a boolean equation.
*/
int getword(char *s, int limit, FILE *stream){
int c;
while(!isalnum( c = getc(stream)) && c != EOF);
if(c == EOF)
return EOF;
else
*s++ = tolower(c);
while(--limit > 0){
if(isalnum(c = getc(stream)))
*s++ = tolower(c);
else if('\'' == c) continue;
else break;
}
*s = '\0';
return s[0];
}
/**************************
* *
* stoi *
* *
**************************
Not using this function now.
PARAMETERS: s = string representation of a number.
RETURN VALUE: the integer value.
*/
int stoi(char *s){
int i,j,r;
int sign = 1;
i=1;
r=0;
for(j=my_strlen(s)-1; j>=0; j--){
if(j == 0 && s[j] == '-')
sign = -1;
else {
if(s[j]>='0' && s[j]<='9'){
r+=((s[j]-'0')*i);
i*=10;
} else {
fprintf(stderr, "Invalid input for String to int\n");
exit(EXIT_FAILURE);
}
}
}
return r * sign;
}
/**************************
* *
* my_strlen *
* *
**************************
I am using my own string length function, but I wrote it with the stoi
function, so am using it here. Perhaps not as safe as the library
functions?
PARAMETERS: s = a string delimited by the NULL character.
RETURN VALUE: the number of characters in the string.
*/
int my_strlen(char *s){
int i=0;
while(s[i]!='\0')
i++;
return i;
}
/**************************
* *
* factors *
* *
**************************
Another unrequired function used to calculate the possiblity of factorisation.
PARAMETERS: x = An integer to be factored towards.
RETURN VALUE: 0 if x has factors, 1 if x is a prime number.
*/
static int factors(int x){
int f = 2;
while(f*f < x){
if(x % f == 0){
return 0;
} else {
f++;
}
}
return 1;
}
/**************************
* *
* prime_gt *
* *
**************************
Used in conjunction with factors to find factorless integers. We increment
bound until it is truely prime.
Bound - We start with bound, sending it to the factors function. If it is
a prime number, then stop searching. Otherwise loop until we find
an prime integer larger than the input integer.
PARAMETERS: s = the input integer.
RETURN VALUE: Bound, for it is now a prime number.
*/
static int prime_gt(int s){
int bound = s;
while(bound > 0){
if(factors(bound))
break;
else
bound++;
}
return bound;
}
/**************************
* *
* relative_prime *
* *
**************************
Decides on a prime number to use to set the table size to.
PARAMETERS: s = the required size of the table.
RETURN VALUE: the newer beter prime number size for the table.
*/
unsigned int relative_prime(int s){
return prime_gt(s);
}
Sorry for it being so big, it's ok if it's just a complete unfixable jumble.
You don't seem to have defined struct hashtable anywhere. You need to say somewhere what fields that struct should actually contain, at the moment there is only a forward declaration in htable.h.
Such a forward declaration just says that the type exists, but not how it exactly looks like. Therefore it is considered an incomplete type, until the compiler sees a full definition of it.
Cause the definition of struct hashtable does not exist, the following line creates an alias of an incomplete pointer type (htable).
typedef struct hashtable *htable;
It is impossible to deference such pointer (the compiler doesn't know the different fields of your structure).
In your file htable.c, maybe you meant :
/* instead of struct htablered */
struct htable {
int size;
int num_entries;
hashing_t method;
char **keys;
int *freqs;
int *stats;
};

Implementing LRU page replacement algorithm

Edited to include short description of what is expected from the code.
#include <sys/file.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#define MAX_PAGE 0xFF+1
/* page table entry you may need to add your own fields to it*/
typedef struct
{
unsigned short frame;/*location*/
unsigned int valid:1;
unsigned int in_mem:1;
unsigned int dirty:1;
unsigned int last_frame;
} pt_entry;
/* list entry for physical frames*/
struct list_item
{
unsigned short frame;
struct list_item *next;
struct list_item *prev;
int page_num;
};
typedef struct list_item *list;
void start_simulation(FILE *);
void resolve(int);
unsigned short find_frame(void);
unsigned short find_victim(void);
void display_stats(void);
void to_resident_set(list);
void free_mem(list);
void invalidate(unsigned short);
/*============================ header ends here ============================== *
/*#include "lru.h"*/
pt_entry pte[MAX_PAGE]; /* page table */
int mem_size; /* physical memory size in page frames */
list free_list_head; /* free list */
list res_set_head; /* resident set */
int total_fault = 0; /* total number of page faults */
int total_ref = 0; /* total number of memory references */
/* main program:
** read in paramters, and open the input file start the simulation */
int main(int argc, char *argv[])
{
FILE *stream;
if (argc != 3)
{
printf("The format is: pager file_name memory_size.\n");
exit(1);
}
printf("File used %s, resident set size %d\n", argv[1], atoi(argv[2]));
if ((stream = fopen(argv[1], "r")) == NULL)
{
perror("File open failed");
exit(1);
}
mem_size = atoi(argv[2]);
start_simulation(stream);
fclose(stream);
}
/*initialise the page table
** initialise the resident set, and the free list
** in the simulation loop
**16-bit memory addresses representing the program trace are read from the input
**file one by one the virtual address is resolved ie. physical frame for the
**virtual page identified
**the loop exits when it encounters the end of file
** free memory allocated for lists
** display statistics
*/
void start_simulation(FILE * stream)
{
char *addr_buf;
int address;
int i, n;
list new_entry, current;
/* initialise the page table */
for(i=0; i<MAX_PAGE;i++)
{
pte[i].frame = -1;
pte[i].valid = 0;
pte[i].dirty = 0;
pte[i].in_mem = 0;
}
/* initialise the resident set - empty*/
res_set_head = (list)malloc(sizeof(struct list_item));
res_set_head->next = res_set_head;
res_set_head->prev = res_set_head;
/* initialise free list - all physical pages*/
free_list_head = (list)malloc(sizeof(struct list_item));
free_list_head->next = free_list_head;
free_list_head->prev = free_list_head;
current = free_list_head;
for(i=0; i<mem_size;i++)
{
new_entry = (list)malloc(sizeof(struct list_item));
current->next = new_entry;
new_entry->prev = current;
new_entry->next = free_list_head;
new_entry->frame = i;
current = new_entry;
free_list_head->prev = current;
}
/* main simulation loop */
while( (n = fscanf(stream, "%x", &address)) != -1)
{
resolve(address);
total_ref++;
}
free_mem(free_list_head);
free_mem(res_set_head);
display_stats();
return;
}
/* resolve address reference
** if page table entry valid - do nothing
** if page table entry invalid - find a physical frame for this page
**and update pte for the page
*/
void resolve(int address)
{
unsigned short frame_alloc;
int virt_page;
static int disp_counter = 0;
virt_page = address >> 8;
if (pte[virt_page].valid == 1)
{
/*Was trying to implement */
//pte[virt_page].frame = pte[0];
}
else
{
frame_alloc = find_frame();
pte[virt_page].valid = 1;
pte[virt_page].frame = frame_alloc;
total_fault++;
}
}
/* find_frame:
** if free list is empty find a victim frame
** else detach the last frame of the free list and attach it
** to the resident set
** return frame number
*/
unsigned short find_frame()
{
unsigned short frame;
list current, new_tail;
if (free_list_head == free_list_head->prev) /* free list empty */
frame = find_victim();
else
{
new_tail = free_list_head->prev->prev;
new_tail->next = free_list_head;
current = free_list_head->prev;
free_list_head->prev = new_tail;
to_resident_set(current);
frame = current->frame;
}
return frame;
}
/* to_resident_set:
** attach a list entry at the end of resident set
*/
void to_resident_set(list current)
{
list tail;
tail = res_set_head->prev;
tail->next = current;
current->next = res_set_head;
current->prev = tail;
res_set_head->prev = current;
}
/* find_victim:
** As you can see I simply take the first page frame from the resident set list.
** This implements the FIFO replacement strategy. Your task is to replace it with
** a more efficient strategy.
*/
unsigned short find_victim()
{
int i;
unsigned short frame=0;
list current;
for(i=0;i<MAX_PAGE;i++)
{
if (pte[i].frame == frame && pte[i].valid == 1)
{
frame = res_set_head->next->frame;
invalidate(frame);
current = res_set_head->next;
res_set_head->next = current->next;
res_set_head->next->prev = res_set_head;
to_resident_set(current);
break;
}
}
return frame;
}
/* invalidate:
** invalidate the page table entry for the victim page */
void invalidate(unsigned short frame)
{
int i;
for(i=0;i<MAX_PAGE;i++)
{
if (pte[i].frame == frame && pte[i].valid == 1)
{
pte[i].valid = 0;
pte[i].frame = -1;
break;
}
}
}
/* display_stats:
** This is very basic, you may want to make it more sophisticated,
** for example save the data from multiple runs into a file for
** comparison etc
*/
void display_stats()
{
printf("\nProcess issued %d memory references\n", total_ref);
printf("Process triggered %d page faults\n", total_fault);
printf("Pafe fault rate is %d percent\n",((total_fault*100)/total_ref));
}
/* free memory allocated to the list */
void free_mem(list head)
{
list current,tail;
tail = head->prev;
current = head;
while (current->prev != tail)
{
current = current->next;
free(current->prev);
}
}
The most obvious problem lies in the input to your algorithm.
The restpage array is a global array and will thus be initialised to contain only the value 0. You then use these array elements as the page-numbers you are requesting, which means that your algorithm processes only requests for page 0 if mem_size < 100.
And if mem_size >= 100, you are overrunning the array bounds and land squarely in the land of undefined behaviour.
There are two fixes you need to make:
Just as you are checking for a valid file in the command-line arguments, you must also check that mem_size is not too large
Write an additional loop to give each element in restpage a random value, to ensure not all page requests are for the same page.
You have dimensioned restpage to [100] but mem_size seems freely configurable, is this the intent?
mem_size = atoi(argv[2]);
fclose(stream);
..
for(i=0;i<mem_size;i++)
{
totalabsence+=find_victim(&pt,restpage[i]);
}
EDIT:
I see one bug in your new code, in your find_victim you don't initialize the local variable 'frame'
EDITx2:
When you read from the file you may just want to put one hex address on each line
and use instead fgets() to read the file line by line (or load the whole file and
go through it line by line).

Resources