遍历时输出的思想(NENU 1133: 4204 W密码)


这是我在解决一位同学提出字符串问题时想到的:

简要介绍

优点

在写程序时,在遍历数组的过程中输出数组元素值有以下优点

  • 调试代码:在程序运行出错时,可以通过输出数组元素的值来判断是不是数组读取操作出现了问题。例如,我们可以在循环中加入 printf
    输出语句,打印出每个数组元素的值来进行调试。

  • 确认数组内容:在处理一些复杂的数据结构时,需要确认数组内部存储的具体内容,以便进行后续操作。通过遍历数组并输出元素的值,可以帮助我们更直观地查看数组的内容。

  • 分析算法复杂度:当我们分析某个算法的时间复杂度时,需要知道某个操作(如数组遍历)的实际执行次数。通过在遍历时输出数组元素的值,可以帮助我们更好地理解算法复杂度,并进行相关优化。

  • 验证算法正确性:在编写算法时,可以通过输出数组元素的值来验证算法是否正确。例如,对于排序算法,可以在排序完成后输出已经排好序的数组元素,以确保算法的正确性。

总之,在遍历数组时输出数组元素的值可以帮助我们更直观地了解数组的内容,同时也可以帮助我们进行调试、分析算法复杂度和确认算法正确性等方面的工作。

实例

#include <stdio.h>

int main() {
    int arr[5] = {1, 2, 3, 4, 5};
    
    printf("Using for loop and array subscript:\n");
    for (int i = 0; i < 5; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");

    printf("Using for loop and pointer arithmetic:\n");
    for (int *p = arr; p < arr + 5; p++) {
        printf("%d ", *p);
    }
    printf("\n");

    printf("Using while loop and array subscript:\n");
    int i = 0;
    while (i < 5) {
        printf("%d ", arr[i]);
        i++;
    }
    printf("\n");

    printf("Using while loop and pointer arithmetic:\n");
    int *p = arr;
    while (p < arr + 5) {
        printf("%d ", *p);
        p++;
    }
    printf("\n");

    return 0;
}

该示例代码定义了一个整型数组 arr 并对其进行初始化。接下来,我们分别使用 for 循环和 while 循环,以及数组下标和指针算术运算两种方式来遍历数组,并在遍历时输出每个数组元素的值。

需要注意的是,在使用指针遍历数组时,首先需要将指针初始化为数组名,即 int *p = arr。然后,可以使用指针算术运算来移动指针的位置,进而遍历整个数组。在循环中,要始终确保指针所指向的内存空间是合法的,并不越界。

总之,在 C 语言中,可以通过循环来遍历数组,并在遍历的同时输出数组元素的值,从而实现对数组的操作。

下面是这位同学问我的题:

1133: 4204 W密码

内存限制:128 MB 时间限制:1.000 S 评测方式:文本比较 命题人:admin 题目描述 加密一条信息需要三个整数码, k1,
k2 和 k3。字符[a-i] 组成一组, [j-r] 是第二组, 其它所有字符 ([s-z] 和下划线)组成第三组。
在信息中属于每组的字符将被循环地向左移动ki个位置。
每组中的字符只在自己组中的字符构成的串中移动。解密的过程就是每组中的字符在自己所在的组中循环地向右移动ki个位置。 例如对于信息
the_quick_brown_fox 以ki 分别为 2, 3 和 1进行加密。加密后变成
_icuo_bfnwhoq_kxert。
下图显示了右旋解密的过程。

在这里插入图片描述

右旋解密示意图

观察在组[a-i]中的字符,我们发现{i,c,b,f,h,e}出现在信息中的位置为{2,3,7,8,11,17}。当k1=2右旋一次后,
上述位置中的字符变成{h,e,i,c,b,f}。下表显示了经过所有第一组字符旋转得到的中间字符串,然后是所有第二组,第三组旋转的中间字符串。在一组中变换字符将不影响其它组中字符的位置。
所有输入字符串中只包含小写字母和下划线( _ )。每个字符串的长度不超过80个字符。ki 是1-100之间的整数。

输入
输入包括一到多组数据。每个组前面一行包括三个整数 k1, k2 和 k3,后面是一行加密信息。输入的最后一行是由三个0组成的。
输出
对于每组加密数据,输出它加密前的字符串。
样例输入 复制
2 3 1
_icuo_bfnwhoq_kxert
1 1 1
bcalmkyzx
3 7 4
wcb_mxfep_dorul_eov_qtkrhe_ozany_dgtoh_u_eji
2 4 3
cjvdksaltbmu
0 0 0
样例输出 复制
the_quick_brown_fox
abcklmxyz
the_quick_brown_fox_jumped_over_the_lazy_dog
ajsbktcludmv

思路

笔架 2023/4/15 21:50:46 分三个组

笔架 2023/4/15 21:51:01 从头到尾遍历一遍

笔架 2023/4/15 21:51:13 把对应字符输入到对应的组里

笔架 2023/4/15 21:51:26 然后再遍历一遍

笔架 2023/4/15 21:51:58 因为刚刚已经把对应字符放到一组里

笔架 2023/4/15 21:52:06 所以知道一组一共多少个

笔架 2023/4/15 21:52:48 用一个位置加总量%总量

笔架 2023/4/15 21:53:23 然后再加上要解密对应的数字

笔架 2023/4/15 21:53:35 就可以找到原文所对应的字符

笔架 2023/4/15 21:53:39 然后输出

笔架 2023/4/15 21:54:16 每次遍历的时候区分一下在整个数组和在分开的三个组内的位置

笔架 2023/4/15 21:54:21 或者说指针

笔架 2023/4/15 21:54:28 这样这道题就做出来了

笔架 2023/4/15 21:55:14 然后如果不是这三个组中的内容

笔架 2023/4/15 21:55:17 第一次遍历时不管

笔架 2023/4/15 21:55:24 第二次遍历时直接输出

这里是通过的代码(注释版):

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

int main() {
	int i, j, k1, k2, k3;
	while(scanf("%d %d %d", &k1, &k2, &k3) != EOF){
	    
		if (k1 == 0&&k2 == 0&&k3 == 0) {
			break;
		}
		
		//用来存输入
		char a[100];
		
		//这里用来存放三个组
		char s1[100],s2[100],s3[100];

		//这里是指针
		int m = 0, n = 0, h = 0;

		//接收换行符
		getchar();
		
		//输入数据
		scanf("%s",a);
		getchar();
		//遍历字符串,并分组
		for (i = 0; i < strlen(a); i++) {
			if (a[i] >= 'a' && a[i] <= 'i') {
				s1[m] = a[i];
				m++;
			}

			if (a[i] >= 'j' && a[i] <= 'r') {
				s2[n] = a[i];
				n++;
			}

			if ((a[i] >= 's' && a[i] <= 'z') || a[i] == '_') {
				s3[h] = a[i];
				h++;
			}
		}
		//用来存放经过修改后的三个组
		char x[100] = "", y[100] = "", z[100] = "";
		
		//分别解密三个组
		for (i = 0; i < m; i++) {
			x[i] = s1[(i + m - k1) % m];
		}
		for (i = 0; i < n; i++) {
			y[i] = s2[(i + n - k2) % n];
		}
		for (i = 0; i < h; i++) {
			z[i] = s3[(i + h - k3) % h];
		}


		//先给指针放回到初始位置
		m = 0;
		n = 0;
		h = 0;

		//输出答案
		for (i = 0; i < strlen(a); i++) {
			if (a[i] >= 'a' && a[i] <= 'i') {
				printf("%c", x[m]);
				m++;
			}

			else if (a[i] >= 'j' && a[i] <= 'r') {
				printf("%c", y[n]);
				n++;
			}

			else if ((a[i] >= 's' && a[i] <= 'z') || a[i] == '_') {
				printf("%c", z[h]);
				h++;
			}
		}
		printf("\n");
	}
	return 0;
}

这里是纯代码版:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
int main() {
	int i, j, k1, k2, k3;
	while(scanf("%d %d %d", &k1, &k2, &k3) != EOF){
		if (k1 == 0&&k2 == 0&&k3 == 0) {
			break;
		}
		char a[100];
		char s1[100],s2[100],s3[100];
		int m = 0, n = 0, h = 0;
		getchar();
		scanf("%s",a);
		getchar();
		for (i = 0; i < strlen(a); i++) {
			if (a[i] >= 'a' && a[i] <= 'i') {
				s1[m] = a[i];
				m++;
			}
			if (a[i] >= 'j' && a[i] <= 'r') {
				s2[n] = a[i];
				n++;
			}
			if ((a[i] >= 's' && a[i] <= 'z') || a[i] == '_') {
				s3[h] = a[i];
				h++;
			}
		}
		char x[100] = "", y[100] = "", z[100] = "";
		for (i = 0; i < m; i++) {
			x[i] = s1[(i + m - k1) % m];
		}
		for (i = 0; i < n; i++) {
			y[i] = s2[(i + n - k2) % n];
		}
		for (i = 0; i < h; i++) {
			z[i] = s3[(i + h - k3) % h];
		}
		m = 0;n = 0;h = 0;
		for (i = 0; i < strlen(a); i++) {
			if (a[i] >= 'a' && a[i] <= 'i') {
				printf("%c", x[m]);
				m++;
			}
			else if (a[i] >= 'j' && a[i] <= 'r') {
				printf("%c", y[n]);
				n++;
			}
			else if ((a[i] >= 's' && a[i] <= 'z') || a[i] == '_') {
				printf("%c", z[h]);
				h++;
			}
		}
		printf("\n");
	}
	return 0;
}

总结

  1. 阅读题目要仔细:在开始解题之前,一定要认真阅读题目描述,并理解题意,确保自己对问题的理解与出题人的意图一致。如果表述不清楚或存在歧义,及时询问出题人或者助教。

  2. 注意输入输出格式和范围:在写程序时,一定要注意输入和输出的格式和数据类型,以及输入数据的范围和约束条件。为了避免出现异常情况,需要在程序中添加必要的错误处理代码,如输入数据是否合法等判断。同时,在开发过程中,也需要通过样例数据来测试程序的正确性。

  3. 选好适合的算法:针对不同的问题,在解决方案选择上可能会使用到不同的算法,例如贪心、动态规划、搜索等。在选择算法时,需要根据题目特点进行分析,以确定哪一种算法是最优的解法。

  4. 编写可读性强的代码:编写可读性强、代码结构清晰的程序可以帮助我们更好地管理并维护程序,同时也可以降低程序出错的概率。当需要修改或更新程序时,良好的代码风格和注释可以使得开发者更容易地理解代码实现的细节和原理。

  5. 程序性能优化:对于一些复杂的问题,算法优化可能是解决问题的一个重要手段。在开发程序时,需要通过不同的技术手段(如代码改写、数据结构优化、提高代码并行度等)来优化程序的性能,以避免出现超时等异常情况。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值