信息学奥赛一本通 第五章 第五章 数 组 第三节C语言非C++

第五章 数 组

第三节 字符类型和字符数组

2046:【例5.15】替换字母

#include <stdio.h>
#include <string.h>

int main()
{
    char s[205], a, b;
    fgets(s, 205, stdin); // 读入带空格的字符串,最多可以读入204个字符
    scanf("%c %c", &a, &b); // 输入a和b
    int len = strlen(s);
    for(int i = 0; i < len; ++i)
    {
        if(s[i] == a)
            s[i] = b;
    }
    printf("%s", s); // 输出字符串
    return 0;
}



2047:【例5.16】过滤空格

#include <stdio.h>
#include <string.h>

int main()
{
    char s_in[205], s_out[205];
    fgets(s_in, 205, stdin); // 读入带空格的字符串,最多可以读入204个字符
    int len = strlen(s_in), bn = 0, si = 0; // len:输入字符串的长度,bn:空格数量计数,si:输出字符串的索引
    for(int i = 0; i <= len; ++i) // 遍历到字符串结束标志'\0'位置
    {
        if(s_in[i] == ' ')
        {
            bn++; // 空格数量计数加1
            if(bn == 1)
                s_out[si++] = s_in[i]; // 将第一个空格填充到输出字符串中
        }
        else
        {
            s_out[si++] = s_in[i]; // 将非空格字符填充到输出字符串中
            bn = 0; // 重置空格数量计数
        }
    }
    printf("%s", s_out); // 输出字符串
    return 0;
}

2048:【例5.18】串排序

#include <stdio.h>
#include <string.h>

void swap(char *a, char *b) {
    char temp[25];
    strcpy(temp, a);
    strcpy(a, b);
    strcpy(b, temp);
}

int main() {
    char s[25][25];
    int n;
    scanf("%d", &n); // 输入n
    for(int i = 0; i < n; ++i) {
        scanf("%s", s[i]); // 输入字符串
    }

    for(int i = 0; i < n - 1; ++i) { // 选择排序
        int m = i; // 找从i+1~n最小值下标
        for(int j = i + 1; j < n; ++j) {
            if(strcmp(s[j], s[m]) < 0) {
                m = j;
            }
        }
        swap(s[m], s[i]); // 交换最小值与当前值
    }

    for(int i = 0; i < n; ++i) {
        printf("%s\n", s[i]); // 输出排序后的字符串
    }
    return 0;
}

2049:【例5.19】字符串判等

#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <ctype.h>

int main() {
    char s1[105], s2[105];
    int i = 0, j = 0, l1, l2; // i:s1的下标 j:s2的下标 也可以管i,j叫做指针
    fgets(s1, 105, stdin); // 读入带空格的字符串
    fgets(s2, 105, stdin);
    l1 = strlen(s1) - 1; // -1是因为fgets会读入换行符
    l2 = strlen(s2) - 1;
    bool isSame = true;

    while(i < l1 || j < l2) { // 只要有一个数组没遍历完,就进行这一循环,直到都遍历完,或跳出。
        if(s1[i] == ' ') {
            i++;
        } else if(s2[j] == ' ') {
            j++;
        } else {
            if(tolower(s1[i]) == tolower(s2[j])) { // 如果两字母相同,或仅仅是大小写不同的相同字母
                i++;
                j++;
            } else {
                isSame = false;
                break;
            }
        }
    }

    if(isSame) {
        printf("YES");
    } else {
        printf("NO");
    }
    return 0;
}

2050:【例5.20】字串包含

#include <stdio.h>
#include <string.h>
#include <stdbool.h>

int main() {
    char s1[35], s2[35], t[35];
    scanf("%s %s", s1, s2);
    int l1, l2, tl;
    l1 = strlen(s1);
    l2 = strlen(s2);
    bool hasSubstr = false;
    if(l1 < l2) { // 让s1是较长的字符串,s2是较短的字符串
        strcpy(t, s1);
        strcpy(s1, s2);
        strcpy(s2, t);
        l1 = strlen(s1);
        l2 = strlen(s2);
    }
    // l1 >= l2的前提下,判断s2是不是s1的子串
    for(int i = 0; i < l1; ++i) { // 循环遍历字符数组
        bool isSubStr = true;
        for(int j = 0; j < l2; ++j) {
            if(s2[j] != s1[(i+j)%l1]) { // 判断s2[j]与s1[(i+j)%l1]是否相同
                isSubStr = false;
                break;
            }
        }
        if(isSubStr) {
            printf("true");
            return 0;
        }
    }
    printf("false");
    return 0;
}

1839:【05NOIP提高组】谁拿了最多奖学金

#include <stdio.h>
#include <string.h>

#define N 105

char name[N][50]; // name[i]: 第i人的姓名,假设姓名长度不超过50
int money[N]; // money[i]: 第i人获得的奖学金,初值为0

int main() {
    int n, gStudy, gClass, paperNum, sum = 0, mxi = 1; // gStudy: 学习成绩, gClass: 班级成绩, paperNum: 论文数量
    char isLeader, isWest; // isLeader: 是否是干部, isWest: 是否来自西部
    scanf("%d", &n);
    for (int i = 1; i <= n; ++i) {
        scanf("%s %d %d %c %c %d", name[i], &gStudy, &gClass, &isLeader, &isWest, &paperNum);
        if (gStudy > 80 && paperNum >= 1)
            money[i] += 8000;
        if (gStudy > 85 && gClass > 80)
            money[i] += 4000;
        if (gStudy > 90)
            money[i] += 2000;
        if (gStudy > 85 && isWest == 'Y')
            money[i] += 1000;
        if (gClass > 80 && isLeader == 'Y')
            money[i] += 850;
        if (money[i] > money[mxi]) // 求最大值下标 mxi:获得最多奖学金的人的编号。如有相同最大值,只会取先出现的最大值的下标
            mxi = i;
        sum += money[i]; // sum:所有人奖学金总和
    }
    printf("%s\n%d\n%d", name[mxi], money[mxi], sum);
    return 0;
}

1129:统计数字字符个数

#include <stdio.h>
#include <string.h>
#include <ctype.h>

int main()
{
    char s[260];
    fgets(s, sizeof(s), stdin); // 使用fgets函数读取输入字符串,可以读取空格和换行符
    int sum = 0, len = strlen(s);
    for(int i = 0; i < len; ++i)
    {
        if(isdigit(s[i])) // 使用isdigit函数判断字符是否为数字
            sum++;
    }
    printf("%d", sum);
    return 0;
}

1130:找第一个只出现一次的字符

#include <stdio.h>
#include <string.h>

int main()
{
    int a[128] = {}; // 数组a[字母]表示该字母出现的次数,初始化为0
    char s[100005];
    scanf("%s", s);
    int len = strlen(s);
    
    for(int i = 0; i < len; ++i)
        a[s[i]]++; // 统计每个字符出现的次数
    
    for(int i = 0; i < len; ++i) // 遍历字符串,找到第一个只出现一次的字符
    {
        if(a[s[i]] == 1)
        {
            printf("%c", s[i]);
            return 0;
        }
    }
    
    printf("no"); // 没找到
    return 0;
}

1131:基因相关性

#include <stdio.h>
#include <string.h>

int main()
{
    double y; // 阈值
    char s1[505], s2[505]; // 输入的两个字符串
    scanf("%lf%s%s", &y, s1, s2); // 读取阈值和两个字符串

    int len = strlen(s1); // 字符串长度
    int ct = 0; // 计数

    // 遍历字符串,比较每个位置上的字符是否相等
    for(int i = 0; i < len; ++i)
    {
        if(s1[i] == s2[i])
            ct++; // 相等则计数加1
    }

    // 计算相等字符的比例并与阈值比较
    if((double)ct / len >= y)
        printf("yes");
    else
        printf("no");

    return 0;
}


1132:石头剪子布

#include <stdio.h>
#include <string.h>

int main()
{
    char s1[10], s2[10];
    int n;
    scanf("%d", &n);

    for(int i = 0; i < n; ++i)
    {
        scanf("%s %s", s1, s2);

        if(strcmp(s1, s2) == 0)
            printf("Tie\n");
        else
        {
            if(strcmp(s1, "Rock") == 0)
            {
                if(strcmp(s2, "Scissors") == 0)
                    printf("Player1\n");
                else
                    printf("Player2\n");
            }
            if(strcmp(s1, "Scissors") == 0)
            {
                if(strcmp(s2, "Paper") == 0)
                    printf("Player1\n");
                else
                    printf("Player2\n");
            }
            if(strcmp(s1, "Paper") == 0)
            {
                if(strcmp(s2, "Rock") == 0)
                    printf("Player1\n");
                else
                    printf("Player2\n");
            }
        }
    }

    return 0;
}

1133:输出亲朋字符串

#include <stdio.h>
#include <string.h>

int main()
{
    char s1[105], s2[105];
    fgets(s1, 105, stdin); // 从标准输入读取一行字符串,存储在s1中
    int len = strlen(s1); // 计算字符串s1的长度

    for(int i = 0; i < len; ++i)
        s2[i] = s1[i] + s1[(i + 1) % len]; // 将s1中每个字符与下一个字符相加,存储在s2中

    s2[len] = '\0'; // 在s2的末尾添加\0,构成字符串
    printf("%s", s2); // 输出s2

    return 0;
}

1134:合法C标识符查

#include <stdio.h>
#include <string.h>

int main()
{
    char s[25];
    scanf("%s", s); // 从标准输入读取字符串,存储在s中
    
    if (s[0] >= '0' && s[0] <= '9') // 如果第一个字符是数字
    {
        printf("no");
        return 0;
    }
    
    int len = strlen(s); // 计算字符串s的长度
    
    for (int i = 0; i < len; ++i)
    {
        // 如果出现不满足要求的字符
        if (!(s[i] >= '0' && s[i] <= '9' || 
              s[i] >= 'a' && s[i] <= 'z' ||
              s[i] >= 'A' && s[i] <= 'Z' ||
              s[i] == '_'))
        {
            printf("no");
            return 0;   
        }
    }
    
    printf("yes");
    return 0;
}

1135:配对碱基链

#include <stdio.h>

int main()
{
    char c;
    
    // 逐个读取字符,直到遇到换行符
    while ((c = getchar()) != '\n')
    {
        // 根据字符的不同,输出对应的字符
        if (c == 'A')
            printf("T");
        else if (c == 'T')
            printf("A");
        else if (c == 'G')
            printf("C");
        else
            printf("G");
    }
    
    return 0;
}

1136:密码翻译

#include <stdio.h>
#include <string.h>

int main() {
    char s[85], r[85];
    fgets(s, sizeof(s), stdin);
    int len = strlen(s);
    for (int i = 0; i < len; ++i) {
        if ((s[i] >= 'a' && s[i] <= 'y') || (s[i] >= 'A' && s[i] <= 'Y'))
            r[i] = s[i] + 1;
        else if (s[i] == 'Z' || s[i] == 'z')
            r[i] = s[i] - 25;
        else
            r[i] = s[i];
    }
    r[len] = '\0';
    printf("%s\n", r);
    return 0;
}


1137:加密的病历单

#include <stdio.h>
#include <string.h>
#include <ctype.h>

void reverse(char s[])//倒序
{
    int len = strlen(s);
    for(int i = 0; i < len/2; ++i)
    {
        // 交换位置
        char temp = s[i];
        s[i] = s[len - 1 - i];
        s[len - 1 - i] = temp;
    }
}

void changeCase(char s[])//大小写转换
{
    int len = strlen(s);
    for(int i = 0; i < len; ++i)
    {
        if(isupper(s[i])) // 大写字母转小写字母
            s[i] = tolower(s[i]);
        else if(islower(s[i])) // 小写字母转大写字母
            s[i] = toupper(s[i]);
    }
}

void moveRight(char s[])//字母右移3位
{
    int len = strlen(s);
    for(int i = 0; i < len; ++i)
    {
        if(isupper(s[i])) // 大写字母右移
            s[i] = (s[i] - 'A' + 3) % 26 + 'A';
        else if(islower(s[i])) // 小写字母右移
            s[i] = (s[i] - 'a' + 3) % 26 + 'a';
    }
}

int main()
{
    char s[55];
    scanf("%s", s); // 获取输入的字符串
    moveRight(s); // 字母右移3位
    changeCase(s); // 大小写转换
    reverse(s); // 倒序
    printf("%s\n", s); // 输出处理后的字符串
    return 0;
}

1138:将字符串中的小写字母转换成大写字母

#include <stdio.h>
#include <string.h>
#include <ctype.h>

int main()
{
    char s[105];
    fgets(s, 105, stdin); // 获取输入的字符串,包括空格
    int len = strlen(s) - 1; // 减去换行符的长度
    for(int i = 0; i < len; ++i)
    {
        if(s[i] >= 'a' && s[i] <= 'z') // 判断字符是否是小写字母
            s[i] = s[i] + 'A' - 'a'; // 转换为大写字母
    }
    printf("%s", s); // 输出处理后的字符串
    return 0;
}

1139:整理药名

#include <stdio.h>
#include <ctype.h>
#include <string.h>

int main()
{
    int n, len;
    char s[25];
    scanf("%d", &n); // 输入整数n

    for (int i = 0; i < n; ++i)
    {
        scanf("%s", s); // 输入字符串s
        len = strlen(s); // 计算字符串s的长度

        s[0] = toupper(s[0]); // 将字符串s的首字母转换为大写
        for (int j = 1; j < len; ++j)
            s[j] = tolower(s[j]); // 将字符串s剩余的字母转换为小写

        printf("%s\n", s); // 输出转换后的字符串s
    }

    return 0;
}

1140:验证子串

#include <stdio.h>
#include <string.h>

#define N 205

// 判断s2是否为s1的子串
int isSubStr(char s1[], char s2[])
{
    int l1 = strlen(s1), l2 = strlen(s2);

    for (int i = 0; i <= l1 - l2; ++i)
    {
        // 判断s1从s1[i]到s1[i+l2-1]是否与s2相同
        int isSame = 1;
        for (int j = 0; j < l2; ++j)
        {
            if (s1[i + j] != s2[j])
            {
                isSame = 0;
                break;
            }
        }
        if (isSame)
            return 1;
    }
    return 0;
}

int main()
{
    char s1[N], s2[N], t[N];
    scanf("%s %s", s1, s2); // 输入字符串s1和s2
    int l1 = strlen(s1), l2 = strlen(s2);

    if (l1 < l2) // 保证s1更长
    {
        strcpy(t, s1);
        strcpy(s1, s2);
        strcpy(s2, t);
        int temp = l1;
        l1 = l2;
        l2 = temp;
    }

    if (isSubStr(s1, s2))
        printf("%s is substring of %s", s2, s1); // 输出s2是s1的子串
    else
        printf("No substring"); // 输出无子串关系

    return 0;
}

1141:删除单词后缀

#include <stdio.h>
#include <string.h>

int main()
{
    char s[50], c3, c2, c1; // c3~c1是倒数第3,2,1个字符 
    scanf("%s", s); // 输入字符串s
    int len = strlen(s); // 获取字符串s的长度

    c1 = s[len - 1]; // 获取倒数第一个字符
    c2 = s[len - 2]; // 获取倒数第二个字符
    c3 = s[len - 3]; // 获取倒数第三个字符

    if (c3 == 'i' && c2 == 'n' && c1 == 'g') // 如果倒数三个字符为"ing"
        s[len - 3] = '\0'; // 将字符串s的倒数三个字符置为字符串结束符'\0'
    else if ((c2 == 'e' && c1 == 'r') || (c2 == 'l' && c1 == 'y')) // 如果倒数两个字符为"er"或"ly"
        s[len - 2] = '\0'; // 将字符串s的倒数两个字符置为字符串结束符'\0'

    printf("%s", s); // 输出修改后的字符串s

    return 0;
}

1142:单词的长度

#include <stdio.h>
#include <string.h>

int main()
{
    char s[1005];
    int isFirst = 1; // 是否是第一个输出的数字,1表示是,0表示否

    while (scanf("%s", s) == 1) // 读取字符串,注意scanf返回的是成功读取的变量个数,当读取失败时返回0或EOF
    {
        if (isFirst)
            isFirst = 0; // 将isFirst置为0,表示后面不再是第一个输出的数字
        else
            printf(","); // 输出逗号

        printf("%lu", strlen(s)); // 输出字符串s的长度,使用%lu格式打印无符号长整型
    }

    return 0;
}

1143:最长最短单词

#include <stdio.h>
#include <string.h>

int main()
{
    char s[205][105]; // 保存分割后的多个单词,s[i]是第i个单词字符串
    char c; // 当前读取的字符
    int w = 0, j = 0; // w: s的第一下标,表示单词编号。 j: s的第二下标,表示某单词的第几字符

    // 不断读取字符,直到遇到换行符
    while ((c = getchar()) != '\n')
    {
        if (c != ' ' && c != ',') // 如果不是分隔符,向单词s[w]添加一个字符
            s[w][j++] = c;
        else if (j != 0) // 如果是分隔符,且排除连续空格或逗号的情况
        {
            s[w][j] = '\0'; // 为单词s[w]添加字符串末尾
            w++; // 开始填充下一个单词
            j = 0;
        }
    }
    
    s[w][j] = '\0'; // 为最后一个单词添加末尾
    w++;
    int wordNum = w; // 单词总数量
    int maxlen = 0, minlen = 200; // maxlen: 最长单词长度, minlen: 最短单词长度
    int max_i, min_i; // max_i: 最长单词编号, min_i: 最短单词编号

    // 遍历所有单词,寻找其中最长和最短单词
    for (int i = 0; i < wordNum; ++i)
    {
        if (strlen(s[i]) > maxlen)
        {
            max_i = i;
            maxlen = strlen(s[i]);
        }
        if (strlen(s[i]) < minlen)
        {
            min_i = i;
            minlen = strlen(s[i]);
        }
    }

    puts(s[max_i]); // puts输出一个字符串后自动输出换行符
    puts(s[min_i]);

    return 0;
}

1144:单词翻转

#include <stdio.h>
#include <string.h>

void rev(char s[]) // 将字符串s前后颠倒
{
    int len = strlen(s);
    for (int i = 0; i < len / 2; ++i)
    {
        char temp = s[i];
        s[i] = s[len - 1 - i];
        s[len - 1 - i] = temp;
    }
}

int main()
{
    char s[505], w[500][505]; // s: 输入的字符串 w: 存储分解出的单词的数组
    fgets(s, sizeof(s), stdin);
    s[strlen(s) - 1] = '\0'; // 去除末尾的换行符

    int len = strlen(s), wi = 0, wj = 0; // len: 字符串s的长度 wi: 单词的索引 wj: 单词中字符的索引

    for (int i = 0; i <= len; ++i)
    {
        if (s[i] == ' ' || s[i] == '\0') // 如果遇到空格或字符串结束符
        {
            w[wi++][wj] = '\0'; // 当前单词结束,添加字符串结束符
            wj = 0; // 重置单词中字符的索引
        }
        else
            w[wi][wj++] = s[i]; // 将当前字符添加到当前单词中
    }

    for (int i = 0; i < wi; ++i)
    {
        rev(w[i]); // 将每个单词进行前后颠倒
        printf("%s ", w[i]); // 输出颠倒后的单词
    }

    return 0;
}

1145:字符串p型编码

#include <stdio.h>
#include <string.h>

int main()
{
    char s[1005], curNum; // s: 输入的字符串 curNum: 当前数字
    int ct = 0, len; // ct: 当前数字的计数器 len: 字符串s的长度
    scanf("%s", s);
    len = strlen(s);

    curNum = s[0]; // 初始化当前数字为字符串的第一个字符

    for (int i = 0; i <= len; ++i) // 遍历字符串s,包括字符串结束符'\0'
    {
        if (s[i] == curNum) // 如果当前字符与当前数字相同
        {
            ct++; // 计数器加1
        }
        else // 如果当前字符与当前数字不同
        {
            printf("%d%c", ct, curNum); // 输出当前数字的计数和当前数字本身
            curNum = s[i]; // 更新当前数字为当前字符
            ct = 1; // 重置计数器为1
        }
    }

    return 0;
}

1146:判断字符串是否为回文

#include <stdio.h>
#include <string.h>

int main()
{
    char s[105]; // s: 输入的字符串
    scanf("%s", s); // 读取字符串
    int len = strlen(s); // 获取字符串的长度

    for (int i = 0; i < len / 2; ++i) // 遍历字符串的前一半字符
    {
        if (s[i] != s[len - i - 1]) // 如果对应的两个字符不相等
        {
            printf("no"); // 输出"no"
            return 0;
        }
    }
    printf("yes"); // 如果所有对应的字符都相等,输出"yes"

    return 0;
}

1147:最高分数的学生姓名

#include <stdio.h>
#include <string.h>

typedef struct Student // 定义学生结构体
{
    int score;
    char name[21];
} Student;

int main()
{
    int n, mx_i = 0; // n: 学生数量 mx_i: 分数最高的学生的下标
    scanf("%d", &n); // 输入学生数量
    Student stu[105]; // 学生结构体数组

    for (int i = 0; i < n; ++i) // 遍历学生数组
    {
        scanf("%d %s", &stu[i].score, stu[i].name); // 输入学生成绩和姓名

        if (stu[i].score > stu[mx_i].score) // 如果当前学生的分数高于分数最高的学生
            mx_i = i; // 更新分数最高的学生下标
    }

    printf("%s", stu[mx_i].name); // 输出分数最高的学生的姓名

    return 0;
}

1148:连续出现的字符

#include <stdio.h>
#include <string.h>

int main()
{
    int k, cn = 1, len; // k: 连续出现的次数 cn: 字符连续出现的次数 len: 字符串长度
    scanf("%d", &k); // 输入连续出现的次数
    char s[2505]; // 字符串数组
    scanf("%s", s); // 输入字符串

    if (k == 1) // 如果k为1,为特例
    {
        printf("%c", s[0]); // 直接输出第0个字符,即为连续出现1次的字符
        return 0; // 结束程序
    }

    len = strlen(s); // 获取字符串长度

    for (int i = 1; i < len; ++i) // 遍历字符串
    {
        if (s[i] == s[i - 1]) // 如果现在看的字符和前一个字符相同
        {
            cn++; // 字符连续出现,连续出现的次数加1
            if (cn >= k) // 如果已经连续出现k次
            {
                printf("%c", s[i]); // 输出这个字符
                return 0; // 结束程序
            }
        }
        else // 如果当前字符与前一个字符不同
        {
            cn = 1; // 重新开始计数,当前字符连续出现1次
        }
    }

    printf("No"); // 如果没有能达到连续出现k次的情况,输出No

    return 0;
}

1149:最长单词2

#include <stdio.h>
#include <string.h>

int main()
{
    char s[505], word[505], mxWord[505]; // s: 完整字符串 word: 当前查看的单词 mxWord: 最长单词
    fgets(s, 505, stdin); // 输入字符串,使用fgets函数读取一行字符串

    int ct = 0, ctMax = 0, wi = 0, len; // ct: 单词中字母计数 ctMax: 最大单词长度 wi: 当前单词字符数组的下标 len: 字符串长度
    len = strlen(s); // 获取字符串长度

    for (int i = 0; i < len; ++i) // 遍历字符串
    {
        if (s[i] == ' ' || s[i] == '.') // 如果当前字符是空格或句点
        {
            word[wi] = '\0'; // 单词末尾加'\0',构成字符串
            wi = 0; // wi还原,等待下次向word字符数组赋值

            if (ct > ctMax) // 如果该单词长度比已知最长的单词长度更长
            {
                ctMax = ct; // ctMax记录最长单词长度
                strcpy(mxWord, word); // mxWord保存最长的单词
            }

            ct = 0; // 重置单词长度计数
        }
        else
        {
            ct++; // 单词长度计数
            word[wi++] = s[i]; // 将当前查看的字符s[i]填入word字符串中
        }
    }

    printf("%s", mxWord); // 输出最长单词

    return 0;
}

  • 7
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值