【C语言】读取指定字符串在文本中出现的位置(只适合小文本文件)

版权声明:可以转载奥 https://blog.csdn.net/Jiajikang_jjk/article/details/87381867

【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到此方法,或许博主的需求才能解决。

猜你喜欢

转载自blog.csdn.net/Jiajikang_jjk/article/details/87381867