Files#
Viewed as streams of bytes
All functions are defined at <stdio.h>
Files have a name in the OS; represented in C by a FILE structure (which describes their current state)
They require opening/closing
Can be opened for read/write/append
Working with Files#
FILE *fopen(const char *filename, const char *mode)
/*returns a pointer to the opened file or NULL on failure*/
int *fclose(FILE *fp)
/*returns 0 on success or EOF on failure*/
#include <stdio.h>
int main(void)
{
FILE *ifp = NULL;
ifp = fopen("my_file", "r");/*Modes: r, w, a, r+, w+, a+*/
assert(ifp != NULL);
fclose(ifp);
}
Character-wise Read/Write#
int fgetc( FILE *);
int fputc( int, FILE*);
Example: Double-Spacing a File#
The program:
Reads the contents of an input file (infile).
Writes the contents to an output file (outfile), adding an extra newline after each existing newline (i.e., double-spacing the file).
main()#
#include <stdio.h>
#include <stdlib.h>
// Function prototypes
void double_space(FILE *ifp, FILE *ofp);
void prn_info(const char *pgm_name);
void prn_err_msg(const char *file_name);
int main(int argc, char **argv)
{
int rtVal = 0; // Return value for program exit
FILE *ifp = NULL, *ofp = NULL; // File pointers
// Ensure the program is invoked with the correct number of arguments
if (argc == 3)
{
ifp = fopen(argv[1], "r"); // Open input file in read mode
if (ifp != NULL)
{
ofp = fopen(argv[2], "w"); // Open output file in write mode
if (ofp != NULL)
{
double_space(ifp, ofp); // Perform double-spacing
fclose(ofp); // Close output file
}
else
rtVal = 2; // Error opening output file
fclose(ifp); // Close input file
}
else
rtVal = 1; // Error opening input file
}
else
{
rtVal = -1; // Incorrect usage
prn_info(argv[0]); // Print usage instructions
}
// Print error message if applicable
if (rtVal > 0)
prn_err_msg(argv[rtVal]);
return rtVal; // Return appropriate exit code
}
prn_info()#
Prints usage instructions to the user if the program is invoked incorrectly.
void prn_info(const char *pgm_name)
{
printf("\nUsage: %s infile outfile\n", pgm_name);
printf("The contents of infile will be double-spaced and written to outfile.\n");
}
prn_err_msg()#
Prints a specific error message if a file cannot be opened.
void prn_err_msg(const char *file_name)
{
printf("\nError: Could not open file %s\n", file_name);
}
double_space()#
void double_space(FILE *ifp, FILE *ofp)
{
int c = 0;
// Read input file character by character
while ((c = fgetc(ifp)) != EOF)
{
fputc(c, ofp); // Write character to output file
if (c == '\n') // If newline is encountered, add another newline
fputc('\n', ofp);
}
}
# @title
%%writefile double_space.c
#include <stdio.h>
#include <stdlib.h>
// Function prototypes
void double_space(FILE *ifp, FILE *ofp);
void prn_info(const char *pgm_name);
void prn_err_msg(const char *file_name);
int main(int argc, char **argv)
{
int rtVal = 0; // Return value for program exit
FILE *ifp = NULL, *ofp = NULL; // File pointers
// Ensure the program is invoked with the correct number of arguments
if (argc == 3)
{
ifp = fopen(argv[1], "r"); // Open input file in read mode
if (ifp != NULL)
{
ofp = fopen(argv[2], "w"); // Open output file in write mode
if (ofp != NULL)
{
double_space(ifp, ofp); // Perform double-spacing
fclose(ofp); // Close output file
}
else
rtVal = 2; // Error opening output file
fclose(ifp); // Close input file
}
else
rtVal = 1; // Error opening input file
}
else
{
rtVal = -1; // Incorrect usage
prn_info(argv[0]); // Print usage instructions
}
// Print error message if applicable
if (rtVal > 0)
prn_err_msg(argv[rtVal]);
return rtVal; // Return appropriate exit code
}
void prn_info(const char *pgm_name)
{
printf("\nUsage: %s infile outfile\n", pgm_name);
printf("The contents of infile will be double-spaced and written to outfile.\n");
}
void prn_err_msg(const char *file_name)
{
printf("\nError: Could not open file %s\n", file_name);
}
void double_space(FILE *ifp, FILE *ofp)
{
int c = 0;
// Read input file character by character
while ((c = fgetc(ifp)) != EOF)
{
fputc(c, ofp); // Write character to output file
if (c == '\n') // If newline is encountered, add another newline
fputc('\n', ofp);
}
}
Cell In[1], line 6
// Function prototypes
^
SyntaxError: invalid syntax
# @title
!gcc double_space.c -o double_space
!./double_space infile.txt outfile.txt
Formatted IO#
int fprintf( FILE *fp, const char *control_string, ...);
int fscanf( FILE *fp, const char *control_string, ...);
FILE *fp = fopen("output.txt", "w");
if (fp != NULL)
{
int age = 25;
char name[] = "Alice";
fprintf(fp, "Name: %s, Age: %d\n", name, age);
fclose(fp);
}
Example: Sum of values#
#include <stdio.h>
int main(void)
{
int a = 0, sum = 0;
FILE *ifp = NULL, *ofp = NULL;
ifp = fopen("my_file", "r");
ofp = fopen("outfile", "w");
...
while (fscanf(ifp, "%d", &a) == 1)
{
sum += a;
}
fprintf(ofp, "The sum is %d.\n", sum);
fclose(ifp);
fclose(ofp);
return 0;
}
Standard file pointers#
In stdio.h:
stdin standard input file connected to the keyboard
stdout standard output file connected to the screen
stderr standard error file connected to the screen
fprintf( stdout, ... ); /*is equivalent to*/ printf( ....);
fscanf( stdin, ...); /*is equivalent to*/ scanf( .... );
Binary files#
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
Reads at most size*nmemb bytes (characters) from the file *stream into the array ptr. Reading stops when EOF is encountered. Returns the number of read bytes.
size_t fwrite(void *ptr, size_t size, size_t nmemb, FILE *stream);
Writes the first size*nmemb bytes in the array ptr into the file *stream. Returns the number of successfully written bytes.
# @title
%%writefile write_binary.c
#include <stdio.h>
#include <stdlib.h>
// Define a student structure
typedef struct {
int id;
char name[50];
float grade;
} Student;
int main() {
Student students[] = {
{1, "Alice", 90.5},
{2, "Bob", 85.3},
{3, "Charlie", 78.9}
};
FILE *file = fopen("students.dat", "wb");
if (!file) {
perror("Error opening file");
return 1;
}
// Write array of structures to the binary file
fwrite(students, sizeof(Student), 3, file);
fclose(file);
printf("Data written to binary file successfully.\n");
return 0;
}
# @title
!gcc write_binary.c -o write_binary
!./write_binary
# @title
%%writefile read_binary.c
#include <stdio.h>
#include <stdlib.h>
// Define a student structure
typedef struct {
int id;
char name[50];
float grade;
} Student;
int main() {
Student students[3]; // Array to hold the data read
FILE *file = fopen("students.dat", "rb");
if (!file) {
perror("Error opening file");
return 1;
}
// Read array of structures from the binary file
fread(students, sizeof(Student), 3, file);
fclose(file);
// Print the read data
printf("Student Records:\n");
for (int i = 0; i < 3; ++i) {
printf("ID: %d, Name: %s, Grade: %.2f\n",
students[i].id, students[i].name, students[i].grade);
}
return 0;
}
# @title
!gcc read_binary.c -o read_binary
!./read_binary
Change the Case of Letters in a File#
#include <ctype.h>
#include <stdio.h>
#include <assert.h>
#define BUFSIZE 1024
int main(int argc, char **argv)
{
char mybuf[BUFSIZE] = { 0 }, *p = NULL;
FILE *ifp = NULL, *ofp = NULL;
int n = 0;
ifp = fopen(argv[1], "r"); /*open the file for reading*/
ofp = fopen(argv[2], "w"); /*open the file for writing*/
assert(ifp != NULL);
assert(ofp != NULL);
while ((n = fread(mybuf, sizeof(char), BUFSIZE, ifp)) > 0) /*read from the file*/
{
for (p = mybuf; p - mybuf < n; ++p)
{
if (islower(*p)) *p = toupper(*p);
else if (isupper(*p)) *p = tolower(*p);
}
fwrite(mybuf, sizeof(char), n, ofp); /*write to the file*/
}
/*close the files*/
fclose(ifp);
fclose(ofp);
return 0;
}
Random access to files: fseek and ftell#
/* no need to define!!! already defined
#define SEEK_SET 0 beginning of the file
#define SEEK_CUR 1 current position in the file
#define SEEK_END 2 end of the file
*/
int fseek(FILE *fp, long offset, int place);
(returns 0 on success and non-zero on failure)
void rewind(FILE *fp);
long ftell(FILE *fp);
(returns current position or -1 on failure)
Example: Write a File Backwards#
#include <stdio.h>
#include <assert.h>
#define MAXSTRING 100
int main(void) {
char file_name[MAXSTRING] = {0};
int c = 0;
FILE *ifp = NULL;
printf("\nInput a file name: ");
scanf("%s", file_name);
ifp = fopen(file_name, "r");
assert(ifp != NULL);
// Move to the end of the file
fseek(ifp, 0, SEEK_END);
// Get the file size
long pos = ftell(ifp);
// Backtrack through the file
while (pos > 0) {
fseek(ifp, -1, SEEK_CUR); // Move back one character
c = fgetc(ifp); // Read the character
putchar(c); // Print it
fseek(ifp, -1, SEEK_CUR); // Adjust position for the next iteration
pos--;
}
fclose(ifp);
return 0;
}
Additional IO functions#
int feof(FILE *fp);
/*non-zero when true and 0 when false*/
char *fgets(char *buf, int buf_size, FILE *fp);
/*appends ‘\0’; returns buf on success and NULL o/w*/
int fputs(const char *str, FILE *fp)
/*removes ‘\0’; returns >=0 on success and EOF o/w*/
int fflush(FILE *fp)
/*flushes on writing; returns 0 on success and EOF o/w*/
int sprintf(char *s , const char *format, ...);
int sscanf(const char *s, const char *format, ...);