二维数组与字符串综合

C++ 三级难点讲解:二维数组与字符串综合

在 GESP/等级考试三级中,二维数组(矩阵) 和字符数组(字符串) 是难度跃升最大的两个模块。它们不像一级二级那样只考简单循环,而是要求你用数组去模拟复杂逻辑。

难度定位

一级~二级:一维数组、简单字符串遍历

三级核心难点:

二维数组的行列遍历、矩阵变换(转置、旋转、蛇形)

字符数组char str[]与cstring函数(strlen,strcpy,strcmp)

字符串与数组/数学的综合题

四级及以上:结构体、多级指针、简单算法

整体来说,三级是从"写代码"到"用数据结构建模"的转折点,二维数组是分水岭。

下面我整理了两道三级常考的经典题型,帮你突破这个难点:

1. 二维数组:矩阵转置(行列互换)

问题描述

给定一个 n×m 的矩阵,输出它的转置矩阵(第 i 行第 j 列变成第 j 行第 i 列)。

输入格式

第一行两个整数 n, m(均不超过 100)。

接下来 n 行,每行 m 个整数。

输出格式

输出转置后的矩阵,共 m 行,每行 n 个整数。

样例

输入:

3 2

1 2

3 4

5 6

输出:

1 3 5

2 4 6

题意回顾

原矩阵 3 行 2 列 → 转置后变成 2 行 3 列。

本质是:a[i][j]→ 放到b[j][i]的位置。

核心思路:双重循环 + 下标互换

开一个原矩阵a[n][m]和一个转置矩阵b[m][n]

遍历原矩阵:对每个a[i][j],把它赋值给b[j][i]

输出b矩阵

关键理解:i是行号,j是列号。转置就是把"行变列、列变行",所以下标互换。

代码逐行解析

#include <bits/stdc++.h>

using namespace std;

int main(){

    int n, m;

    cin >> n >> m;


    int a[105][105], b[105][105];  // 开大一点防止越界


    // 读入原矩阵

    for(int i = 0; i < n; i++){

        for(int j = 0; j < m; j++){

            cin >> a[i][j];

        }

    }


    // 转置:a[i][j] → b[j][i]

    for(int i = 0; i < n; i++){

        for(int j = 0; j < m; j++){

            b[j][i] = a[i][j];  // 核心:下标互换

        }

    }


    // 输出转置后的矩阵(m 行 n 列)

    for(int i = 0; i < m; i++){

        for(int j = 0; j < n; j++){

            cout << b[i][j] << " ";

        }

        cout << endl;

    }


    return 0;

}

复杂度

时间:O(n×m),遍历两遍矩阵

空间:O(n×m),开了一个辅助矩阵

常见错误提醒

错误后果

输出时还是for i<n, j<m输出维度和原矩阵一样,没转置

b[i][j] = a[i][j]没互换下标,只是复制

数组开a[100][100]但输入 100×100下标从 0 到 99 刚好,但如果用 1~100 就越界

忘记换行cout << endl输出格式错误,全部挤一行

🧠 进阶变体

原地转置? 只有方阵(n=m)才能原地,用swap(a[i][j], a[j][i])只遍历上三角

矩阵旋转 90°? 转置后再每行反转,或者直接用b[j][n-1-i] = a[i][j]

蛇形填数? 按方向模拟,需要dir数组控制上下左右

2. 字符数组与字符串:单词计数

问题描述

输入一行可能包含空格的字符串(英文句子),统计其中有多少个单词。单词之间用一个或多个空格隔开。

输入格式

一行字符串,长度不超过 1000。

输出格式

一个整数,表示单词个数。

样例

输入:Hello  world  from  C++

输出:4

题意回顾

给定一行带空格的字符串,单词由字母组成,词间可能多个空格。统计单词总数。

核心思路:状态切换法(或cin >> string流)

方法一:用cin >> string逐个读单词(最简单)

cin遇到空格自动截断,每次读一个单词,读几次就是几个单词。

方法二:字符数组遍历(三级常考,理解原理)

遍历字符数组,遇到"从空格变成非空格"的瞬间,说明新单词开始了 → 计数+1。

代码逐行解析(方法一:推荐,简洁)

#include <bits/stdc++.h>

using namespace std;

int main(){

    string s;

    int cnt = 0;


    // cin >> s 会自动跳过前导空格,每次读一个单词

    while(cin >> s){

        cnt++;

    }


    cout << cnt;

    return 0;

}

方法二:字符数组遍历(理解底层逻辑)

#include <bits/stdc++.h>

using namespace std;

int main(){

    char str[1005];

    cin.getline(str, 1005);        // 读一整行(含空格)


    int len = strlen(str);

    int cnt = 0;

    bool inWord = false;          // 标记当前是否在单词内


    for(int i = 0; i < len; i++){

        if(str[i] != ' ' && !inWord){

            // 从空格进入单词 → 新单词开始

            cnt++;

            inWord = true;

        }

        else if(str[i] == ' '){

            // 遇到空格 → 离开单词

            inWord = false;

        }

    }


    cout << cnt;

    return 0;

}

逐行解析(方法二)

cin.getline(str, 1005)— 读取整行,包括空格,存到字符数组

strlen(str)— 算实际长度(不含\0)

inWord是状态标记:

false表示当前在空格区

true表示正在单词内部

当str[i]不是空格且inWord == false→ 刚进入新单词 →cnt++

复杂度

时间:O(n),n ≤ 1000

空间:O(1) 或 O(n)(存字符串)

常见错误提醒

错误后果

用cin >> str而不是getline只能读第一个单词,遇空格就停

多个连续空格时if(str[i]!=' ')直接cnt++一个单词里每个字母都算一次

strlen用在未初始化的char[]找不到\0,返回随机值

忘记#include <cstring>strlen编译报错

🧠 延伸变体

统计每个单词的长度? 进入单词时记起始位置,离开时算差值

找最长的单词? 边计数边记录最大长度

字符串反转(单词不反)? 先整体反转,再逐个单词反转回来

大数加法? 两个字符串逐位相加,进位存数组

📌 一句话总结

模块核心考点一句话口诀

二维数组双重循环、下标映射"i 是行 j 是列,转置互换就完事"

字符数组strlen/strcpy/strcmp、状态遍历"空格切单词,状态记进出"

字符串转数字s[i]-'0'"位数超 19,一律当字符串"

掌握这两道例题的套路,三级的数组和字符串大题基本都能拿到分。二维数组多画图模拟,字符串多手动追踪状态,考试时不慌。

制作不易,如果对你有帮助,点个赞吧 😁

最后编辑于 :
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容