服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C/C++ - 基于C语言编写简易的英文统计和加密系统

基于C语言编写简易的英文统计和加密系统

2023-05-06 15:17微凉秋意 C/C++

这篇文章主要介绍如何基于C语言编写一个简易的英文统计和加密系统,实际上就是对字符数组的基本操作的各种使用,感兴趣的可以了解一下

前言

耗时一天一夜写了一个简易的《英文统计和加密系统》,实际上就是对字符数组的基本操作的各种使用,其中也牵扯到简单的读写文件,把结构体存入文本文件等知识。总体来说,只要在编写前搭建好一个思维框架,逐个实现功能就轻松的多了。

部分功能、开发环境与项目结构

部分功能展示:

基于C语言编写简易的英文统计和加密系统

开发环境:

我使用的开发环境是 Visual Stduio 2022(2019版本应该更好)。

项目结构:

包含两个头文件和对应的源文件, main.c,以及三个文本文件:

基于C语言编写简易的英文统计和加密系统

主函数设计

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
// 英文统计和加密系统
// statistics 统计
// encryption 加密(结构体相关功能也在此处)
#include"statistics.h"
#include"encryption.h"
int main() {
    char buf[BUFSIZE];
    memset(buf, '0', sizeof(buf)); // 给字符数组初始化为 '0'
    showInfo(buf);
    printf("当前字母数:%d\n",countCharacter(buf));
    printf("当前单词数:%d\n",countWord(buf));
    printf("第12个字母为:");
    show_i(buf, 12);
    printf("与字母 'b'相比,小于,等于,大于的字母个数分别为:");
    classify_c(buf, 'b');
    int x = count_appear(buf, 'y');
    printf("字母y(不区分大小写)出现的次数为:%d\n", x);
    printf("所有y出现的下标为:");
    int* A = (int*)malloc(sizeof(int) * x +1);
    int *n = location_index(buf, A, 'y');
    for (int i = 0; i < x; i++) {
        printf("%3d", n[i]);
    }
    printf("\n");
    encryption(buf, 3);
    /*puts(buf);*/
    printf("将26个英文字母打包成一个结构体,附加对应次数\n");
    alphabet chars;
    Initialize(&chars);
    printf("计算字母出现次数并存入文本文件中:\n");
    count_letters(buf, &chars);
    encrypt en = maxTimes(chars);
    encrypt minEn = minTimes(chars);
    printf("出现最多的字母为:%c,对应次数为:%d\n", en.data, en.num);
    printf("出现最少的字母为:%c,对应次数为:%d\n", minEn.data, minEn.num);
    printf("字母平均出现次数:%.2f\n", averageNum(chars));
    int k = 8;
    char* list = list_k(chars,k);
    printf("前%d名字母序列为:", k);
    for (int i = 0; i < k; i++) {
        printf("%2c", list[i]);
    }
    select_sort(chars);
    //setText(&chars); // 需要更新结构体文本文件时使用
}

主函数完全可以使用 循环+switch-case来做一个菜单,重复使用功能。

实现效果已经在上文中展示,后序不再展示。

statistics 头文件以及源文件

statistics.h

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#pragma once // 避免重复包含头文件
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define BUFSIZE 512
// 获取原文长度
int get_length(char* buf);
// 获取文本的原文内容
void getText(char *buf);
// 得到原文内容
void showInfo(char *buf);
// 统计原文字母个数
int countCharacter(char* buf);
// 统计原文单词个数
int countWord(char* buf);
// 显示原文第i个单词
void show_i(char* buf,int i);
// 根据字符c的大小,分为三部分
void classify_c(char* buf, char c);
// 定位值为c的下标
int* location_index(char* buf, int* index,char c);
// 字符c的出现次数
int count_appear(char* buf, char c);

statistics.c

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
#include"statistics.h"
// 获取原文有效长度
int get_length(char* buf) {
    int len = 0;
    for (int i = 0; i < BUFSIZE && buf[i] != '0'; i++) {
        len++;
    }
    return len;
}
//用子函数实现从文本文件读取原文的操作
void getText(char *buf) {
    FILE* file;
    file = fopen("myfile.txt", "r");
    if (file == NULL) {
        printf("打开文件失败!");
        exit(-1);
    }
    char arr[BUFSIZE];
    memset(arr, '0', sizeof(arr));
    fgets(arr, sizeof(arr), file);
    fclose(file);
    strcpy(buf, arr);
}
//1.定义一字符数组word,用户输入原文或从一文本文件读入(调用子函数)原文(一段英文),
// 输出显示该原文,以及其总长度。
void showInfo(char* buf) {
    printf("1.输入原文:\n");
    printf("2.读取原文\n");
    int choice = 0;
    scanf("%d", &choice);
    rewind(stdin); // 清空缓冲区
    if (choice == 1) {
        char arr[BUFSIZE];
        memset(arr, '0', sizeof(arr));
        fgets(arr, sizeof(arr), stdin);
        strcpy(buf, arr);
    }
    else if (choice == 2) {
        getText(buf);
    }
    else {
        printf("请正确选择获取原文方式!"); exit(-1);
    }
    int sum = get_length(buf);
    if (choice==2) printf("总长度为:%d\n",  --sum); // 去掉自带的 .
    else printf("总长度为:%d\n",  sum-2); // fgets会多读一个字符
    printf("原文:%s\n", buf);
}
//3.用子函数实现统计原文中的字母个数。
int countCharacter(char* buf) {
    int i;
    int count = 0;
    for (i = 0; i < BUFSIZE&&buf[i]!= '0'; i++) {
        if (buf[i] >= 'a' && buf[i] <= 'z' || buf[i] >= 'A' && buf[i] <= 'Z') {
            count++;
        }
    }
    return count;
}
//4.用子函数实现统计原文中的单词个数。
int countWord(char* buf) {
    int i;
    int count = 0;
    for (i = 1; i < BUFSIZE&&buf[i]!='0'; i++) {
        if (buf[i] == ' ' &&(buf[i - 1] >= 'a' && buf[i - 1] <= 'z' || buf[i - 1] >= 'A' && buf[i - 1] <= 'Z'))
            count++;
    }
    if (buf[i - 1] >= 'a' && buf[i - 1] <= 'z' || buf[i - 1] >= 'A' && buf[i - 1] <= 'Z')
        count++;
    return count;
}
//5.定义一子函数,输入任一下标值i,检查i的输入合法性,
// 合法输出显示word的第i个字母,否则输出“输入i不合法”。
void show_i(char* buf,int i) {
    int len = countCharacter(buf);
    if (i<1 || i>len) {
        printf("输入i不合法\n");
        exit(-1);
    }
    int index = 0; // 记录当前字母位序
    for (int j = 0; j < BUFSIZE && buf[j] != '0'; j++) {
        if (buf[j] >= 'a' && buf[j] <= 'z' || buf[j] >= 'A' && buf[j] <= 'Z') {
            ++index;
            if (index == i) {
                printf("%c\n", buf[j]);
                return;
            }
        }
    }
}
//6.定义一子函数,输入一字母c, 分别输出word中大于字母c的个数和小于字母c的个数,
// 以及等于字母c的个数。
void classify_c(char* buf, char c) {
    char arr[BUFSIZE];
    memset(arr, '0', sizeof(arr));
    int index = 0; // 记录当前字母位序
    for (int j = 0; j < BUFSIZE && buf[j] != '0'; j++) {
        if (buf[j] >= 'a' && buf[j] <= 'z' || buf[j] >= 'A' && buf[j] <= 'Z') {
            arr[index++] = buf[j];
        }
    }
    // 冒泡排序(升序)
    for (int i = 0; i < index; i++) {
        char flag = 'f';// 标志位
        for (int j = index-1; j > i; j--) {
            if (arr[j] < arr[j - 1]) {
                flag = 't';
                char ch = arr[j];
                arr[j]=arr[j-1];
                arr[j - 1] = ch;
            }
        }
        if (flag == 'f') break;
    }
    int l, h, e,i;
    for (l = 0, h = 0, e = 0, i = 0; i < index; i++) {
        if (arr[i] < c) l++;
        else if (arr[i] == c) e++;
        else break;
    }
    h = index - l - e;
    printf("little:%d equal:%d high:%d\n", l, e, h);
}
//7.定义一子函数,实现字符查找功能:判定该字母是否存在,
// 是则返回每一个出现位置的下标(或者首次出现的下标位置),否则返回 - 1。
int* location_index(char* buf, int *index,char c) {
    int i;
    int in = 0;
    char flag = 'f';// 如果最终还是f,说明找不到该字母
    for (i = 0; i < BUFSIZE && buf[i] != '0'; i++) {
        if (buf[i] == c||c == buf[i]+32||c==buf[i]-32) index[in++] = i;
        flag = 't';
    }
    if (flag == 'f') return -1;
    return index;
}
//8.定义一子函数,实现输入一字母,统计原文中该字母的出现次数(字母不区分大小写, 实现合并计数)
// 并返回。函数中需要有对输入的字母是否输入异常判定和捕获操作,并在主程序中进行输入错误提示。
int count_appear(char* buf, char c) {
    if (!(c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z')) {
        printf("当前字符为%c,请输入正确字母\n", c);
        exit(-1);
    }
    int i;
    int count = 0;
    for (i = 0; i < BUFSIZE && buf[i] != '0'; i++) {
        if (c == buf[i] || c == buf[i] + 32 || c == buf - 32) count++;
    }
    return count;
 }

encryption 头文件以及源文件

encryption.h

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#pragma once
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
// 字母以及出现次数的结构体
typedef struct {
    char data; // 显示字母
    int num; // 出现次数
}encrypt;
typedef struct {
    encrypt letters[26];
}alphabet;
// 初始化字母表
void Initialize(alphabet *chars);
// 计算各个字母的出现次数
void count_letters(char* buf, alphabet* chars);
// 存入结构体文本文件
void setText(alphabet *chars);
// 返回出现次数最多的字母
encrypt maxTimes(alphabet chars);
// 返回出现次数最少的字母
encrypt minTimes(alphabet chars);
// 计算字母出现的平均次数
float averageNum(alphabet chars);
// 出现前k名的字母序列
char* list_k(alphabet chars, int k);
// 选择升序或者降序排序
void select_sort(alphabet chars);
// 加密算法,根据n的位置循环后移
void encryption(char* buf, int n);
// 存入加密的文本文件
void setEncryptText(char* buff);

encryption.c

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
#include"encryption.h"
#include"statistics.h"
//9.将26个英文字母和其对应的出现次数打包定义为一个结构体类型来存储。
// 初始化结构体数组
void Initialize(alphabet* chars) {
    int k = 0;
    char c = 'a';
    for (int i = 0; i < 26; i++) {
        chars->letters[i].num = k;
        chars->letters[i].data = c + i;
    }
}
//10.设计实现一新的子函数,针对读入的原文,统计出26个英文字母在单词中出现的次数,
//并统一存储到9定义的结构体数组中,然后完成11到16的操作。
void count_letters(char* buf, alphabet* chars) {
    printf("1.输入原文:\n");
    printf("2.读取原文\n");
    int choice = 0;
    int sum = 0;
    scanf("%d", &choice);
    rewind(stdin); // 清空缓冲区
    if (choice == 1) {
        char arr[BUFSIZE];
        memset(arr, '0', sizeof(arr));
        fgets(arr, sizeof(arr), stdin);
        strcpy(buf, arr);
    }
    else if (choice == 2) {
        getText(buf);
    }
    else {
        printf("请正确选择获取原文方式!"); exit(-1);
    }
    char arr[BUFSIZE]; // 最终转化为全部字母
    memset(arr, '0', sizeof(arr));
    int index = 0; // 记录当前字母位序
    for (int j = 0; j < BUFSIZE && buf[j] != '0'; j++) {
        if (buf[j] >= 'a' && buf[j] <= 'z' || buf[j] >= 'A' && buf[j] <= 'Z') {
            arr[index++] = buf[j];
        }
    }
    for (int i = 0; i < index; i++) {
        for (int j = 0; j < 26; j++) {
            if (arr[i] == chars->letters[j].data || arr[i] + 32 == chars->letters[j].data)
                chars->letters[j].num++;
        }
    }
}
//11.将结构体数组结果存储到一文本文件。
void setText(alphabet* chars) {
    FILE* fp;
    fopen_s(&fp, "struct.txt", "wt+");    //打开文件
    for (int i = 0; i < 26; i++)            //将N条信息存储进去
    {
        fprintf(fp, "%d %d\n", chars->letters[i].data, chars->letters[i].num);
    }
    fclose(fp);    //关闭文件
    //encrypt buff[26];
    //FILE* fpp;
    //fopen_s(&fpp, "struct.txt", "rb");
    //fread(buff, sizeof(encrypt), 26, fpp); // 将N条消息全部从文件中读取出来
    //fclose(fpp);
}
//12.设计一子函数:返回出现次数最多的字母和对应次数。
encrypt maxTimes(alphabet chars) {
    int max = chars.letters[0].num;
    int i, index;
    for (i = 1, index = 0; i < 26; i++) {
        if (max < chars.letters[i].num) {
            max = chars.letters[i].num;
            index = i;
        }
    }
    return chars.letters[index];
}
//13.设计一子函数:返回出现次数最少的字母和对应次数。
encrypt minTimes(alphabet chars) {
    int min = chars.letters[0].num;
    int i, index;
    for (i = 1, index = 0; i < 26; i++) {
        if (min > chars.letters[i].num) {
            min = chars.letters[i].num;
            index = i;
        }
    }
    return chars.letters[index];
}
//14.设计一子函数:返回26个字母的平均出现次数。
float averageNum(alphabet chars) {
    float avg = 0.0;
    for (int i = 0; i < 26; i++) {
        avg += chars.letters[i].num;
    }
    avg /= 26;
    return avg;
}
//15. 设计一子函数:输入数字k,返回出现次数前k名的字母序列
char* list_k(alphabet chars, int k) {
    if (k < 1 || k>26) exit(-1);
    char* list = (char*)malloc(sizeof(char) * k);
    // 冒泡排序
    for (int i = 0; i < 26; i++) {
        char flag = 'f';
        for (int j = 25; j > i; j--) {
            if (chars.letters[j].num > chars.letters[j - 1].num) {
                flag = 't';
                encrypt temp = chars.letters[j];
                chars.letters[j] = chars.letters[j - 1];
                chars.letters[j - 1] = temp;
            }
        }
        if (flag == 'f') break;
    }
    for (int i = 0; i < k; i++) {
        list[i] = chars.letters[i].data;
    }
    return list;
}
//16.定义一排序子函数,实现对结构体数组结果按照出现次数进行升序或降序排列
//(由用户在运行时选择排序方式), 输出排序结果以及对应的字母。
void select_sort(alphabet chars) {
    printf("\n1.升序排列\n2.降序排列\n");
    int choice = 0;
    scanf("%d", &choice);
    if (choice == 2) {
        for (int i = 0; i < 26; i++) {
            char flag = 'f';
            for (int j = 25; j > i; j--) {
                if (chars.letters[j].num > chars.letters[j - 1].num) {
                    flag = 't';
                    encrypt temp = chars.letters[j];
                    chars.letters[j] = chars.letters[j - 1];
                    chars.letters[j - 1] = temp;
                }
            }
            if (flag == 'f') break;
        }
    }
    else if (choice == 1)
    {
        for (int i = 0; i < 26; i++) {
            char flag = 'f';
            for (int j = 25; j > i; j--) {
                if (chars.letters[j].num < chars.letters[j - 1].num) {
                    flag = 't';
                    encrypt temp = chars.letters[j];
                    chars.letters[j] = chars.letters[j - 1];
                    chars.letters[j - 1] = temp;
                }
            }
            if (flag == 'f') break;
        }
    }
    else {
        printf("请正确选择排序规则!");
        exit(-1);
    }
    printf("排序结果为:");
    for (int i = 0; i < 26; i++) {
        printf("%2c", chars.letters[i].data);
    }
}
//17.用子函数实现将读取的原文按规则加密后存入另一字符数组中。
//电文加密 : 问题描述:为使电文保密,常按一定规律将其转换成密文后发送,
//收报人再按约定的规律将其译回原文。设定加密规则为:
//每个字母变成其后的第n(n由用户输入指定)个字母,如A变成其后第n个字母….。
//说明 : 只对原文中的英文字母加密, 其他非英文字母要原样保留。
void encryption(char* buf, int n) {
    n %= 26; // 确保英文字母加密后还是英文字母
    int i;
    int len = get_length(buf);
    char* arr = (char*)malloc(len * sizeof(char));
    memset(arr, '0', sizeof(arr));// 初始化
    for (i = 0; i < len; i++) {
        if (buf[i] >= 'a' && buf[i] <= 'z' || buf[i] >= 'A' && buf[i] <= 'Z') {
            if (buf[i] + n > 'z') {
                arr[i] = buf[i] + n - 26;
            }
            else if (buf[i] <= 'Z' && buf[i] + n > 'Z') {
                arr[i] = buf[i] + n - 'Z' + 'A'-1;
            }
            else {
                arr[i] = buf[i] + n;
            }
        }
        else {
            arr[i] = buf[i];
        }
    }
    printf("加密后:%s\n", arr);
    setEncryptText(arr);
}
//18.用子函数实现将密文存入密文文本文件中。
void setEncryptText(char* buff) {
    FILE* fp;
    fp = fopen("encryption.txt", "wt+");
    if (fp == NULL) {
        printf("打开文件失败!");
        exit(-1);
    }
    fputs(buff, fp);
    fclose(fp);
}

myfile.txt文件中可自行输入密文(26个英文字母大小写,各种符号,数字等等);

struct.txt文件有26行,对应着原文中26个英文字母出现的次数以及ASCII码值;

encryption.txt文件是myfile.txt文件中的字母通过循环后移 n 位得到,其中的难点在于大写字母后移超过Z时的处理方法,这点大家可以在encryption.c文件中的encryption函数中获得灵感。

到此这篇关于基于C语言编写简易的英文统计和加密系统的文章就介绍到这了,更多相关C语言英文统计和加密系统内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://blog.csdn.net/m0_58618795/article/details/130501616

延伸 · 阅读

精彩推荐
  • C/C++C/C++自主分配出现double free or corruption问题解决

    C/C++自主分配出现double free or corruption问题解决

    这篇文章主要为大家介绍了C/C++出现double free or corruption问题解决,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪...

    englyf ENG八戒5932023-04-04
  • C/C++OpenCV实现帧间差分法详解

    OpenCV实现帧间差分法详解

    这篇文章主要为大家详细介绍了OpenCV实现帧间差分法,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    特种军靴7682021-08-27
  • C/C++C语言边角料4:利用_Pragma来温柔的废弃API

    C语言边角料4:利用_Pragma来温柔的废弃API

    这篇小短文就来聊一聊利用_Pragma来温柔的废弃API,希望能够帮助到你! ...

    IOT物联网小镇4052021-03-27
  • C/C++老生常谈C/C++内存管理

    老生常谈C/C++内存管理

    下面小编就为大家带来一篇老生常谈C/C++内存管理。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧...

    jingxian11962021-05-13
  • C/C++C语言植物大战数据结构堆排序图文示例

    C语言植物大战数据结构堆排序图文示例

    这篇文章主要为大家介绍了C语言植物大战数据结构堆排序的图文示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职...

    _奇奇8722022-11-27
  • C/C++C语言main函数的三种形式实例详解

    C语言main函数的三种形式实例详解

    这篇文章主要介绍了 C语言main函数的三种形式实例详解的相关资料,需要的朋友可以参考下...

    ieearth7042021-05-16
  • C/C++Windows下CMake的下载与安装过程

    Windows下CMake的下载与安装过程

    CMake是一个跨平台的安装(编译)工具,可以用简单的语句来描述所有平台的安装(编译过程),这篇文章主要介绍了Windows下CMake的下载与安装,需要的朋友可以...

    wendy_ya10302022-09-29
  • C/C++C语言中关于sizeof 和 strlen的区别分析

    C语言中关于sizeof 和 strlen的区别分析

    本文通过示例简单分析了4种情况下C语言中sizeof 和 strlen的区别,算是个人经验的一个小小的总结,如有遗漏还请大家告知。...

    C语言教程网10642021-02-22