C语言|文件处理|字符串处理|统计一个英文文本文件中26个英文字母出现次数并按英文字母序输出统计结果,查找并替换此英文文本文件中某字符串。

本文描述了一个C语言程序,实现了从一个文本文件中读取内容,统计大写和小写字母出现次数,然后根据用户输入的目标字符串和替换字符串,查找并替换文件中的特定内容。
摘要由CSDN通过智能技术生成
#include <stdio.h>
#include <string.h>
void count(FILE *fp_1);//实现记录每一个大写/小写字母;并输出到终端中
void replace(FILE *fp_1, FILE *fp_2);//实现更换
int search(char *loadZone, char *objectString, int loadZoneIndex, int objectStringIndex);//实现找到每一行中第一个目标字符串出现的位置并返回该位置的下标
void write(FILE *fp_2, char *loadZone, char *objectString, char *replaceString, int loadZoneIndex, int objectStringIndex, int replaceStringIndex);//实现对缓冲行的循环判断和写入
int main()
{
    FILE *fp_1 = fopen("C:\\VS Code\\C Programs\\CFilesLearning\\files\\FilesDemo2_2_1.txt", "r");
    if (fp_1 == NULL)
    {
        perror("File open failed:");
        exit(0);
    }
    FILE *fp_2 = fopen("C:\\VS Code\\C Programs\\CFilesLearning\\files\\FilesDemo2_2_2.txt", "w");
    if (fp_2 == NULL)
    {
        perror("File open failed:");
        exit(0);
    }
    count(fp_1);
    fseek(fp_1, 0, 0);//注意count函数使用fp_1文件指针对文件1进行遍历,遍历结束指针会移到文件尾,下一步replace函数再次遍历文件1,则需要用fseek函数把指针移到文件1开头
    replace(fp_1, fp_2);
    fclose(fp_1);
    fclose(fp_2);
    return 0;
}
void count(FILE *fp_1)
{
    char load = '\0';
    int characterTable[26] = {0};//使用一个int类型数组记录每一个字母出现的次数
    while (fscanf(fp_1, "%c", &load) != EOF)
    {
        if (load >= 'a' && load <= 'z')
        {
            characterTable[load - 'a']++;
        }
        else if (load >= 'A' && load <= 'Z')
        {
            characterTable[load - 'A']++;
        }
    }
    for (int i = 0; i < 26; i++)//遍历输出此数组
    {
        printf("%c/%c:%d\n", i + 'A', i + 'a', characterTable[i]);
    }
}
void replace(FILE *fp_1, FILE *fp_2)
{
    printf("Please enter the object string:\n");
    char objectString[1000] = {'\0'};
    char load = '\0';
    int objectStringIndex = 0;
    while (1)//读取目标字符串
    {
        load = getchar();
        if (load == '\n')
        {
            break;
        }
        else
        {
            objectString[objectStringIndex++] = load;
        }
    }
    printf("Your object string is:\n");
    for (int i = 0; i < objectStringIndex; i++)
    {
        printf("%c", objectString[i]);
    }

    printf("\n");
    printf("Please enter the replace string:\n");
    char replaceString[1000] = {'\0'};
    int replaceStringIndex = 0;
    while (1)//读取要替换成的字符串
    {
        load = getchar();
        if (load == '\n')
        {
            break;
        }
        else
        {
            replaceString[replaceStringIndex++] = load;
        }
    }

    printf("Your replace string is:\n");
    for (int i = 0; i < replaceStringIndex; i++)
    {
        printf("%c", replaceString[i]);
    }

    char loadZone[1000] = {'\0'};
    int loadZoneIndex = 0;

    while (1) // 把整个文本文件按行拆分成一个个字符串
    {
        if (fscanf(fp_1, "%c", &load) == EOF)//如果scanf返回终止符EOF,则对最后一行进行如下操作
        {
            // 这里对最后一行判断并写完再退出,同理,见下面非最后一行的操作
            if (strstr(loadZone, objectString) != NULL)
            {
                write(fp_2, loadZone, objectString, replaceString, loadZoneIndex, objectStringIndex, replaceStringIndex);
            }
            else
            {
                for (int i = 0; i < loadZoneIndex; i++)
                {
                    fprintf(fp_2, "%c", loadZone[i]);
                }
                fprintf(fp_2, "%c", '\n');
            }
            for (int i = 0; i < loadZoneIndex; i++)
            {
                loadZone[i] = '\0';
            }

            loadZoneIndex = 0;
            break;
        }
        //如果未读到最后一行,则以'\n'为标志,将每一行存入缓冲区(缓冲字符串loadZone中)
        if (load != '\n')
        {
            loadZone[loadZoneIndex++] = load;
        }
        else if (load == '\n')//读到'\n',判断一行读完,开始进行判断和写入操作
        {
            if (strstr(loadZone, objectString) != NULL)//调用函数strstr,判断缓冲区是否有目标字符串
            {
                //若有,则调用write函数
                write(fp_2, loadZone, objectString, replaceString, loadZoneIndex, objectStringIndex, replaceStringIndex);
            }
            else//若没有,则把缓冲区的字符全部写入
            {
                for (int i = 0; i < loadZoneIndex; i++)
                {
                    fprintf(fp_2, "%c", loadZone[i]);
                }
                fprintf(fp_2, "%c", '\n');//一行输出完毕,加上换行符
            }
            for (int i = 0; i < loadZoneIndex; i++)//清空缓存区,准备存入下一行
            {
                loadZone[i] = '\0';
            }
            loadZoneIndex = 0;
        }
    }
}
int search(char *loadZone, char *objectString, int loadZoneIndex, int objectStringIndex)
{
    //实现返回缓冲区中第一次出现目标字符串的第一个字符的下标
    int objectStringPosition = 0;
    int flag = 0;
    int k = 1;
    for (int i = 0; i < loadZoneIndex; i++)
    {
        if (loadZone[i] == objectString[0] && flag != 1)
        {
            objectStringPosition = i;
            flag = 1;
            continue;
        }
        if (flag == 1)
        {
            if (loadZone[i] == objectString[k++])
            {
                if (k == objectStringIndex)
                {
                    break;
                }
                else
                {
                    continue;
                }
            }
            else
            {
                flag = 0;
                k = 1;
            }
        }
    }
    return objectStringPosition;
}
void write(FILE *fp_2, char *loadZone, char *objectString, char *replaceString, int loadZoneIndex, int objectStringIndex, int replaceStringIndex)
{
    int objectStringPosition = 0;//目标字符串的第一个字符在缓冲区中第一次出现的下标
    int currentNeedle = 0;//记录当前在缓冲区中的下标
    objectStringPosition = search(loadZone, objectString, loadZoneIndex, objectStringIndex);
    while (1)//循环判断,可能一行出现多个目标字符串
    {
        for (int i = currentNeedle; i < objectStringPosition; i++)//在目标串前的缓冲区字符写入文件2
        {
            fprintf(fp_2, "%c", loadZone[i]);
        }
        for (int i = 0; i < replaceStringIndex; i++)//当前下标读到目标字符串第一个字符出现的位置,开始写入要替换的字符串
        {
            fprintf(fp_2, "%c", replaceString[i]);
        }
        currentNeedle = objectStringPosition + objectStringIndex;//更新当前下标,跳到第一个目标字符串最后一个字符的后一位
        //遍历,用缓冲区后面字符串把第一个目标字符串及其前面的字符全部覆盖,这样后面若还有目标字符串,则因为第一个被覆盖,其又变成第一个
        for (int i = 0; i < loadZoneIndex - currentNeedle; i++)
        {
            loadZone[i] = loadZone[i + currentNeedle];
        }
        for (int i = loadZoneIndex - currentNeedle; i < loadZoneIndex; i++)//多余的字符消掉
        {
            loadZone[i] = '\0';
        }

        loadZoneIndex -= currentNeedle;//缓冲区数组长度更新
        currentNeedle = 0;

        if (strstr(loadZone, objectString) == NULL)//继续寻找,若没有目标字符串了,则输出剩下的
        {
            // 输出剩下的
            for (int i = currentNeedle; i < loadZoneIndex; i++)
            {
                fprintf(fp_2, "%c", loadZone[i]);
            }
            fprintf(fp_2, "%c", '\n');
            break;
        }
        else // 若还有目标字符串,则更新位置,重复上述过程
        {
            objectStringPosition = search(loadZone, objectString, loadZoneIndex, objectStringIndex);
        }
    }
    //最终跳出循环,完成对文件中一行字符的处理
}

初学编程,逻辑和实现很是拙劣和冗杂,若有不当之处,敬请多多指出和交流。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值