跳转至

Alpha 串、数组、广义表

统计字符串中数字和字母的个数

请根据注释完成函数 count,实现统计字符串中数字(0-9)和字母(A-Z,a-z)出现的个数的功能。

示例

Text Only
1
字符串:"abc11def001010DJK"

输出

Text Only
1
2
字母个数:9
数字个数:8

题目

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
#include <stdio.h>
#include <stdlib.h>

//统计输入字符串中出现的A-Z及a-z字符的个数
//统计输入字符串中出现的0-9个数。
//s:输入的字符串
//pzm:指向保存A-Z和a-z个数的整型变量的指针 
//psz:指向保存0-9个数的整型变量的指针

void count(char s[], int *pzm, int *psz)
{

}

int main()
{
    char s[] = "abc11def001010DJK";
    int zm = 0; //字符串中A-Z或a-z字符的个数
    int sz = 0; //字符串中0-9的个数
    count(s,&zm,&sz); 

    printf("字母个数:%d\n数字个数:%d",zm,sz);

    return 0;
}

答案

C
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
void count(char s[], int* pzm, int* psz) {
    // 初始化字母和数字的个数为 0
    *pzm = 0;
    *psz = 0;

    // 遍历字符串中的每个字符
    for (int i = 0; s[i] != '\0'; i++) {
        // 检查字符是否是字母
        if ((s[i] >= 'A' && s[i] <= 'Z') || (s[i] >= 'a' && s[i] <= 'z')) {
            (*pzm)++;
        }
        // 检查字符是否是数字
        if (s[i] >= '0' && s[i] <= '9') {
            (*psz)++;
        }
    }
}

标准答案

C
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
void count(char s[], int* pzm, int* psz)
{
    int i = 0;
    while (s[i] != '\0') {
        if (('0' <= s[i]) && (s[i] <= '9')) {
            (*psz)++;
        } // 数字
        else if (('a' <= s[i] && s[i] <= 'z') || ('A' <= s[i] && s[i] <= 'Z')) {
            (*pzm)++;
        } // 字母
        i++;
    }
}

字符串分割

请完成函数part,实现如下功能:给定字符串 s,按给定的长度 n 分割成两个字符串,字符串 s 的前 n 个字符存入 s1,其多余的字符存入 s2。

示例

Text Only
1
2
字符串 s:"abc123456789"
长度 n:5

输出

Text Only
1
2
abc12
3456789

题目

C
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
#include <stdio.h>
#include <stdlib.h>

void part(char *s, char *s1, char *s2, int n){
    //请在此处编写代码,实现题目要求


}

int main()
{
    char s[] = "abc123456789";
    char s1[10],s2[10];
    part(s,s1,s2,5); 
    printf("%s\n%s",s1,s2);
    return 0;
}

答案

第一种方法,直接用string.h,注意strncpystrcpy的区别。

区别如下:

  1. 功能不同:
  2. strncpy(destination, source, n):将源字符串 source 的前 n 个字符复制到目标字符串 destination 中。如果 source 的长度小于 n,则在复制完 source 的内容后,将剩余的字符用空字符 \0 填充。
  3. strcpy(destination, source):将源字符串 source 的所有字符复制到目标字符串 destination 中,直到遇到空字符 \0 为止。

  4. 长度控制不同:

  5. strncpy 允许指定要复制的字符个数 n,并且即使 source 的长度小于 n,也会在 destination 中填充空字符 \0,以保证 destination 的长度为 n
  6. strcpy 没有指定要复制的字符个数,它会一直复制直到遇到 source 的空字符 \0,因此 destination 的长度取决于 source 的长度。

  7. 安全性不同:

  8. strncpy 在复制 source 的前 n 个字符时,不会检查 source 的实际长度,因此可能出现未复制完整字符串或未填充足够的空字符的情况。这可能导致目标字符串 destination 不是一个有效的 C 字符串。
  9. strcpy 会复制源字符串 source 的所有字符,直到遇到空字符 \0。它会保证目标字符串 destination 是一个有效的 C 字符串,且以空字符结尾。

总的来说,strncpy 在需要控制复制字符个数的情况下比较有用,但需要小心处理字符串结束符的情况。而 strcpy 则是常用的字符串复制函数,适用于复制整个字符串的场景,并确保目标字符串是一个有效的 C 字符串。

C
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
#include <string.h> // 别忘了这个

void part(char* s, char* s1, char* s2, int n) {
    // 将 s 的前 n 个字符复制到 s1
    strncpy(s1, s, n);
    s1[n] = '\0'; // 设置 s1 的末尾为字符串结束符

    // 将 s 中剩余的字符复制到 s2
    strcpy(s2, s + n);
}

第二种方法,手动实现string.h功能。

C
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
void part(char* s, char* s1, char* s2, int n) {
    int i;

    // 复制 s 的前 n 个字符到 s1
    for (i = 0; i < n && s[i] != '\0'; i++) {
        s1[i] = s[i];
    }
    s1[i] = '\0'; // 设置 s1 的末尾为字符串结束符

    // 复制 s 中剩余的字符到 s2
    for (int j = 0; s[i] != '\0'; i++, j++) {
        s2[j] = s[i];
    }
    s2[i - n] = '\0'; // 设置 s2 的末尾为字符串结束符
    // 可有可无
}

标准答案(不太好)

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
void part(char* s, char* s1, char* s2, int n)
{
    char* p = s, * q = s1;
    int i = 0;
    if (*p == '\0') {//s为空 
        return;
    }

    //s1 
    while (*p != '\0' && i < n) {
        *q = *p;
        q++;
        p++;
        i++;
    }
    *q = '\0';
    if (*p == '\0') {
        return;
    }

    //s2    
    q = s2;
    while (*p != '\0') {
        *q = *p;
        q++;
        p++;
    }
    *q = '\0';
}

字符串的插入

请完成函数insert,实现如下功能:将字符串 t 插入到字符串 s 中,插入位置为 pos。

示例

Text Only
1
2
3
字符串s:"1234567890"
字符串t:"abcd"
插入位置pos:6

输出

Text Only
1
12345abcd67890

题目

C
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
#include <stdio.h>
#include <stdlib.h>

void  insert(char *s,char *t,int pos){
    //请在此处编写代码,完成题目要求


}

int main()
{
    char s[20] = "1234567890";
    char t[20] = "abcd";
    insert(s,t,6);
    printf("%s",s);
    return 0;
}

答案

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
void insert(char* s, char* t, int pos) {
    int len_s = 0;
    int len_t = 0;

    // 计算字符串 s 和 t 的长度
    while (s[len_s] != '\0') {
        len_s++;
    }
    while (t[len_t] != '\0') {
        len_t++;
    }

    // 因为首元素下标为‘1’
    pos--;

    // 这一段可有可无
    // 检查插入位置是否超出 s 的长度范围
    // 如果 pos 大于 len_s,则将 pos 设置为 len_s
    // 以确保插入位置不会超出字符串 s 的末尾。
    if (pos > len_s) {
        pos = len_s;
    }

    // 为 t 中的字符腾出空间,移动原来的字符向后
    for (int i = len_s; i >= pos; i--) {
        s[i + len_t] = s[i];
    }

    // 将 t 中的字符复制到插入位置开始的位置
    for (int i = 0; i < len_t; i++) {
        s[pos + i] = t[i];
    }

    // 在 s 的末尾添加字符串结束符
    s[len_s + len_t] = '\0';
}

标准答案(不太好)

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
void  insert(char* s, char* t, int pos)
{
    int i = 1, x = 0, j;
    char* p = s, * q = t;
    if (pos < 1) {
        return;
    }
    while (*p != '\0' && i < pos) {
        p++;
        i++;
    }
    if (*p == '\0') {
        return;
    }
    else
        while (*p != '\0') {
            p++;
            i++;
        }
    while (*q != '\0') {
        q++;
        x++;
    }
    for (j = i; j >= pos; j--) {
        *(p + x) = *p;
        p--;
    }
    q--;

    for (j = 1; j <= x; j++) {
        *(p + x) = *q;
        p--;
        q--;
    }
}

KMP模式匹配(待完成)

请编写模式匹配函数KMP,借助 KMP 算法来实现如下功能:如果匹配成功,则返回对应的位置;如果匹配不成功,则返回-1。

示例 1

调用函数

Text Only
1
KMP("aabaabbaaabab","aaab")

输出

Text Only
1
8

示例 2

调用函数

Text Only
1
KMP("aabaabbaaabab","aaabbb")

输出

Text Only
1
-1

题目

C
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
#include <stdio.h>
#include <string.h>

//匹配成功,则函数返回位置
int KMP(char * S,char * T){

}
int main() {
    int i=KMP("aabaabbaaabab","aaab");
    printf("%d",i);
    return 0;
}

答案

构建next数组的时候int next[len_t];,VS会报错,“E0028:表达式必须含有常量值”。解决方法嘛,要么动态分配内存,要么就直接填个next[100]算了。

如果VS报错:“E0167:const char *类型的实参与char *类型的形参不兼容”,则请将文件后缀由.cpp改为.c

下面这个的next[]首元素是-1,和上课的0有些许区别。不过都一样。

这个计算的是“首元素下标为0”,但是题目要求的是“首元素是下标为1”,所以最后return的时候需要+1。

为了实现KMP算法来进行模式匹配,并返回匹配成功的位置或 -1,可以按照以下步骤完成 KMP 函数:

  1. 计算模式字符串 T 的长度。
  2. 创建辅助数组 next,用于存储模式字符串中每个位置前缀的最长可匹配前缀子串的结束位置。
  3. 根据模式字符串 T 构建 next 数组。
  4. 初始化 next[0]-1
  5. 初始化两个指针 ij,其中 i = 0j = -1
  6. 通过比较 T[i]T[j] 的字符来更新 next[i+1]
    • 如果 T[i]T[j] 相等,则将 next[i+1] 设置为 next[j] + 1,然后递增 ij
    • 如果 T[i]T[j] 不相等,将 j 更新为 next[j] 的值,直到 j-1T[i]T[j] 相等。然后将 next[i+1] 设置为 j + 1,然后递增 i
  7. 使用 next 数组进行字符串匹配。
  8. 初始化两个指针 ij,其中 i = 0j = 0
  9. 通过比较 S[i]T[j] 的字符进行匹配:
    • 如果 S[i]T[j] 相等,则递增 ij
    • 如果 S[i]T[j] 不相等:
    • 如果 j0,说明当前字符不匹配且无法继续回退,将 i 递增。
    • 否则,将 j 更新为 next[j] 的值。
  10. 根据匹配的结果返回相应的位置或 -1

下面是完整的代码实现:

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
int KMP(char *S, char *T) {
    int len_s = strlen(S);
    int len_t = strlen(T);

    // 构建 next 数组
    int next[len_t];
    next[0] = -1;
    int i = 0, j = -1;
    while (i < len_t - 1) {
        if (j == -1 || T[i] == T[j]) {
            i++;
            j++;
            next[i] = j;
        } else {
            j = next[j];
        }
    }

    // 使用 next 数组进行字符串匹配
    i = 0;
    j = 0;
    while (i < len_s && j < len_t) {
        if (j == -1 || S[i] == T[j]) {
            i++;
            j++;
        } else {
            j = next[j];
        }
    }

    if (j == len_t) {
        return i - j + 1; // 返回匹配成功的位置
    } else {
        return -1; // 匹配不成功
    }
}

标准答案

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
void Next(char* T, int* next) {
    int i = 1;
    next[1] = 0;
    int j = 0;
    while (i < strlen(T)) {
        if (j == 0 || T[i - 1] == T[j - 1]) {
            i++;
            j++;
            next[i] = j;
        }
        else {
            j = next[j];
        }
    }
}

int KMP(char* S, char* T) {
    int next[10];
    Next(T, next);
    int i = 1;
    int j = 1;
    while (i <= strlen(S) && j <= strlen(T)) {
        if (j == 0 || S[i - 1] == T[j - 1]) {
            i++;
            j++;
        }
        else {
            j = next[j];
        }
    }
    if (j > strlen(T)) {
        return i - (int)strlen(T);
    }
    return -1;
}

统计字符串中字符频度

请完成函数Account_char_count,该函数接受一个字符串参数,统计字符串中各个字符的频度,并输出每个字符及其频度。(字符串的合法字符为A ~ Z26个大写字母和0 ~ 910个数字,其它字符忽略)。

示例

输入

Text Only
1
请输入待统计的字符串(合法字符为A~Z和0~9):123321ASDDSA

输出(请按此格式输出)

Text Only
1
2
3
4
5
6
1的频度为:2
2的频度为:2
3的频度为:2
A的频度为:2
S的频度为:2
D的频度为:2

题目

C
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
#include <stdio.h>
#define SIZE 1000

void Account_char_count(char str[]){
     //请在此处编写代码


}

int main(){
     int i=0;
     char str[SIZE];
     printf("请输入待统计的字符串(合法字符为A~Z和0~9):");
     while((str[i]=getchar())!='\n')
         i++;
     str[i]='\0';
     Account_char_count(str);
} 

答案

先看看我第一次写的,通不过检查,因为输入顺序是按照ABCD顺序,而非题目输入顺序。

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
#include <stdio.h>
#define SIZE 1000

void Account_char_count(char str[]) {
    int count[36] = { 0 };  // 用于统计字符频度的数组,下标 0-25 对应 A-Z,下标 26-35 对应 0-9

    for (int i = 0; str[i] != '\0'; i++) {
        char c = str[i];
        if (c >= 'A' && c <= 'Z') {
            count[c - 'A']++;
        }
        else if (c >= '0' && c <= '9') {
            count[c - '0' + 26]++;
        }
    }

    for (int i = 26; i < 36; i++) {
        if (count[i] != 0) {
            printf("%c的频度为:%d\n", '0' + i - 26, count[i]);
        }
    }

    for (int i = 0; i < 26; i++) {
        if (count[i] != 0) {
            printf("%c的频度为:%d\n", 'A' + i, count[i]);
        }
    }

}

int main() {
    int i = 0;
    char str[SIZE];

    printf("请输入待统计的字符串(合法字符为A~Z和0~9):");
    while ((str[i] = getchar()) != '\n') {
        i++;
    }
    str[i] = '\0';

    Account_char_count(str);

    return 0;
}

按照输入顺序输出。

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
void Account_char_count(char str[]) {
    int count[36] = { 0 };  // 用于统计字符频度,下标 0-25 对应 A-Z,下标 26-35 对应 0-9
    int visited[36] = { 0 };  // 记录字符是否已经输出过,0表示没有输出过,1表示输出过

    // 统计字符频度
    for (int i = 0; str[i] != '\0'; i++) {
        char c = str[i];

        if (c >= 'A' && c <= 'Z') {
            count[c - 'A']++;
        }
        else if (c >= '0' && c <= '9') {
            count[c - '0' + 26]++;
        }
    }

    // 输出
    for (int i = 0; str[i] != '\0'; i++) {
        char c = str[i];

        // 这里使用了一个额外的数组 visited 来记录字符是否已经输出过,避免重复输出相同字符的频度。
        // 在遍历字符串时,如果遇到一个字符是第一次遇到的字符,则输出其频度,并将对应的 visited 数组标记为已输出。
        // 这样可以保证按照输入字母的顺序输出字符及其频度。
        if (c >= 'A' && c <= 'Z' && !visited[c - 'A']) {
            visited[c - 'A'] = 1;

            printf("%c的频度为:%d\n", c, count[c - 'A']);
        }
        else if (c >= '0' && c <= '9' && !visited[c - '0' + 26]){
            visited[c - '0' + 26] = 1;

            printf("%c的频度为:%d\n", c, count[c - '0' + 26]);
        }
    }
}

标准答案(有点乱,自己的就OK)

C
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
void Account_char_count(char str[]) {
    char account_chr[SIZE];//存放每个不同的字符 
    int count[SIZE] = { 0 };//初始化每个字符的频度为0 
    int i, j, n = 0;//n表示字符种类 
    for (i = 0; str[i] != '\0'; i++) {
        for (j = 0; j < n; j++)
            if (str[i] == account_chr[j] || (account_chr[j] >= 'a' && account_chr[j] <= 'z' && str[i] + 32 == account_chr[j]))
                break;//往account_chr数组中存放的字符不可以重复 
        if (j < n)
            count[j]++;//字符出现过,频度加1 
        else {
            if (str[i] >= 'A' && str[i] <= 'Z')
                account_chr[j] = str[i];
            else
                account_chr[j] = str[i];
            count[j]++;
            n++; //新字符,放到 account_chr中,频度加1 
        }
    }
    for (i = 0; i < n; i++)
        printf("%c的频度为:%d\n", account_chr[i], count[i]);
}

将一段字符插入到另一段字符中的指定位置

编写算法,实现下面函数的功能。函数void insert(char *s, char *t, int pos)将字符串t插入到字符串s中,插入位置为pos,插入后字符之间不能有空位置。假设分配给字符串s的空间足够让字符串t插入。

示例

输入

Text Only
1
2
3
4
5
请输入字符串s:123

请输入字符串t:asd

输入插入的位置(位置从1开始):2

输出

Text Only
1
字符串插入后的新字符串为:1asd23

题目

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
#include <stdio.h>
#include <stdlib.h>

#define SIZE1 200
#define SIZE2 50

void insert(char *s, char *t, int pos){
     //请在此处编写代码

}

int main(){ 

    char s[SIZE1], t[SIZE2];
    int pos;

    printf("请输入字符串s:");
    scanf("%s", s); 
    printf("\n请输入字符串t:");
    scanf("%s", t); 

    printf("\n输入插入的位置(位置从1开始):");
    scanf("%d", &pos);
    printf("\n字符串插入后的新字符串为:");
    insert(s, t, pos);
    return 0;
}

答案

C
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
void insert(char* s, char* t, int pos) {
    int s_len = strlen(s);
    int t_len = strlen(t);
    int new_len = s_len + t_len;
    int i, j;

    pos--; // 设置首元素下标为‘1’

    // 向右移动原字符串s中的字符,给插入的字符串t腾出空间
    for (i = s_len; i >= pos; i--) {
        s[i + t_len] = s[i];
    }

    // 将字符串t插入到字符串s中
    for (j = 0; j < t_len; j++) {
        s[pos + j] = t[j];
    }

    // 输出插入后的新字符串
    for (i = 0; i < new_len; i++) {
        printf("%c", s[i]);
    }
}

标准答案(不太好)

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
void insert(char* s, char* t, int pos) {
    //将字符串插入到另一个字符串的指定位置

    char* strs = s, * strt = t;

    int i = 0;
    while (*strs && i < pos - 1) {
        strs++;
        i++;
    }
    if (pos < 1 || *strs == '\0') {
        printf("输入的pos值错误!\n");
        exit(0);
    }//判断是否输入错误,输入错误时,正常退出 

    while (*strt != '\0') {
        strt++;//找到t字符串的末位 
    }
    strs = s + pos - 1;
    while (*strs != '\0') {
        *(strt++) = *(strs++);//将字符串s的pos后的字符放到t中 
    }
    strs = s + pos - 1;
    while (*t != '\0') {
        *(strs++) = *(t++);//pos后的部分放回原位置 
    }
    *strt = *strs = '\0';//末尾制空
    printf("%s", s);//输出字符串s 
}

将数组中的正数排在负数前面

设任意n个整数存放于数组A[1...n]中,试编写算法,完善函数Change,将所有正数排在所有负数前面(要求算法复杂度为O(n))。

示例

输入

Text Only
1
2
3
4
5
6
7
请输入数组中元素个数:3

请输入第1个元素个数:-1

请输入第2个元素个数:2

请输入第3个元素个数:3

输出

Text Only
1
调整次序后的元素序列为:3 2 -1

题目

C
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <stdio.h>
#define MAX 100

void Change(int A[],int n){
     //请在此处编写代码

}

int main(){
    int A[MAX],i,n;
    printf("请输入数组中元素个数:");
    scanf("%d",&n);
    for(i=0;i<n;i++){
        printf("\n请输入第%d个元素个数:",i+1);
        scanf("%d",&A[i]);
     }

    Change(A,n);
    printf("\n调整次序后的元素序列为:");
    for(i=0;i<n;i++)
        printf("%d ",A[i]);
    return 0;
}

答案

使用两个指针来实现将正数排在负数前面的功能。一个指针从数组的开头开始,另一个指针从数组的末尾开始。然后,交换两个指针指向的元素,直到两个指针相遇。这样,正数就会排在负数前面。

算法的时间复杂度是 O(n),因为我们只需要遍历数组一次来将正数排在负数前面。

直接上POE吧:

  1. 初始化左指针 left 为数组的开头(索引为 0),右指针 right 为数组的末尾(索引为 n - 1)。

  2. 进入循环,条件是左指针小于右指针。这是因为当左指针和右指针相遇时,意味着已经完成了所有元素的调整,不再需要继续交换。

  3. 在循环中,左指针从数组的开头开始向右移动,直到找到第一个负数。这是通过检查 A[left] > 0 来判断的。如果 A[left] 是正数,就继续向右移动左指针。这样,左指针最终会指向第一个负数或者数组的末尾。

  4. 在循环中,右指针从数组的末尾开始向左移动,直到找到第一个正数。这是通过检查 A[right] < 0 来判断的。如果 A[right] 是负数,就继续向左移动右指针。这样,右指针最终会指向第一个正数或者数组的开头。

  5. 如果左指针小于右指针,说明找到了需要交换的元素。在这种情况下,交换左指针和右指针指向的元素。这样就将一个正数放在了负数的前面。

  6. 重复步骤 3 到 5,直到左指针和右指针相遇,完成所有元素的调整。

这个算法的关键在于通过左指针寻找负数,右指针寻找正数,然后交换它们的位置。通过不断向中间移动指针,并在需要交换时执行交换操作,最终可以将所有正数排在负数前面。

C
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
void Change(int A[], int n) {
    int left = 0;  // 左指针
    int right = n - 1;  // 右指针

    while (left < right) {
        // 左指针找到第一个负数
        while (left < right && A[left] > 0) {
            left++;
        }

        // 右指针找到第一个正数
        while (left < right && A[right] < 0) {
            right--;
        }

        // 交换左右指针指向的元素
        if (left < right) {
            int temp = A[left];
            A[left] = A[right];
            A[right] = temp;
        }
    }
}

标准答案(都一样)

C
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
void Change(int A[], int n) {
    //将所有正数都排在负数前面
    int i = 0, j = n - 1, temp;
    while (i < j) {
        if (i < j && A[i]>0)
            i++;
        if (i < j && A[j] < 0)
            j--;
        if (i < j) {
            temp = A[i];
            A[i++] = A[j];
            A[j--] = temp;
        }
    }
}

字符串逆置

请编写代码,实现字符串的逆置操作。Char_Reverse是一个递归函数,该函数接受一个字符数组,通过递归方式实现字符串的逆置,并将逆置后的字符串存储在原数组中。

注意:逆置的字符串以字符’#'作为结束标志。字符数组的长度不超过预定义的最大长度。

示例

输入

Text Only
1
请输入一个字符串:asdfg#

输出

Text Only
1
字符串逆置之后为:gfdsa

题目

C
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
#include <stdio.h>
#define MAXSIZE 100

void Char_Reverse(char array[]){
    //请在此处编写代码

}

int main(){
    char array[MAXSIZE];
    printf("请输入一个字符串(以“#”结束):");
    Char_Reverse(array);
    printf("字符串逆置之后为:%s",array);
    return 0;
}

答案

需要改一下main(),要不然真的不知道怎么递归。

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
#include <stdio.h>
#include <string.h>

#define MAXSIZE 100

void Char_Reverse(char array[], int start, int end) {
    if (start >= end) {
        return;
    }

    // 交换首尾字符
    char temp = array[start];
    array[start] = array[end];
    array[end] = temp;

    // 递归处理剩余部分
    Char_Reverse(array, start + 1, end - 1);
}

int main() {
    char array[MAXSIZE];
    printf("请输入一个字符串(以 '#' 结束):");
    fgets(array, MAXSIZE, stdin);

    // 移除换行符
    array[strcspn(array, "\n")] = '\0';

    // 计算字符串长度
    int length = strlen(array);

    // 逆置字符串(不包括 '#')
    Char_Reverse(array, 0, length - 1);

    printf("字符串逆置之后为:%s\n", array);
    return 0;
}

关于strcspn()函数:

strcspn 函数是 C 语言中的一个字符串函数,其原型定义在 <string.h> 头文件中。

函数签名如下:

C
1
size_t strcspn(const char *str1, const char *str2);

该函数用于计算字符串 str1 开头连续不包含字符串 str2 中任何字符的字符数,也即返回 str1 中第一个匹配 str2 中任何字符的位置的索引。

具体来说,strcspn 函数会从 str1 的开头开始逐个字符比较,直到遇到 str2 中的任意字符,或者到达 str1 的结尾为止。返回的值是 str1 开头连续不包含 str2 中任何字符的字符数,即第一个匹配的字符在 str1 中的索引位置。

下面是一个示例来说明 strcspn 函数的使用:

C
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
#include <stdio.h>
#include <string.h>

int main() {
    char str1[] = "Hello, World!";
    char str2[] = "Wod";

    size_t index = strcspn(str1, str2);

    printf("第一个匹配字符的索引位置:%zu\n", index);

    return 0;
}

输出结果为:

Text Only
1
第一个匹配字符的索引位置:6

在上面的示例中,str1 是要搜索的字符串,str2 是要匹配的字符集合。函数返回的是 str1 中第一个匹配 str2 中任何字符的位置的索引。在这个示例中,字符 'W' 在 str1 中的索引位置为 6。

标准答案(考试用这个)

用了static。这递归还是很有水平的。

C
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
void Char_Reverse(char array[]) {
    char str;
    static int i = 0;//数组下标
    scanf("%c", &str);
    if (str != '#') {
        Char_Reverse(array);
        array[i++] = str;//先存的放到后边
    }
    array[i] = '\0';
}

复制字符串

请编写代码,完善函数copy,实现将字符串 s2 的全部字符复制到字符串 s1 中。该函数接受两个字符串参数 s1 和 s2,将字符串 s2 的全部字符复制到字符串 s1 中,并输出复制后的字符串 s1。

注意:禁止使用strcpy函数实现复制字符串功能。

示例

输入

Text Only
1
2
请输入s1中的字符串:123
请输入s2中的字符串:asd

输出

Text Only
1
复制之后字符串s1为:asd

题目

C
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
#include <stdio.h>
#define N 100 

void copy(char s1[], char s2[]){
    //请在此处编写代码


} 

int main(){
    char s1[N], s2[N];
    printf("请输入s1中的字符串:");
    scanf("%s", s1);
    printf("请输入s2中的字符串:");
    scanf("%s", s2);
    copy(s1, s2);
    return 0;
}

答案

C
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
void copy(char s1[], char s2[]) {
    int i = 0;

    // 复制字符串s2到s1
    while (s2[i] != '\0') {
        s1[i] = s2[i];
        i++;
    }

    s1[i] = '\0'; // 添加字符串结束符
    printf("复制之后字符串s1为:%s\n", s1);
}

标准答案

C
1
2
3
4
5
6
7
8
void copy(char s1[], char s2[]) {
    int i;
    for (i = 0; s2[i] != '\0'; i++) {
        s1[i] = s2[i];
    }
    s1[i] = '\0';
    printf("复制之后字符串s1为:%s\n", s1);
}

分离数组中的奇数和偶数

分离数组中的奇数和偶数,存放在原数组中。 请编写代码,完善函数Separate,实现将数组中的奇数和偶数分开的操作。该函数接受一个整数数组 arr 和数组的长度 length,将数组中的奇数和偶数分开,并按照奇数在前、偶数在后的顺序重新排列数组。

示例

输入

Text Only
1
main()函数中设置arr[] = { 3, 2, 3, 4, 5, 9, 7, 8, 9 };

输出

Text Only
1
变换次序后的数组为:9 7 9 5 3 3 8 4 2

题目

C
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <stdio.h>
#include <stdlib.h>

#define MAX 10

void Separate(int arr[],int length){
     //请在此处编写代码

} 

int main(){
     int arr[] = { 3, 2, 3, 4, 5, 9, 7, 8, 9 };
     int length = sizeof(arr) / sizeof(arr[0]);//计算数组的长度 

     // printf("变换次序后的数组为:");
     Separate(arr,length);
     for (int i = 0; i < length; i++){
         printf("%d ", arr[i]);//输出数组 
     }
     exit(0);//执行完正常退出 
     return 0;
}

答案

先看一段错误代码,用的方法和上边的“将数组中的整数排在负数前面”,不知道为什么过不了检查。问题在于输出的顺序(完成了分离奇数偶数,但是奇数偶数中的顺序不对)

C
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
void Separate(int arr[], int length) {
    int i = 0;
    int j = length - 1;

    while (i < j) {
        // 从前往后找到第一个偶数
        while (i < j && arr[i] % 2 != 0) {
            i++;
        }

        // 从后往前找到第一个奇数
        while (i < j && arr[j] % 2 == 0) {
            j--;
        }

        // 交换偶数和奇数的位置
        if (i < j) {
            int temp = arr[i];
            arr[i] = arr[j];
            arr[j] = temp;
        }
    }
}

~~正确答案~~(bushi

能过检查点的答案。(不难看出,我对这个题非常无语)

还是看官方答案吧,人家的代码确实好!

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
void Reverse(int arr[], int start, int end) {
    while (start < end) {
        int temp = arr[start];
        arr[start] = arr[end];
        arr[end] = temp;
        start++;
        end--;
    }
}

void Separate(int arr[], int length) {
    int oddCount = 0; // 奇数计数器

    // 统计奇数的个数
    for (int i = 0; i < length; i++) {
        if (arr[i] % 2 != 0) {
            oddCount++;
        }
    }

    // 复制原数组到临时数组tmpArr
    int* tmpArr = (int*)malloc(length * sizeof(int));
    for (int i = 0; i < length; i++) {
        tmpArr[i] = arr[i];
    }

    int oddIndex = 0; // 奇数部分的索引
    int evenIndex = oddCount; // 偶数部分的索引

    // 将奇数和偶数分别放置到对应的位置
    for (int i = 0; i < length; i++) {
        if (tmpArr[i] % 2 != 0) {
            arr[oddIndex++] = tmpArr[i];
        }
        else {
            arr[evenIndex++] = tmpArr[i];
        }
    }

    // 对奇数部分进行逆序
    Reverse(arr, 0, oddCount - 1);
    // 对偶数部分进行逆序
    Reverse(arr, oddCount, length - 1);

    free(tmpArr);
}

标准答案(考试用这个)

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
void Separate(int originalArray[], int length) {
    // 将数组中的奇数和偶数分开存储到两个不同的数组中

    int i = 0, oddIndex = 0, evenIndex = 0;
    int odd[MAX] = { 0 }, even[MAX] = { 0 };

    // 遍历原始数组
    while (i < length) {
        // 如果当前元素为奇数,存储到奇数数组中
        if (originalArray[i] % 2 == 1) {
            odd[oddIndex++] = originalArray[i++];
        }
        // 如果当前元素为偶数,存储到偶数数组中
        else {
            even[evenIndex++] = originalArray[i++];
        }
    }

    // 重置循环变量以便后续遍历
    i = 0;
    oddIndex--; // 因为之后用下标,从0开始
    evenIndex--;

    // 将奇数数组中的元素复制回原始数组
    while (oddIndex != -1) {
        originalArray[i++] = odd[oddIndex--];
    }

    // 将偶数数组中的元素复制回原始数组
    while (evenIndex != -1) {
        originalArray[i++] = even[evenIndex--];
    }
}

判断三维数组中是否存在鞍点

判断三维数组中是否存在鞍点,如果存在则输出。(鞍点:一行中的最大值,并且也是一列中的最小值) 请编写代码,完善函数Find,实现在给定的 3x3 数组中找到鞍点。鞍点是指在数组中的某个元素,它在所在行上是最大值,在所在列上是最小值。该函数接受一个二维数组 arr 和数组的行数 row 和列数 col,查找数组中的鞍点。

要求

Text Only
1
2
1、如果鞍点不存在,则输出 “该数组中不存在鞍点!”。(双引号中的内容)
2、如果鞍点存在,则输出 “该数组中存在鞍点arr[%d][%d] = %d”。(%d代表相应的数据)

示例

输入

Text Only
1
2
3
4
请输入数组:
7 8 3
5 7 5
1 8 3

输出

Text Only
1
该数组中存在鞍点arr[1][1] = 7 (第2行第2列)

题目

C
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
#define ROW 3
#define COL 3       

#include <stdio.h>
#include <stdlib.h>

void Find(int arr[][COL], int row, int col){
     //请在此处编写代码

}

int main(){
     int arr[ROW][COL] = { 0 };
     Find(arr, ROW, COL);               
     return 0;
}

答案

官方答案是把咱放main()里面的东西放到了函数里面实现。

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
#include <stdio.h>

#define ROW 3
#define COL 3                          

void Find(int arr[][COL], int row, int col) {
    int i, j;
    int max_row, min_col;
    int flag = 0; // 标记是否找到了鞍点

    // 遍历每一行
    for (i = 0; i < row; i++) {
        // 找到当前行中的最大值
        max_row = arr[i][0];
        for (j = 1; j < col; j++) {
            if (arr[i][j] > max_row) {
                max_row = arr[i][j];
            }
        }

        for (j = 0; j < col; j++) {
            // 找到当前行中最大值对应的列索引
            if (arr[i][j] == max_row) {

                // 检查该列中的元素是否是最小值
                min_col = arr[0][j];
                for (int k = 0; k < row; k++) {
                    if (arr[k][j] < min_col) {
                        min_col = arr[k][j];
                    }
                }

                // 如果当前行中的最大值也是所在列的最小值,则找到了鞍点
                if (min_col == max_row) {
                    printf("该数组中存在鞍点arr[%d][%d] = %d\n", i, j, max_row);
                    flag = 1;

                    break; // 不再继续搜索该行
                }
            }
        }
    }

    // 如果没有找到鞍点
    if (!flag) {
        printf("该数组中不存在鞍点!\n");
    }
}

int main() {
    int arr[ROW][COL] = { 0 };

    printf("请输入数组:\n");
    int i, j;
    for (i = 0; i < ROW; i++) {
        for (j = 0; j < COL; j++) {
            scanf("%d", &arr[i][j]);
        }
    }

    Find(arr, ROW, COL);
    return 0;
}

还是上POE吧:

这段代码是一个完整的程序,用于接收用户输入的3x3整数数组,并判断是否存在鞍点。

首先,我们定义了常量ROWCOL,分别表示数组的行数和列数。在这个例子中,我们将其设置为3。

接下来,我们定义了一个函数Find,用于查找鞍点。该函数接受一个二维数组arr、数组的行数row和列数col作为参数。

Find函数中,我们使用了两个嵌套的循环来遍历数组。外层循环用于遍历每一行,内层循环用于遍历每一列。

在外层循环中,我们首先找到当前行中的最大值max_row,并在内层循环中判断是否存在最小值min_col。如果当前行中的最大值也是所在列的最小值,则找到了鞍点。我们将其输出,并将鞍点找到标志flag设置为1。

若没有找到鞍点,则通过判断flag的值是否为0来输出"该数组中不存在鞍点!"的信息。

main函数中,我们声明了一个名为arr的二维数组,用于存储用户输入的数组。然后,我们使用两个嵌套的循环来接收用户输入的值,并将其存储在arr数组中。

最后,我们调用Find函数,并将arr数组、ROWCOL作为参数传递给它,以便查找鞍点。

通过这段代码,用户可以输入一个3x3的整数数组,并根据输入的数组判断是否存在鞍点。如果存在鞍点,将输出鞍点的位置和值;如果不存在鞍点,将输出"该数组中不存在鞍点!"的提示信息。

标准答案

不是我说,虽然这叫做“标准答案”,但是这col_min初始化的指定有点问题,逻辑不对,VS运行出来也不对。

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
void Find(int arr[][COL], int row, int col) {

    int i, j;
    printf("请输入数组:\n");

    // 读取用户输入的数组
    for (i = 0; i < ROW; i++) {
        for (j = 0; j < COL; j++) {
            scanf("%d", &arr[i][j]);
        }


    int row_max = 0, col_min = 0;  // 保存行最大值和列最小值              
    int tag = 0;  // 标记是否找到鞍点

    for (i = 0; i < ROW; i++) {
        row_max = arr[i][0];   // 假设每行第一个元素为最大值 
        col_min = arr[0][col]; // 假设每列第一个元素为最小值

        for (j = 0; j < COL; j++) {
            // 查找当前行的最大值及其列下标
            if (arr[i][j] > row_max) {
                row_max = arr[i][j];
                row = i;  // 记录当前行下标
                col = j;  // 记录当前列下标
            }
        }
        // 查找当前列的最小值
        for (j = 1; j < COL; j++) {
            if (arr[j][col] <= col_min)
                col_min = arr[j][col];
        }
        // 判断是否存在鞍点
        if (col_min == row_max) {
            printf("该数组中存在鞍点 arr[%d][%d] = %d\n", row, col, row_max);
            tag = 1;
        }
    }
    // 如果没有找到鞍点,则输出不存在的提示
    if (tag == 0)
        printf("该数组中不存在鞍点!\n");
}

自行改正(考试用这个)

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
void Find(int arr[][COL], int row, int col) {
    int i, j;
    printf("请输入数组:\n");

    for (i = 0; i < row; i++) {
        for (j = 0; j < col; j++) {
            scanf("%d", &arr[i][j]);
        }
    }

    int tag = 0;
    for (i = 0; i < row; i++) {
        int row_max = arr[i][0]; // 初始化每行的最大值
        int col_index = 0; // 记录最大值所在的列索引

        // 找出当前行的最大值和其列索引
        for (j = 1; j < col; j++) {
            if (arr[i][j] > row_max) {
                row_max = arr[i][j];
                col_index = j;
            }
        }

        // 检查当前列是否为该最大值所在的列中的最小值
        int col_min = arr[0][col_index];
        for (j = 0; j < row; j++) {
            if (arr[j][col_index] < col_min) {
                col_min = arr[j][col_index];
            }
        }

        // 如果该列中的最小值与该行中的最大值相等,则找到鞍点
        if (col_min == row_max) {
            printf("该数组中存在鞍点 arr[%d][%d] = %d\n", i, col_index, row_max);
            tag = 1;
        }
    }

    if (tag == 0) {
        printf("该数组中不存在鞍点!\n");
    }
}