You could first read the file contents into a buffer. Then you could parse and insert data from this buffer into some data structure, such as an array of structs. Once you have that, you can just rewrite the filtered contents back to the file.
Below is some sample code(tweaked) that I wrote a while ago that does something similar to what you want. It takes in 2 command line arguements as input. The first is the file to read from, and the second one is the data to not include, in your case the chair value. You can amend it to read from stdin
if you wanted to.
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define START_SIZE 10;
#define BASE 10
typedef struct {
char *chair;
int number;
char *name;
} data_t;
typedef struct {
data_t *data;
size_t n;
} file_data_t;
char *get_file_contents(const char *);
file_data_t *insert_data(char *, const char *);
int main(int argc, char *argv[]) {
// Check arguments
if (argc != 3) {
fprintf(stderr, "Usage: ./deletefile [file] [chair]\n");
exit(EXIT_FAILURE);
}
// Get buffer
char *buffer = get_file_contents(argv[1]);
// Get structure holding data
file_data_t *file_data = insert_data(buffer, argv[2]);
// Free buffer
free(buffer);
// Open file to write to
FILE *fp = fopen(argv[1], "w");
if (fp == NULL) {
fprintf(stderr, "Count not open file\n");
exit(EXIT_FAILURE);
}
// Write to file, and free contents
for (size_t i = 0; i < file_data->n; i++) {
fprintf(fp, "-.\nChair: %s\nNumber: %d\nName: %s\n",
file_data->data[i].chair,
file_data->data[i].number,
file_data->data[i].name);
free(file_data->data[i].chair);
free(file_data->data[i].name);
}
// Free everything else
free(file_data->data);
free(file_data);
fclose(fp);
return EXIT_SUCCESS;
}
file_data_t *insert_data(char *buffer, const char *dont_keep) {
size_t buffsize = START_SIZE;
const char *delim_section = "-.", *delim_line = "\n";
const char delim_colon = ':';
char *token = NULL;
char *rest = buffer;
size_t count = 0;
// Create main structure
file_data_t *file_data = malloc(sizeof *file_data);
if (file_data == NULL) {
fprintf(stderr, "Could not allocate file data\n");
exit(EXIT_FAILURE);
}
// Allocate data elements
file_data->data = malloc(buffsize * sizeof *file_data->data);
if (file_data->data == NULL) {
fprintf(stderr, "Could not allocate %zu bytes for data\n", buffsize);
exit(EXIT_FAILURE);
}
while ((token = strtok_r(rest, delim_section, &rest)) != NULL) {
// Reallocate data if necessary
if (count == buffsize) {
buffsize *= 2;
void *ptr = realloc(file_data->data, buffsize * sizeof *file_data->data);
if (ptr == NULL) {
fprintf(stderr, "Could not reallocate %zu bytes for buffer\n", buffsize);
exit(EXIT_FAILURE);
}
file_data->data = ptr;
}
char *saveptr = NULL, *endptr = NULL;
// Parse chair
char *chair = strtok_r(token, delim_line, &saveptr);
char *chair_value = strchr(chair, delim_colon);
chair_value += 2;
// If chair value is not the same as dont_keep, proceed
if (strcmp(chair_value, dont_keep) != 0) {
// Copy chair value over
file_data->data[count].chair = strdup(chair_value);
if (file_data->data[count].chair == NULL) {
fprintf(stderr, "Could not copy chair buffer\n");
exit(EXIT_FAILURE);
}
// Parse number
char *number = strtok_r(NULL, delim_line, &saveptr);
char *number_value = strchr(number, delim_colon);
number_value += 2;
// Convert number to integer
long val = strtol(number_value, &endptr, BASE);
// Didnt find a value number
if (endptr == number_value || *endptr != '\0') {
fprintf(stderr, "Count not parse number\n");
exit(EXIT_FAILURE);
}
// Add number value
file_data->data[count].number = val;
// Parse name
char *name = strtok_r(NULL, delim_line, &saveptr);
char *name_value = strchr(name, delim_colon);
name_value += 2;
// Copy name over
file_data->data[count].name = strdup(name_value);
if (file_data->data[count].name == NULL) {
fprintf(stderr, "Coul not copy name buffer\n");
exit(EXIT_FAILURE);
}
// Increment count
count++;
}
}
file_data->n = count;
return file_data;
}
char *get_file_contents(const char *path) {
// Open file
FILE *fp = fopen(path, "r");
if (fp == NULL) {
fprintf(stderr, "Failed to open %s\n", path);
exit(EXIT_FAILURE);
}
// Go to end of file
int end = fseek(fp, 0L, SEEK_END);
if (end != 0) {
fprintf(stderr, "Could not go to end of file\n");
exit(EXIT_FAILURE);
}
// Get size of file
long buffsize = ftell(fp);
if (buffsize == -1) {
fprintf(stderr, "Count not get size of file\n");
exit(EXIT_FAILURE);
}
// Allocate buffer
char *buffer = malloc(buffsize + 1);
if (buffer == NULL) {
fprintf(stderr, "Could not allocate %ld bytes for buffer\n", buffsize);
exit(EXIT_FAILURE);
}
// Go back to start of file
int start = fseek(fp, 0L, SEEK_SET);
if (start != 0) {
fprintf(stderr, "Could not go to start of file\n");
exit(EXIT_FAILURE);
}
// Read contents of file
size_t newlen = fread(buffer, 1, buffsize, fp);
if (ferror(fp) != 0) {
fprintf(stderr, "Error reading contents of file into buffer\n");
exit(EXIT_FAILURE);
}
fclose(fp);
// Null terminate buffer
buffer[newlen++] = '\0';
return buffer;
}
Output:
$ cat file.txt
-.
Chair: A23
Number: 123
Name: Joshua
-.
Chair: B12
Number: 512
Name: Marcus
-.
Chair: C2
Number: 1
Name: Drake
$ gcc -Wall -Wextra -o deletefile deletefile.c
$ ./deletefile file.txt B12
$ cat file.txt
-.
Chair: A23
Number: 123
Name: Joshua
-.
Chair: C2
Number: 1
Name: Drake
Note: The above code is not the best way to do this task, and can certainly be improved. You can use this as a base, and improve upon it.