1组成无重复数字的三位数
有1、2、3、4个数字,能组成多少个互不相同且无重复数字的三位数?都是多少?
分析:可填在百位、十位、个位的数字都是1、2、3、4。组成所有的排列后再去 掉不满足条件的排列。
#include <stdio.h>
#include <conio.h>
int main()
{
int i, j, k;
printf("\n");
for (i = 1; i < 5; i++) /*以下为三重循环*/
for (j = 1; j < 5; j++)
for (k = 1; k < 5; k++)
{
if (i != k && i != j && j != k) /*确保i、j、k三位互不相同*/
printf("%d, %d, %d\n", i, j, k);
}
getchar();
}
2在字符串中的所有数字字符前加一个$字符
问题描述
请编写程序,实现以下功能:在字符串中的所有数字字符前加一个$字符。例如,输入 A1B23CD45,输出 A$1B$2$3CD$4
5
。
问
题
分
析
方
法
一
:
用
串
S
拷
贝
出
另
一
个
串
T
,
对
串
T
从
头
至
尾
扫
描
,
对
非
数
字
字
符
原
样
写
入
串
S
,
对
于
数
字
字
符
先
写
一
个
5。 问题分析 方法一:用串S拷贝出另一个串T,对串T从头至尾扫描,对非数字字符原样写入串S,对于数字字符先写一个
5。问题分析方法一:用串S拷贝出另一个串T,对串T从头至尾扫描,对非数字字符原样写入串S,对于数字字符先写一个符号再写该数字字符,最后,在S串尾加结束标志。使用此方法是牺牲空间,赢得时间。
方法二:对串S从头至尾扫描,当遇到数字字符时,从该字符至串尾的所有字符右移一位,在该数字字符的原位置上写入一个$。使用此方法是节省了空间,但浪费了时间。
#include <stdio.h>
int fun(char *s)
{
char t[80];
int i, j;
for (i = 0; s[i]; i++) /*将串s拷贝至串t*/
t[i] = s[i];
t[i] = '\0';
for (i = 0, j = 0; t[i]; i++)
/*对于数字字符先写一个$符号,再写该数字字符*/
if (t[i] >= '0' && t[i] <= '9')
{
s[j++] = '$';
s[j++] = t[i];
}
/*对于非数字字符原样写入串s*/
else
s[j++] = t[i];
s[j] = '\0'; /*在串s结尾加结束标志*/
return 0;
}
int main()
{
char s[80];
printf("Enter a string:");
scanf_s("%s", s, 80); /*输入字符串*/
getchar();
fun(s);
printf("The result: %s\n", s); /*输出结果*/
getchar();
getchar();
return 0;
}
3除了字符串前后的号之外,将串中其他的号全部删除
现在有一串字符需要输入,规定输入的字符串中只包含字母和号。请编写程序,实现以下功能:除了字符串前后的号之外,将串中其他的*号全部删除。
例如,假设输入的字符串为ABCDEFG********,删除串中的号后,字符串变为****ABDEFG********
问题描述
该问题需要对字符串进行操作,而在C语言中没有专门的字符串变量,因此如果需要将一个字符串存放在变量中,则必须使用字符数组,即使用一个字符型数组来存放一个字符串,数组中的每一个元素存放一个字符。
算法分析
设置两个指向字符的指针变量t和f。先使用循环语句让t指针指向字符串中最后一个字符,而f指针指向字符串中第一个字符;再判断t和f指向的字符是否为“*”,如果为“**”,则t指针自减,f指针自增,直到遇到第一个不是的字符为止。
再定义一个函数fun()用于删除字符串中的“”号,同时保留字符串前后的“”号。
#include <stdio.h>
int fun(char *a, char *h, char *p)
{
int i, j;
/*删除指针h与p之间的所有“*”*/
for (i = 0, j = 0; &h[i] < p; i++)
if (h[i] != '*')
h[j++] = h[i];
/*将指针p至字符串尾部的所有字符前移*/
for (i = 0; p[i]; i++, j++)
h[j] = p[i];
h[j] = '\0'; /*在字符串尾部添加结束标志*/
return 0;
}
int main()
{
char s[81], *t, *f;
printf("Enter a string :\n");
gets_s(s); /*输入字符串*/
t = f = s; /*用字符指针t、f指向串s*/
while (*t)
t++;
t--; /*将指针t定位到字符串中最后一个字符*/
while (*t == '*') /*指针t指向字符串中最后一个字符*/
t--;
while (*f == '*') /*指针f指向字符串中第一个字符*/
f++;
fun(s, f, t);
printf("The string after deleted:\n"); /*输出结果*/
puts(s);
getchar();
return 0;
}
4输出一个矩阵的转置
问题描述
编写一个程序,将一个3行3列的矩阵转置
在对一个3x3阶矩阵转置时,只需将主对角线右上方的数组元素n[0][1]、n[0][2]、n[1][2],分别与主对角线左下放的数组元素n[1][0]、n[2][0]、n[2][1]的值,通过一个临时变量进行交换即可,总共只要进行3次交换就可以实现矩阵的转置。
#include<stdio.h>
int main()
{
int n[3][3] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
int i, j, temp;
printf("原始矩阵:\n");
for (i = 0; i < 3; i++)
{
for (j = 0; j < 3; j++)
printf("%d ", n[i][j]); /*输出原始矩阵*/
printf("\n");
}
for (i = 0; i < 3; i++)
for (j = 0; j < 3; j++)
{
if (j > i)
{ /*将主对角线右上方的数组元素与主对角线左下方的数组元素进行单方向交换*/
temp = n[i][j];
n[i][j] = n[j][i];
n[j][i] = temp;
}
}
printf("转置矩阵:\n");
for (i = 0; i < 3; i++)
{
for (j = 0; j < 3; j++)
printf("%d ", n[i][j]); /*输出原始矩阵的转置矩阵*/
printf("\n");
}
getchar();
return 0;
}
5魔方阵
问题分析
所谓“n-魔方阵”,指的是使用1〜n.^2共 n.^2个自然数排列成一个n×n的方阵,其中n为奇数;该方阵的每行、每列及对角线元素之和都相等,并为一个只与n有关的常数,该常数为n×(n2+1)/2。
例如5-魔方阵,其第一行、第一列及主对角线上各元素之和如下:
第一行元素之和:17+24+1+8+15=65
第一列元素之和:17+23+4+10+11=65
主对角线上元素之和:17+5+13+21+9=65
而 n×(n2+1)/2=5×(52+1)/2=65 可以验证,5-魔方阵中其余各行、各列及副对角线上的元素之和也都为65。
假定阵列的行列下标都从0开始,则魔方阵的生成方法为:在第0行中间置1,对从2开始的其余n2-1个数依次按下列规则存放:
(1) 假定当前数的下标为(i,j),则下一个数的放置位置为当前位置的右上方,即下标为(i-1,j+1)的位置。
(2) 如果当前数在第0行,即i-1小于0,则将下一个数放在最后一行的下一列上,即下标为(n-1,j+1)的位置。
(3) 如果当前数在最后一列上,即j+1大于n-1,则将下一个数放在上一行的第一列上,即下标为(i-1,0)的位置。
(4) 如果当前数是n的倍数,则将下一个数直接放在当前位置的正下方,即下标为(i+1,j)的位置。
算法设计
在设计算法时釆用了下面一些方法:
定义array()函数,array()函数的根据输入的n值,生成并显示一个魔方阵,当发现n不是奇数时,就加1使之成为奇数。
使用动态内存分配与释放函数malloc()与free(),在程序执行过程中动态分配与释放内存,这样做的好处是使代码具有通用性,同时提高内存的使用率。
在分配内存时还要注意,由于一个整型数要占用两个内存,因此,如果魔方阵中要存放的数有max个,则分配内存时要分配2max个单元,从而有malloc(max+max)。在malloc()函数中使用max+max而不是2max是考虑了程序运行的性能。
显然应该使用二维数组来表示魔方阵,但虽然数组是二维形式的,而由于内存是一维线性的,因此在存取数组元素时,要将双下标转换为单个索引编号。在程序中直接定义了指针变量来指向数组空间,即使用malloc()函数分配的内存。
#include<stdio.h>
#include<stdlib.h>
int array(int n)
{
int i, j, no, num, max;
int *mtrx;
if (n % 2 == 0) /*n是偶数,则加1使其变为奇数*/
{
n = n + 1;
}
max = n * n;
mtrx = (int *)malloc(max + max); /*为魔方阵分配内存*/
mtrx[n / 2] = 1; /* 将1存入数组*/
i = 0; /*自然数1所在行*/
j = n / 2; /*自然数1所在列*/
/*从2开始确定每个数的存放位置*/
for (num = 2; num <= max; num++)
{
i = i - 1;
j = j + 1;
if ((num - 1) % n == 0) /*当前数是n的倍数*/
{
i = i + 2;
j = j - 1;
}
if (i < 0) /*当前数在第0行*/
{
i = n - 1;
}
if (j > n - 1) /*当前数在最后一列,即n-1列*/
{
j = 0;
}
no = i * n + j; /*找到当前数在数组中的存放位置*/
mtrx[no] = num;
}
/*打印生成的魔方阵*/
printf("生成的%d-魔方阵为:", n);
no = 0;
for (i = 0; i < n; i++)
{
printf("\n");
for (j = 0; j < n; j++)
{
printf("%3d", mtrx[no]);
no++;
}
}
printf("\n");
free(mtrx);
return 0;
}
int main()
{
int n;
printf("请输入n值:\n");
scanf_s("%d", &n);
array(n); /*调用array函数*/
return 0;
}
2在解决该问题时,采用的是动态分配内存的方式,并使用了指针变量mtrx来指向二维数组中的元素。在算法设计中,要存储魔方阵需要一个二维数组,因此再给出直接使用二维数组来生成5-魔方阵的程序。
#include<stdio.h>
#define N 5
int main()
{
int a[N][N] = { 0 }, i, j, k, t, x, y;
i = 0; /*自然数1的行标*/
j = N / 2; /*自然数1的列标*/
t = N - 1; /*最后一行、最后一列的下标*/
for (k = 1; k <= N * N; k++)
{
a[i][j] = k;
x = i;
y = j;
if (i == 0)
i = t;
else
i = i - 1;
if (j != t)
j = j + 1;
else
j = 0;
if (a[i][j] != 0)
{
i = x + 1;
j = y;
}
}
printf("生成的5-魔方阵为:");
for (i = 0; i < N; i++)
{
printf("\n");
for (j = 0; j < N; j++)
{
printf("%3d", a[i][j]);
}
}
printf("\n");
getchar();
return 0;
}