【C语言】读取指定字符串在文本中出现的位置(只适合小文本文件)
一、前言
博主在实现的自己的需求时,奈何文本过大需求无法实现,至此有了以下适合小文本的版本,真的是心力交瘁。
二、代码
/*c
程序功能:
1: 判断子字符串是否实现在原字符串中
2: 且返回出现在原字符串所在的位置
3:记录一共?行存在待查词,一共?个待查词
4:后台反馈出包含待查词所在行的内容
5:保存出现待查词所在行到文本:wenben_searchword.txt中
*/
// #include "hanshu3.c"
#include <math.h>
#include <stdio.h>
#include <stdlib.h> // free()函数
#include <string.h>
int is_in(char *s, char *c, int location[]);
int feilin(int s[], int N); // 非零判断
int main(int argc, char *argv[])
{
FILE *fp, *fpIn, *fpOut; // 文件指针
char *pFile, *pFile2, *pFile3;
char line[3000];
int i;
int ii = 0; // 记录每行出现的位置次数
int n_lines = 0; // 标识行
int n_lines2 = 0; // 统计行
int sum_line = 0; // 记录一共出现待查词的行数
int sum_number = 0; // 统计一共出现待查词的个数
// int loc[2300] = {0}; // 每行存储出现待查词位置
// int *location = loc;
int **lovs = NULL; // 创建一个二维数组
int nn; // 获取location 长度(开头给了具体的分配内存)
int changdu = 0; // 行长度
char *filename = argv[1]; // 后台第二个参数:一个待读取的文本文档
// char *search_word = argv[2]; // 后台第三个参数:待查词
char *filename4 = argv[3]; // 后台第四个参数:存储文件
if (argc == 1 || argc == 2 || argc == 3)
{
printf("标准输出格式之打印到控制台:程序文件 原文本文件 异常词 -out\n");
printf("标准输出格式之指定文件:程序文件 原文本文件 待查词 存储文件\n");
return 0;
}
if (argc == 4)
{
pFile2 = strrchr(argv[1], '.'); // 判断输入的文件名最后输出.的位置
if (pFile2 != NULL)
{
if (strcmpi(pFile2, ".txt") == 0) // 等于文本文件
{
pFile3 = strrchr(argv[3], '.'); // 判断输入的文件名最后输出.的位置
if (strcmpi(argv[3], "-out") == 0)
{
// printf("打印控制台\n");
// 只读文件
if ((fpIn = fopen(filename, "r")) == NULL) // 以更新模式打开文件(以读写文件打开)
{
printf("无法打开文件:%s,请检查文件是否存在\n", argv[1]);
exit(EXIT_FAILURE); //表示没有成功地执行一个程序--退出
}
// 获取总的行数
while (fgets(line, sizeof(line), fpIn))
{
n_lines++;
}
// fclose(fpIn); // 关闭文件指针
// printf("\n一共%d行\n", n_lines);
rewind(fpIn);
lovs = (int **)malloc(sizeof(int *) * n_lines); // 为二维数组分配行
while (fgets(line, sizeof(line), fpIn)) // sizeof(line):每行最大数量 --行循环
{
int ii = 0; // 记录每行出现的位置次数
n_lines2++;
changdu = strlen(line); // 获取当前行的长度
lovs[n_lines2] = (int *)malloc(sizeof(int) * changdu); // 给当前行分配列
for (i = 0; i < changdu; i++) // 遍历当前行的长度
{
lovs[n_lines2][i] = 0; // 重置当前行的列为0
}
if (is_in(line, argv[2], lovs[n_lines2]) == 1)
{
sum_line++; // 存在待查词行数
nn = feilin(lovs[n_lines2], changdu);
printf("\n%-4d %2s ", n_lines2, argv[2]);
for (int hangshu = 0; hangshu <= nn; hangshu++) // 遍历每行中的每列
{
if (lovs[n_lines2][hangshu] != 0)
{
ii++;
printf("%-2d ", lovs[n_lines2][hangshu] / 2);
}
}
sum_number += ii; // 统计出现待查词的个数
}
free(lovs[n_lines2]); // 每列释放内存 */
lovs[n_lines2] = NULL;
}
free(lovs); // 每行释放内存
lovs = NULL; // free释放堆空间后,必须把无效指针变为空。(分手要清空前任的一切)
printf("\n存在异常词的行数,异常词的个数分别是:%d %d\n", sum_line, sum_number);
fclose(fpIn);
exit(0);
}
else if (strcmpi(pFile3, ".txt") == 0)
{
// printf("存储到文本文件\n");
// char copy[1000000]; // 存储重复的一维数组
// copy[0] = '\0'; // 初始化
if ((fpIn = fopen(filename, "r")) == NULL) // 以更新模式打开文件(以读写文件打开)
{
printf("无法打开文件:%s,请检查文件是否存在\n", argv[1]);
exit(EXIT_FAILURE); //表示没有成功地执行一个程序--退出
}
if ((fp = fopen(argv[3], "w")) == NULL) // 以更新模式打开文件(以读写文件打开)---写死的文本
{
printf("无法打开文件:%s", argv[3]);
exit(EXIT_FAILURE); // 表示没有成功地执行一个程序--退出
}
// 获取总的行数
while (fgets(line, sizeof(line), fpIn))
{
n_lines++;
}
// printf("\n一共%d行\n", n_lines);
rewind(fpIn);
lovs = (int **)malloc(sizeof(int *) * n_lines); // 为二维数组分配行
while (fgets(line, sizeof(line), fpIn)) // sizeof(line):每行最大数量 --行循环
{
int ii = 0; // 记录每行出现的位置次数
n_lines2++;
changdu = strlen(line); // 获取当前行的长度
lovs[n_lines2] = (int *)malloc(sizeof(int) * changdu); // 给当前行分配列
for (i = 0; i < changdu; i++) // 遍历当前行的长度
{
lovs[n_lines2][i] = 0; // 重置当前行的列为0
}
if (is_in(line, argv[2], lovs[n_lines2]) == 1)
{
sum_line++; // 存在待查词行数
nn = feilin(lovs[n_lines2], changdu);
printf("\n%-4d %2s ", n_lines2, argv[2]);
for (int hangshu = 0; hangshu <= nn; hangshu++) // 遍历每行中的每列
{
if (lovs[n_lines2][hangshu] != 0)
{
ii++;
printf("%-2d ", lovs[n_lines2][hangshu] / 2);
}
}
sum_number += ii; // 统计出现待查词的个数
//strcat(copy, line); // line:被拷贝;copy:拷贝到此处。
fprintf(fp, "%s", line);
}
free(lovs[n_lines2]); // 每列释放内存 */
lovs[n_lines2] = NULL;
}
fclose(fpIn);
fclose(fp);
free(lovs); // 每行释放内存
lovs = NULL; // free释放堆空间后,必须把无效指针变为空。(分手要清空前任的一切)
printf("\n存在异常词的行数,异常词的个数分别是:%d %d\n", sum_line, sum_number);
exit(0);
}
else
{
printf("您输入的:%s非指定参数\n", argv[3]);
exit(1);
}
}
else
{
printf("您输入的:%s非文本文件\n", argv[1]);
exit(1);
}
}
}
else
{
printf("输入参数不符合规范\n");
exit(1);
}
return 0;
}
int is_in(char *s, char *c, int location[])
{
int i = 0, j = 0, flag = -1, cishu = 0;
int num = 0;
int firstW = 0;
int flag2 = -1;
while (i < strlen(s) && j < strlen(c)) // s:原字符串,c: 比较字符串
{
if (s[i] == c[j]) // 指针所指位置的字符
{ //如果字符相同则两个字符都增加
i++;
j++;
}
else
{
i = i - j + 1; //主串字符回到比较 最开始比较的 后一个字符
j = 0; //字串字符重新开始
}
if (j == strlen(c)) //如果匹配成功
{
flag = 1; //字串出现
cishu++;
location[num] = i - strlen(c) + 2; // 存储每行出现待查词的位置
num++;
j = 0;
continue;
// break; // 第一次出现了不能结束
}
}
// printf("flag = %d",flag);
return flag;
}
// 非零判断
int feilin(int s[], int N)
{
int i;
int m = 0;
for (i = 0; i < N; i++)
{
if (s[i] != 0) // 不等于0
{
m++; // 统计个数
}
}
return m; // 返回非零个数
}
三、结果
四、说明
此代码只适合小文本至于多小博主也没测试也不会测试,基于以上版本问了许多大哥大姐们然而还是未能解决,get到基于文本的大小设计程序,此种方法博主还没get到,推测:get到此方法,或许博主的需求才能解决。