你可以先将文件内容读入缓冲区。然后,你可以从这个缓冲区解析并插入数据到某个数据结构中,比如一个结构体数组。一旦你拥有了这个数据结构,你就可以将过滤后的内容重写回文件。
以下是我之前编写的一些示例代码(稍作调整),它与你想要的功能类似。它以两个命令行参数作为输入。第一个参数是要读取的文件,第二个参数是要排除的数据,在你的情况下是“chair”值。如果你愿意,你可以修改它以从标准输入读取。
#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[]) {
if (argc != 3) {
fprintf(stderr, "Usage: ./deletefile [file] [chair]\n");
exit(EXIT_FAILURE);
}
char *buffer = get_file_contents(argv[1]);
file_data_t *file_data = insert_data(buffer, argv[2]);
free(buffer);
FILE *fp = fopen(argv[1], "w");
if (fp == NULL) {
fprintf(stderr, "Count not open file\n");
exit(EXIT_FAILURE);
}
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(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;
file_data_t *file_data = malloc(sizeof *file_data);
if (file_data == NULL) {
fprintf(stderr, "Could not allocate file data\n");
exit(EXIT_FAILURE);
}
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) {
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;
char *chair = strtok_r(token, delim_line, &saveptr);
char *chair_value = strchr(chair, delim_colon);
chair_value += 2;
if (strcmp(chair_value, dont_keep) != 0) {
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);
}
char *number = strtok_r(NULL, delim_line, &saveptr);
char *number_value = strchr(number, delim_colon);
number_value += 2;
long val = strtol(number_value, &endptr, BASE);
if (endptr == number_value || *endptr != '\0') {
fprintf(stderr, "Count not parse number\n");
exit(EXIT_FAILURE);
}
file_data->data[count].number = val;
char *name = strtok_r(NULL, delim_line, &saveptr);
char *name_value = strchr(name, delim_colon);
name_value += 2;
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);
}
count++;
}
}
file_data->n = count;
return file_data;
}
char *get_file_contents(const char *path) {
FILE *fp = fopen(path, "r");
if (fp == NULL) {
fprintf(stderr, "Failed to open %s\n", path);
exit(EXIT_FAILURE);
}
int end = fseek(fp, 0L, SEEK_END);
if (end != 0) {
fprintf(stderr, "Could not go to end of file\n");
exit(EXIT_FAILURE);
}
long buffsize = ftell(fp);
if (buffsize == -1) {
fprintf(stderr, "Count not get size of file\n");
exit(EXIT_FAILURE);
}
char *buffer = malloc(buffsize + 1);
if (buffer == NULL) {
fprintf(stderr, "Could not allocate %ld bytes for buffer\n", buffsize);
exit(EXIT_FAILURE);
}
int start = fseek(fp, 0L, SEEK_SET);
if (start != 0) {
fprintf(stderr, "Could not go to start of file\n");
exit(EXIT_FAILURE);
}
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);
buffer[newlen++] = '\0';
return buffer;
}
输出:
$ 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
注意:上述代码并不是完成此任务的最佳方式,可以进行改进。您可以将其用作基础,并进行改进。