This is a small template file I wrote to refresh my memory on how we handle pointers in C. It is not by any means a tutorial. Rather, if I need to do some file I/O or pass pointers to strings around between functions, this is really just to remind me how it is done. It should compile just fine on any GNU Linux machine with gcc:
# gcc -o file-io file-io.c
So why include C source code in a blog for topics in system administration; isn't that really a developer's topic? Strictly speaking it is development. The reality, however is that in most organizations, the development staff tends to be focused upon development of systems that directly generate revenue. Developer salaries generally run higher on average, so the appropriate use of that resource is in generating revenue, not maintaining infrastructure (this is not to say that the developer function is more important than management of infrastructure; just more costly). So, when the system administrator needs to retrofit some behavior in the operating system, he or she needs to understand at least some C, or rely upon someone else to have already developed a solution/workaround. In addition, since this blog is really focused upon Open Source administration, and Linux, as well as other operating systems are heavy in C, you should not be surprised to see the occasional C programming entry here.
One of the things you might notice is that I've abstracted simple functions like fprintf() and getline(). I can't imagine any reason to do this in a real project; it amounts to just code bloat. The only reason I've done that is to show not only how to pass pointers into functions, but also how to manipulate the data they represent inside the function. I also go a little overboard with variable naming, and comments. That's really just a style thing for me. I like the code to be crystal clear, so I can spend all my cognitive capital thinking about the problem space, rather than code details.
On to the file-io.c code (or as I like to call it, 94 lines to pointer nirvana):
==BEGIN==
/* file-io.c
** Template for handling file I/O in C using pointers & functions.
*/
/*--------------------------- includes -------------------------------*/
#include <stdio.h>
#include <stdlib.h>
/*---------------------------- defines -------------------------------*/
#define MODE_APPEND "a"
#define MODE_READONLY "r"
#define MODE_READWRITE "rw"
/*---------------------- function prototypes -------------------------*/
int iWriteLineToFile(FILE *, char *);
int iReadLineFromFile(char **line, size_t *n, FILE *stream);
void vOpenFile(FILE **fp, const char *filename, char *mode);
void vCloseFile(FILE *fp, const char *filename);
/*--------------------------------------------------------------------*/
/*---------------------------- main() --------------------------------*/
/*--------------------------------------------------------------------*/
int main(void)
{
/* Declare & initialize our variables */
char *sLine; /* any line of text */
size_t iLength = NULL; /* size of buffer allocated */
FILE *fpOut; /* output file pointer */
FILE *fpIn; /* input file pointer */
int iInRetVal = 0; /* return value of writes */
int iOutRetVal = 0; /* return value of writes */
const char *sOutFile = ""; /* name of the file to write to */
const char *sInFile = ""; /* name of the file to read from */
sOutFile = "./output.txt";
sInFile = "./input.txt";
vOpenFile(&fpIn, sInFile, MODE_READONLY);
vOpenFile(&fpOut, sOutFile, MODE_APPEND);
iInRetVal = iReadLineFromFile(&sLine, &iLength, fpIn);
iOutRetVal = iWriteLineToFile(fpOut, sLine);
free(sLine); //good boys & girls clean up after themselves...
vCloseFile(fpOut, sOutFile);
vCloseFile(fpIn, sInFile);
return iInRetVal + iOutRetVal;
}
/*--------------------------------------------------------------------*/
/*---------------------- iWriteLineToFile() --------------------------*/
/*--------------------------------------------------------------------*/
int iWriteLineToFile(FILE *fpOut, char *sLine)
{
if(fprintf(fpOut, "%s", sLine) < 0)
return(EXIT_FAILURE);
else
return(EXIT_SUCCESS);
}
/*--------------------------------------------------------------------*/
/*---------------------- iReadLineFromFile() -------------------------*/
/*--------------------------------------------------------------------*/
int iReadLineFromFile(char **sLine, size_t *iN, FILE *fpIn)
{
if(getline(sLine, iN, fpIn) < 0)
return(EXIT_FAILURE);
else
return(EXIT_SUCCESS);
}
/*--------------------------------------------------------------------*/
/*------------------------- vOpenFile() ------------------------------*/
/*--------------------------------------------------------------------*/
void vOpenFile(FILE **fp, const char *sFilename, char *cMode)
{
if((*fp = fopen(sFilename, cMode)) == NULL)
{
fprintf(stderr, "Failure opening %s\n", sFilename);
exit(EXIT_FAILURE);
}
}
/*--------------------------------------------------------------------*/
/*------------------------- vCloseFile() -----------------------------*/
/*--------------------------------------------------------------------*/
void vCloseFile(FILE *fp, const char *sFilename)
{
if (fclose(fp) == -1)
{
fprintf(stderr, "Failure closign %s\n",sFilename);
exit(EXIT_FAILURE);
}
}
==END==
This code is free to use for any purpose, and without consent. Enjoy!
Update 2/8/2017: Updated iReadLineFromFile to return either EXIT_SUCCESS or EXIT_FAILURE, rather than the count of characters read. This makes the final return code from the application 0 upon success.
No comments:
Post a Comment