如何返回指向缓冲区中位置的指针?

时间:2018-02-07 15:13:57

标签: c pointers buffer

我目前正在使用C创建一个缓冲程序所需的项目。在大多数情况下,我的程序已经完成,但我只缺少一个必需的函数:一个位置函数,用于返回头部(数组的开头)到short loc_offset指定的所需位置之间的距离。 鉴于我已经拥有的东西,我如何从我的短片中返回指向索引或位置的指针? 这是我给出和创建的代码: 主要(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;
}

该主文件没有错误或警告,它被授予我用作我的主要文件。 这是我编辑的源文件(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;
}

最后我的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

所以,我需要在b_location函数中找到loc_offset的位置并将其作为指针返回。提前谢谢!

1 个答案:

答案 0 :(得分:1)

custom action