1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | #include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
/* This is part 2 of a 3-part series of snippets illustrating how to handle
* runtime errors without obscuring the core logic of the function. This
* illustrates how to use a helper function to make a newly allocated copy of a
* given string on the heap.
*/
typedef struct {
int x, y, z; // separate lines is preferable, but this is ok for lecture
char name[255]; // do not declare strings like this in production code (security risk)
} ThreeDNamedPoint;
// _strdup(…) makes a copy of a string on the heap. Caller is responsible for freeing.
//
// You may use or adapt the _strdup(…) function in your code.
char* _strdup(const char* s) { // caller is responsible for freeing memory
char* s_copy = malloc(sizeof(*s_copy)*(strlen(s) + 1));
strcpy(s_copy, s);
return s_copy;
}
bool write_point(ThreeDNamedPoint p, char* filename, char** error) { // 14 lines
// Open file
FILE* fp = fopen("tdnp.bin", "w");
// Error handler #1: Make sure object was written successfully.
if(fp == NULL) {
*error = _strdup("cannot open file");
return false; // failure
}
// Error handler #2: Make sure object was written successfully.
size_t num_written = fwrite(&p, sizeof(p), 1, fp);
if(num_written != 1) {
*error = _strdup("unable to write to file");
return false; // failure
}
fclose(fp);
return true;
}
///////////////////////////////////////////////////////////////////////
void _print_point(ThreeDNamedPoint p_orig) {
printf("x=%d, y=%d, z=%d, name=%s\n", p_orig.x, p_orig.y, p_orig.z, p_orig.name);
}
int main(int argc, char* argv[]) {
// Create a ThreeDNamedPoint object
ThreeDNamedPoint p_orig = {.x=5, .y=6, .z=7, .name="polyester"};
// Write the point to a binary file.
char* error = NULL;
write_point(p_orig, "tdnp.bin", &error);
// Handle errors -- if any, print the message and exit
if(error != NULL) {
fprintf(stderr, "Error: %s\n", error);
free(error); // free the memory for the error message
return EXIT_FAILURE;
}
// Read the ThreeDNamedPoint from the binary file created above into a new object.
// It would be better to do this in a separate function, similar to write_point(…).
FILE* fp = fopen("tdnp.bin", "r");
ThreeDNamedPoint p_copy; // not initializing because fread(…) will do that for us
fread(&p_copy, sizeof(p_copy), 1, fp); // essentially copies bytes from disk to memory
fclose(fp);
// Print the original object and the copy made when we read it from disk, to visually
// confirm that they are the same.
_print_point(p_orig);
_print_point(p_copy);
return EXIT_SUCCESS;
}
/* vim: set tabstop=4 shiftwidth=4 fileencoding=utf-8 noexpandtab: */
|
© Copyright 2017 Alexander J. Quinn This content is protected and may not be shared, uploaded, or distributed.