《C程序设计》|学习记录1108

之前,在零基础C语言——数组-CSDN博客中,我们简单学习了一维数组的知识。

多维数组

多维数组的声明一般形式如下:

type name[size1][size2]……[sizeN];

二维数组

是多维数组中最简单的形式。在本质上,是一个一维数组的列表,声明一个x行y列的二维整型数组。

type arrayName[x][y];

一个二维数组可以被认为是一个带有x行y列的表格或矩阵。用矩阵形式表示一个二维数组,是逻辑上的概念,能形象化的表示出行列关系。在内存中,各元素是连续存放的,不是二维,是线性的。

引用数组元素

表示形式:

数组名[下标][下标]

如一维数组的一样,二维数组中,第一个下标表示行下标(行索引),第二个为列下标(列索引)。(行序号和列序号都是从0起算)

初始化

1.分行赋值——直观的表示

int arr[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}};

2.将所有数据写在一个括号内,按数组元素在内存中的排序顺序对各元素赋初值。

int arr[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};

3.对部分元素赋初值。

int arr[3][4]={{1},{5},{9}};

//运行结果是
//1    0    0    0
//5    0    0    0
//9    0    0    0

它的作用是只对各行第一列的元素赋值,其余元素自动为0。

也可以对各行中的某一个元素赋初值。

int arr[3][4]={{1},{0,6},{0,0,11}};


//运行结果是
//1    0    0    0
//0    6    0    0
//0    0    11   0

当然,可以对特定元素赋值,自此不演示。

也可以某一行元素不赋值。

int arr[3][4]={{1},{},{9}};

4.如果对全部元素都赋初值(即提供全部初始数据),则定义数组时对对第一维的长度可以不指定,但第二维的长度不能省。系统会根据数据总个数和第二维的长度算出第一位的长度。

字符数组

字符型数据是以字符的ASCII代码C储单元中的,一般占一个字节。由于ASCII代码属于整数形式,在C99中,把字符类型归纳为整型类型中的一种。

C语言中没有字符串类型,也没有字符串变量,字符串是存放在字符型数组中的。

定义字符数组

由于字符类型的存储方式,因此用整型数组来存放字符数据。

初始化

char c[10]={'I',' ','a','m'};

将字符用 ‘ ’ 引起,其余元素自动定为空字符 ‘ \0 ’。

引用与一维数组的一样

字符串和字符串的结束标志

在实际工作中,更关注的是字符串的有效长度,而非字符数组长度。

C语言规定了一个“字符串结束标志”。以字符’\0‘作为结束标志。遇到字符’\0'时,表示字符串结束。

C系统在用字符数组存储字符串常量时会自动增加一个'\0'作为结束符。例如“C program"共有9个字符,放到一维数组中占据10个字节。

’\0'代表ASCII代码为0的字符,ASCII码为0的字符不是一个可以显示的字符,而是一个”空操作符“,即什么也不做。

在执行printf函数时,每输出一个字符检查一次,遇到‘\0'时停止输出。

在此基础上,我们可以用一种新的方法,用字符串常量来使字符数组初始化。

char c[]={"I am happy"};
//也可省略括号
char c[]="I am happy";

说明:字符数组并不要求它的最后 一个字符为'\0',人为加上是为了便于观察。

字符串的输入与输出

(1)逐个字符输入输出,使用格式符”%c“。                                                                            (2)将整个字符串一次输入输出,用格式符"%s"(对应单词string字符串)。

如果一个字符数组中包含一个以上的'/0',则遇第一个'\0'时输出就结束。

使用scanf函数时:1)当输入一个字符串时,输入项是已定义的字符数组名char c[6];        2)当输入多个字符串,应在输入时以空格分隔。由于有空格字符分隔,分成几份就用几个字符串数组。例:scanf("%s%s%s",str1,str2,str3);如果只是设置了一个数组canf("%s",str);,只会将第一个分隔的内容存入,其余不会存入。

 使用字符串处理函数(STRing+……)

1.puts函数——输出一个以'\0‘结束的字符串到终端。(可用printf函数代替)

2.gets函数——从终端输入一个字符串到字符数组,并得到一个函数值(该字符数组的起始地址)。puts和gets只能输出或输入一个字符串。

3.stract函数——将后者字符数组连接到前者字符数组后面,并放在前者数组中,函数返回值为前者数组的地址。格式为:strcat(字符数组1,字符数组2);连接时将前一数组的'\0'删去,只在新数组后保留‘\0'。

4.strcpy和strncpy函数——将字符串2复制到字符数组1中。                                                               形式:strcpy(字符数组1,字符数组2);                                                                                                 strncpy( 字符数组1,字符数组2,n);——将字符串2前n个字符复制到字符数组1中去。

5.strcmp函数——比较字符串1和字符串2,形式:strcmp(字符串1,字符串2);

字符串比较的规则:将两个字符串自左向右逐个字符相比(按照ASCII码值比大小),直到出现不同的字符或遇到'\0'为止。如果参与比较的两个字符串都由英文字母组成,有一个简单的规律:在英文字典中位置在后的为“大”。小写字母比大写字母“大”。返回值:相同=0,1>2为正整数,1<2为负整数。

if(str1>str2)        //错误
//数组名表示地址,只能用
if(strcmp(str1,str2)>0)

6.strlen函数——测试字符串长度的函数。返回值为字符串的实际长度(不包含'\0'在内)。

7.strlwr函数——将字符串中大写字母换成小写字母。形式:strlwr(字符串);

8.strupr函数——将字符串中小写字母换成大写字母。形式:strupr(字符串);

这些函数的头文件为string,即:#include<string.h>

P165

1.用筛选法求100之内的素数。

注:筛选法:即“埃拉托色尼筛选法”:埃拉托斯特尼筛法_百度百科 (baidu.com)

#include<stdio.h>
#include<math.h>
int main()
{
	int i, j, n, a[101];
	for (i = 1; i <= 100; i++)
	{
		a[i] = i;			//把100个数写进数组,不使用a[0];
	}
	a[1] = 0;				//除去1
	for (i = 2; i < sqrt(100); i++)
	{
		for (j = i + 1; j <= 100; j++)
		{
			if (a[i] != 0 && a[j] != 0)
			{
				if (a[j] % a[i] == 0)
				{
					a[j] = 0;		//挖去非素数
				}
			}
		}
	}
	for (i = 2, n = 0; i <= 100; i++)
	{
		if (a[i] != 0)		//筛选素数
		{
			printf("%d\t", a[i]);	//输出
			n++;
		}
		if (n == 10)		//换行,制表
		{
			printf("\n");
			n = 0;
		}
	}
	printf("\n");
	return 0;
}

2.用选择法对10个整数排序。

int main()
{
	int i, j, mid, com, arr[10];
	for (i = 0; i <10; i++)
	{
		printf("请输入第%d个数:", i+1);
		scanf("%d", &arr[i]);
	}
	printf("\n");
	for (i = 0; i <9; i++)
	{
		com = i;                    //
		for (j = i + 1; j < 10; j++)
		{
			if (arr[com] > arr[j])    //判断
			{
				com = j;
			}
		}
		mid = arr[i];        /交换
		arr[i] = arr[com];
		arr[com] = mid;
	}
	printf("排序为:");
	for (i = 0; i < 10; i++)
	{
		printf("%d ",arr[i]);
	}
	return 0;
}

3.求一个3\times3的整型矩阵对角线元素之和。

int main()
{
    int a[3][3],sum=0;
    int i, j ;
    printf("输入3x3矩阵计算对角线和:\n");
    for (i = 0; i < 3; i++)
    {
        for (j = 0; j < 3; j++) 
        {
            scanf("%d", &a[i][j]);
        }
    }
    for (i = 0; i < 3; i++)
    {
        sum += a[i][i];
    }
    printf("sum=%d",sum);
    return 0;
}

结果为

4.有一个已经排的数组,要求输入一个数后,按原来排序的规律将它插入数列中。

假设此数列为升序排序,

int main()
{

	int a[11] = { 1,2,3,4,5,6,7,8,9,10 };
	int i, j, num;
	int	tamp1, tamp2;
	printf("原先的序列为:");
	for (i = 0; i < 10; i++)
	{
		printf("%d ",a[i]);
	}
	printf("\n");
	printf("请插入一个数:");
	scanf("%d", &num);
	if (num > a[9])
	{
		a[10] = num;
	}
	else
		for (i = 0; i < 10; i++)
		{
			if (a[i] > num)
			{
				tamp1 = a[i];
				a[i] = num;
				for (j = i + 1; j < 11; j++)
				{
					tamp2 = a[j];
					a[j] = tamp1;
					tamp1 = tamp2;
				}
				break;
			}
		}
	printf("新的排序为:");
	for (i = 0; i < 11; i++)
	{
		printf("%d ", a[i]);
	}
	return 0;
}

结果为:

扩展代码的功能性可添加:输入已排好的数据,并检测其排序方式(设置函数判断是否符合规律,返回值利用switch语句判断其规律),利用函数的调用使已插入数的新数列再执行一边(或从某一边进行插入)。

5.将一个数组中的值按逆顺序重新存放。例如:原来顺序是:8,6,5,4,1.要求改为1,4,5,6,8。

注:题目要求是“存放”,不要写成逆序打印了。

int main() 
{
	int t, i, n;
	printf("将重新排序的数的个数为:");
	scanf("%d", &n);
	int a[100];		//设置一个足够用的大小
	printf("请输入:");
	for (i = 0; i < n; i++)
	{
		scanf("%d", &a[i]);
	}
	for (i = 0; i < n / 2; i++)//交换
	{
		t = a[i];
		a[i] = a[n - i - 1];
		a[n - i - 1] = t;
	}
	for (i = 0; i < n; i++)
	{
		printf("%5d", a[i]);
	}
	return 0;
}

结果为:

6.输出以下的杨辉三角形(要去要输出10行)       

        1

        1        1

        1        2        1

        1        3        3        1

        …………

#include <stdio.h>
#include <stdlib.h>
int main() 
{
	int num[10][10];
	for (int i = 0; i < 10; i++) 
    {
		for (int j = 0; j <= i; j++) 
		{
			if (j == 0 || j == i) 
			{
				num[i][j] = 1;//每行数字左右对称,由1开始
			}
			else 
			{
				num[i][j] = num[i - 1][j] + num[i - 1][j - 1];//每个数等于它上方两数之和
			}
			printf("%4d", num[i][j]);
		}
		printf("\n");
	}
	return 0;
}

输出结果为:

7.输出“魔方阵”。所谓魔方阵是指这样的方阵,它的每一行,每一列和对角线之和均相等。例如,三阶魔方阵:        8        1        6

                             3        5        7

                             4        9        2

要求输出1\sim n^{2}的自然数构成的魔方阵。魔方矩阵_百度百科 (baidu.com)​c​​​​​

void Exchange(int** pj, int tr, int tc, int n) {
    n++;
    if (1 <= tr && tr <= n / 2 && 1 <= tc && tc <= n) {
        pj[tr][tc] += pj[n - tr][n - tc];
        pj[n - tr][n - tc] = pj[tr][tc] - pj[n - tr][n - tc];
        pj[tr][tc] -= pj[n - tr][n - tc];
    }
}

int main() {

    int n, i = 0, j = 0, ** pj;
    int tr, tc;

    printf("输入魔方矩阵的阶层:");
    scanf("%d", &n);
    // 初始化二维数组
    pj = (int**)malloc(sizeof(int**) * (n + 1));
    for (i = 0; i < (n + 1); i++)
        pj[i] = (int*)malloc(sizeof(int*) * (n + 1));

    // n为奇数时
    if (n % 2 == 1) {
        // 1.将1放至第一行中间
        i = 1; j = n / 2 + 1;
        pj[1][n / 2 + 1] = 1;
        // 2.沿右上45°,依次放置剩下的数
        for (int k = 2; k <= n * n; k++) {
            // 行数上移,列数右移,即右上45°移动
            tr = i - 1; tc = j + 1;

            // 条件一:若超出,则回绕
            if (tr < 1) tr = n;
            if (tc > n) tc = 1;
            // 条件二:若有数据,则放在上一个数字之下
            if (0 < pj[tr][tc] && pj[tr][tc] <= n * n) {
                tr = i + 1; tc = j;
                if (tr < 0) tr = n;
            }
            pj[tr][tc] = k;
            i = tr; j = tc;
        }
    }
    // n为4的倍数时
    else if (n % 4 == 0) {
        i = 1; j = 1;
        // 1.先将数据从上到下,从左到右填入
        for (int k = 1; k <= n * n; k++) {
            pj[i][j++] = k;
            if (j > n) { j = 1; i++; }
        }
        // 2.将方阵的所有4*4子方阵中的两对角线上的数
        // 关于大方阵中心作中心对称交换
        i = 1; j = 1;
        for (size_t r = 0; r < n / 4 + 1; r++) {
            for (size_t c = 0; c < n / 4 + !(r % 2); c++) {

                tr = 2 * r + i;
                tc = 4 * c + r % 2 * 2 + j;
                Exchange(pj, tr, tc, n);
                Exchange(pj, tr - 1, tc, n);
                Exchange(pj, tr, tc - 1, n);
                Exchange(pj, tr - 1, tc - 1, n);
            }
        }
    }
    for (i = 1; i <= n; i++) {
        for (j = 1; j <= n; j++)
            printf("\t%d", pj[i][j]);
        printf("\n");
    }
}

此代码无法生成6阶魔方阵。

8.找出一个二维数组中的鞍点,即该位置上的元素在该行上最大、在该列上最小,也可能没有鞍点。

注:我的想法为:每行最大的数所在的列中是否为最小。

#define N 5
#define M 4
int Saddle_point(int p, int q,int arr[M][N])
{
	int Max, Min;
	int i, j, m, n, k;
	int count = 0;
	for (i = 0; i < p; i++)
	{
		for (j = 0; j < q; j++)
		{
			printf("%d\t", arr[i][j]);//打印
			if (j == (q - 1))
			{
				printf("\n");
			}
		}
	}
	for (i = 0; i < p;)					//分行筛选
	{
		Max = 0, Min = 0;
		n = 0, m = 0;					//再次初始化
		for (j = 0; j < q; j++)
		{
			if (Max < arr[i][j])		//找出此行最大值
			{
				Max = arr[i][j];
				m = j;					//确定最大值所在的列
				n = i;
			}
			Min = arr[n][m];
			if (j == (q - 1))
			{
				for (k = 0; k < p; k++)
				{
					if (Min > arr[k][m])//找出m列的最小值
					{
						Min = arr[k][m];
						n = k;
					}
				}
			}
		}
		if (Max != Min)//判断是否为鞍点,并返回值
		{
			printf("在%d行无鞍点\n", i + 1);
			i++;
		}
		else
		{
			count++;
			printf("在%d列的鞍点为arr[%d][%d]=%d\n", i + 1, n, m, Max);
			i++;
		}
	}
	return count;
}
int main()
{
	int arr[M][N];
	int i, j;
	printf("请输入:\n");
	for (i = 0; i < M; i++)
	{
		for (j = 0; j < M; j++)
		{
			scanf("%d", &arr[i][j]);
		}
	}
	int count=0;
	int p = sizeof(arr) / sizeof(arr[0]);			//计算二维数组的列数
	int q = sizeof(arr[0]) / sizeof(arr[0][0]);		//计算二维数组的行数
	Saddle_point( p, q,arr);						//函数的调用
	printf("此数组有%d个鞍点\n", count);
	return 0;
}

9.有15个数按照由小到大顺序存放在一个数组中,输入一个数,要求用折半查找法找出该数是数组中第几个元素的值。如果该数不在数组中,则输出“无此数”。

#include <stdio.h>

int main()
{
	int a[15];
	int i,j,n,mid,flag = 0;
	printf("请输入15个数:\n");
	for(i = 0;i < 15;i++)
	{
		scanf("%d",&a[i]); 
	}
	printf("\n请输入一个数:");
	scanf("%d",&n);
	i = 0;
	j = 14;
	while(i < j)
	{
		mid = (i + j) / 2;
		if(a[mid] > n)
		{
			i = mid + 1;
		}
		if(a[mid] < n)
		{
			j = mid - 1;
		}
		if(a[mid] == n)
		{
			printf("该数是第%d个元素",mid+1);
			flag = 1;
			break; 
		}
	}
	
	if(flag == 0)
	printf("无此数!"); 
 } 

10.有一篇文章,共有3行文字,每行有80个字符。要求分别统计出其中英文大写字母、小写字母、数字、空格以及其他字符的个数。

#include<stdio.h>
int main()
{
	int i, j, q = 0, p = 0, z = 0, o = 0, n = 0;
    char a[3][80];
    for (i = 0; i < 3; i++)
    {
        printf("第%d行:", i + 1);
        gets_s(a[i]);                //字符串输入
    }
    for (i = 0; i < 3; i++) {
        for (j = 0; a[i][j] != '\0'; j++)
        {
            if (a[i][j] >= 'A' && a[i][j] <= 'Z') 
            {
                q++;
            }
            else if (a[i][j] >= 'a' && a[i][j] <= 'z')
            {
                p++;
            }
            else if (a[i][j] >= '0' && a[i][j] <= '9') 
            { 
                z++;
            }
            else if (a[i][j] == ' ') 
            {
                o++;
            }
            else
            { 
                n++;
            }
        }
    }
    printf("大写字母:%d\n小写字母:%d\n数字:%d\n空格:%d\n其它:%d\n", q, p, z, o, n);
    return 0;
}

11.输出以下图形:

                                        *        *        *        *        *

                                            *        *        *        *        *

                                                *        *        *        *        *

                                                     *        *        *        *        *

                                                          *        *        *        *        *

int main()
{
	char a[5] = { '*','*','*','*','*' };
	int i, j,k;
	char space = ' ';
	for (i = 0; i < 5; i++)
	{
		printf("\n");
		printf("	");
		for (j = 1; j <=i; j++)
		{
			printf("%c",space);
		}
		for (k = 0; k < 5; k++)
		{
			printf("%c   ", a[k]);//用空格调位
		}
		printf("\n");
	}
	return 0;
}

12.有一行电文,一案下面规律译成密码:

A\rightarrow Z\quad a\rightarrow z \\B\rightarrow Y \quad b\rightarrow y \\C\rightarrow X\quad c\to y \\...\quad\quad\quad\quad...

即第一个字母变成第26个字母,第i个字母变成第(26-i+1)个字母,非字母字符不变。要求编程将密码译回原文,并输出密码和原文。

int main()//主函数 
{
	int j, n;//定义整型变量 
	char ch[80], tran[80];//定义字符数组 
	printf("输入密码:\n");//提示语句 
	gets_s(ch);//键盘输入 
	printf("\n密码是:\n%s", ch);//密码 
	j = 0;//赋初值 
	while (ch[j] != '\0')//不是最后一个字符时 
	{
		if ((ch[j] >= 'A') && (ch[j] <= 'Z'))//ASCII中A对应的值是65,a对应的值是97 
		{
			tran[j] = 155 - ch[j];
		}
		else if ((ch[j] >= 'a') && (ch[j] <= 'z'))//小写 
		{
			tran[j] = 219 - ch[j];
		}
		else
		{
			tran[j] = ch[j];
		}
		j++;
	}
	n = j;
	printf("\n输出原文:\n");//提示语句 
	for (j = 0; j < n; j++)//遍历输出 
	{
		putchar(tran[j]);
	}
	printf("\n");//换行 
	return 0;//函数返回值为0 
}

13.编写一个程序,将两个字符串连接起来,不要使用strcat函数。

int main()
{
   char str1[120],str2[120];	//char数组大小最大为120
   int i=0,j=0;
   printf("请输入第一个字符串:");
   scanf("%s",str1);			//因要给整个数组输入字符,不需要带&地址符,带&特指某一位
   printf("\n请输入第二个字符串:");
   scanf("%s",str2);
   while(str1[i]!='\0')			//检验数组位是否为空
    {  
    i++;						//不为空时,i+1
    }
    while(str2[j]!='\0')			//检验数组位是否为空
	  {
	     str1[i]=str2[j];		//将第二个字符数组添加到第一个字符数组后面
	     i++;
	     j++;
	  }
  str1[i]='\0';
  printf("\n两个字符串连接后:%s \n",str1);
} 

14.编写一个程序,将两个字符串s1和s2比较,若s1>s2,输出一个正数;若s1=s2,输出0;若s1<s2,输出一个负数。不要用strcpy函数。两个字符串用gets函数读入。输出的正数或负数的绝对值应是相比较的两个字符串相应字符的ASCII码的差值。例如,“A”与“C”相比,由于“A”<"C",应输出负数,同时由于'A'与'C'的ASCII码差值为2,因此应输出-2.同理:”And"和"Aid"比较,根据第二个字符比较结果,’n'比'i'大5,因此应输出5。

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

int main()
{
	char s1[100], s2[100];
	printf("请输入s1:");
	gets_s(s1);
	printf("请输入s2: ");
	gets_s(s2);
	int len1 = strlen(s1);
	int len2 = strlen(s2);
	int sign = 0;
	int i, j, value;
	for (i = 0, j = 0; (i < len1) && (j < len2); i++, j++)
	{
		if (s1[i] > s2[j] || s1[i] < s2[j]) 
		{
			sign = 1;
			value = s1[i] - s2[j];
			break;
		}
	}
	if (len1 > len2 && sign == 0)
	{
		value = s1[i] - s2[j];
	}
	else if (len1 < len2 && sign == 0)
	{
		value = s1[i] - s2[j];
	}
	else if(len1 == len2 && sign == 0)
	{
		value = 0;
	}
	printf("结果为: %d\n", value);
	return 0;
}

15.编写一个程序,将字符数组s2中的全部字符复制到字符数组s1中。不用strcpy函数。复制时,"\0"也要复制过去。'\0'后面的字符不复制。

#include<stdio.h>
#include<string.h>
int main()
{
    char s1[100], s2[100];
    int i;
    i = 0;
    printf("请输入s1:");
    gets_s(s1);
    printf("请输入s2:");
    gets_s(s2);
    for (i = 0; i <= 100; i++)
    {
        s1[i] = s2[i];
        if (s2[i] == '\0')
            break;
    }
    printf("s1=%s\n",s1);
    printf("s2=%s",s2);
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

七十二旹

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值