C语言实现修改文本文件中的特定行

本文详细描述了如何使用C语言实现类似Shell sed命令的功能,包括文本读取、匹配和修改特定行内容的过程。

     最近由于项目需要实现修改文件的功能,所以,博主认真查阅了一些资料,但是,很遗憾,并没有太多的收获。

好的,首先我先叙述下功能要求:

其实很简单,就是Shell中sed命令的C语言实现,实现定位到所需要的字段的那一行,之后修改成需要的内容。但是由于C语言是面向过程的语言,需要顺序执行的特点,所以,实现中遇到了很多麻烦,在这里博主将实现的过程描述如下,以便大家参考。

问题描述:

文本内容:

wireless.1.authmode=1
wireless.1.compression=0
wireless.1.current_ap=ssid12
wireless.1.current_state=1
wireless.1.devname=ath0
wireless.1.enable_slave1_status=disabled
wireless.1.enable_slave2_status=disabled
wireless.1.enable_slave3_status=disabled
我需要做的就是修改第四行的内容,使之变为:

wireless.1.current_state=0

问题看似简单,实现过程颇费周折。。。


这里我给出实现的代码,注释已经加在代码中:

/*
 * Author:DLUTBruceZhang
 * Date: 2013.06.24
 */
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
int main()
{
	/*
	 *linebuffer:读取文件中的一行存入的缓冲
	 *buffer1:一行中第一个字段的存入缓冲
	 *buffer2:一行中第二个字段的存入缓冲
	 */
	char linebuffer[512] = {0};
	char buffer1[512] = {0};
	char buffer2[512] = {0};
	
	int line_len = 0;
	int len = 0;
	int res;
	
	/*
	 * cc.cfg是文件名,r+代表可以读写文件
	 */
	FILE *fp = fopen("cc.cfg", "r+");
	if(fp == NULL)
	{
		printf("open error");
		return -1;
	}
	while(fgets(linebuffer, 512, fp))
	{
		line_len = strlen(linebuffer);
		len += line_len;
		/*
		 * buffer1=wireless.1.current_state
		 * buffer2=1
		 */
		sscanf(linebuffer, "%[^=]=%[^=]", buffer1,buffer2);
		if(!strcmp("wireless.1.current_state", buffer1))
		{
			/*
			 * 由于已经找到所需要写的位置,所以需要写位置的“头”
			 */
			len -= strlen(linebuffer);
			/*
			 * 实现文件位置的偏移,为写文件做准备
			 */
			res = fseek(fp, len, SEEK_SET);
			if(res < 0)
			{
				perror("fseek");
				return -1;
			}
			strcpy(buffer2, "=0");
			/*strcat(buffer1, "=");*/
			strcat(buffer1, buffer2);
			printf("%d",strlen(buffer1));
			/*
			 * 写文件,存入所需的内容
		     */
			fprintf(fp, "%s", buffer1);
			fclose(fp);
			return;
		}
	}
return 0;
}

保存文件名为:my_sed.c

运行效果如下:



我们再来看文件中的内容已经变为:

wireless.1.authmode=1
wireless.1.compression=0
wireless.1.current_ap=ssid12
wireless.1.current_state=0
wireless.1.enable_slave1_status=disabled
wireless.1.enable_slave2_status=disabled
wireless.1.enable_slave3_status=disabled

实现原理:

这里实现的效率比较高,因为不是把整个文件的内容装入缓冲区中,而是一行一行的读取,知道匹配为止,之后利用写文件的特性,直接覆盖所写内容即可,由此完成所需功能

### 修改文本文件特定实现原理 在 C 语言中,由于文件操作是顺序进的,不能直接定位到某一行修改。因此,若要修改文本文件中的一行内容,通常需要将整个文件读取到内存中,对相应修改后,再将全部内容重新写回原文件或临时文件中[^3]。 #### 文件读取与内容加载 首先,使用 `fopen` 函数以只读模式打开源文件,并逐读取内容,同时记录每一行的字符数,以便确定每在内存中的起始位置。可以采用动态分配数组的方式存储所有的内容,确保程序能够灵活处理不同长度的文本文件[^1]。 ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX_LINE_LENGTH 1024 int main(int argc, char *argv[]) { if (argc != 4) { printf("Usage: %s <filename> <line_number> <new_content>\n"); return -1; } const char *filename = argv[1]; int target_line = atoi(argv[2]); const char *new_content = argv[3]; FILE *fp = fopen(filename, "r"); if (!fp) { printf("无法打开文件 %s\n", filename); return -1; } char **lines = NULL; size_t line_count = 0; size_t capacity = 0; char line[MAX_LINE_LENGTH]; while (fgets(line, sizeof(line), fp)) { if (line_count >= capacity) { capacity += 10; lines = realloc(lines, capacity * sizeof(char *)); } lines[line_count++] = strdup(line); } fclose(fp); ``` #### 替换目标内容并更新文件 完成原始文件内容的读取后,检查目标号是否合法,即是否在有效范围内。如果合法,则释放该原有字符串的内存,并分配新的内容;否则输出错误信息。随后,重新打开文件,但这次使用 `"w"` 模式以清空原有内容,并依次将修改后的各写入文件中[^2]。 ```c if (target_line <= 0 || target_line > line_count) { printf("无效的目标号: %d\n", target_line); for (size_t i = 0; i < line_count; ++i) free(lines[i]); free(lines); return -1; } free(lines[target_line - 1]); lines[target_line - 1] = strdup(new_content); fp = fopen(filename, "w"); if (!fp) { printf("无法写入文件 %s\n", filename); for (size_t i = 0; i < line_count; ++i) free(lines[i]); free(lines); return -1; } for (size_t i = 0; i < line_count; ++i) { fputs(lines[i], fp); free(lines[i]); } free(lines); fclose(fp); printf("第 %d 已成功更新为: %s\n", target_line, new_content); return 0; } ``` 上述代码实现了从命令接收文件名、目标号和新内容三个参数,并完成指定替换操作。通过这种方式,可以在不依赖外部工具的情况下,利用 C 语言自身功能实现类似 Shell 中 `sed` 命令的效果。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值