1.1一维数组的声明与字符数组
1.1.1一维数组的声明与初始化
1.一维数组的声明
例1:如下定义是否正确?
int& a[10];
error C2109: 下标要求数组或指针类型
例2:定义数组a的引用。
int a[6] = { 0,2,4,6,8,10 };
int(*p)[6] = a;
2.一维数组的初始化
例1:给定如下代码:
数组x和y的值为?
int x[4] = { 0 };
int y[4] = { 1 };
x{0,0,0,0}
y{1,0,0,0}
1.1.2C风格字符串与字符数组
1.C风格字符串
例2:下列哪些是C风格字符串?
char ca1[] = { 'C','+','+' };
char ca2[] = { 'C','+','+' ,'\0' };//是
char ca3[] = "C++";//是
const char *cp = "C++";//是
char *cp1 = ca1;
char *cp2 = ca2;//是
2.字符数组
例1:下面的初始化是否正确?
const char ch3[6] = "Deniel";
error C2117: “ch3”: 数组界限溢出
例2:给出以下定义,则正确的叙述为数组x的长度大于数组y的长度。
char x[] = "abcdefg";
char y[] = { 'a','b','c','d','e','f','g' };
printf("%d\n", sizeof(x));
printf("%d\n", sizeof(y));
例3:下面程序段的运行结果是ab。
char c[5] = { 'a','b','\0','c','\0' };
printf("%s\n", c);
1.2二维数组
1.2.1二维数组的声明与初始化
例1:以下声明是否正确?
int disp(int a[][]);
error C2087: “a”: 缺少下标
例2:下列代码输出是1。
int a[3][2] = { (0,1),(2,3),(4,5) };
int *p = a[0];
printf("%d\n", p[0]);
1.2.2行优先存储与列优先存储
例1:有一矩阵大小为16Kx16K,若对两个这样的矩阵做加法运算,行优先读取与列优先读取的区别为行优先快。
例2:下列程序执行后的输出结构是6。
#include <stdio.h>
#include <windows.h>
int main()
{
int a[3][3], *p, i;
p = &a[0][0];
for (i = 0; i < 9; i++)
{
p[i] = i + 1;
}
printf("%d\n", a[1][2]);
system("pause");
return 0;
}
例3:下面的函数是一个用指针实现二维数组的读取函数,请完成该函数。
#include <stdio.h>
#include <windows.h>
#define M 3
#define N 4
int get(int *p, int i, int j)
{
if (NULL == p || i < 0 || i >= M || j < 0 || j >= N)
{
return (0);
}
return *(p + i*N + j);
}
int main()
{
int a[M][N] = { {1,2,3,4},{5,6,7,8},{9,10,11,12} };
printf("a[2][3] == %d\n", get(&a[0][0], 2, 3));
system("pause");
return 0;
}
例4:有一个二维数组a[1...100,1...65]有100行,65列,我们以行序为主序,如果该数组的基地址是10000,且每个元素占2个存储单元,请问a[56,22]的存储地址是?
10000+[(56-1)x65+(22-1)]x2
例5:下面程序执行的结果是:h。
#include <stdio.h>
#include <windows.h>
int main()
{
char matrix[3][3] = { {'a','b','c'},{ 'd','e','f' },{ 'g','h','i' } };
printf("%c\n", matrix[1][4]);
system("pause");
return 0;
}
1.3数组指针、指针数组与数组名的指针操作
1.3.1指针运算——算术运算、关系运算
例1:What is output if you compile and execute the following code?
Garbage value
指向常量的指针
#include <stdio.h>
#include <windows.h>
int main()
{
int i = 11;
int const *p = &i;
p++;
printf("%d\n", *p);
system("pause");
return 0;
}
1.3.2指针数组与数组指针
例1:设有“int w[3][4];”,pw是与数组名w等价的数组指针,则pw的初始化语句为int(*pw)[4] = w;。
1.3.3指针运算在数组中的应用
例1:下述代码是否正确?
char a[] = "hello";
a[0] = 'x';
char* q = a;
q[0] = 'b';
char* p = "hello";/*并不是把整个字符串装入指针变量,而是把存放该字符串的首地址装入指针变量*/
p[0] = 'x';
例2:针对int a[10];以下表达式不可以表示a[1]的地址是?
printf("0X%x\n", a + sizeof(int));
printf("0X%x\n", &a[0] + 1);
printf("0X%x\n", (int*)&a + 1);
printf("0X%x\n", (int*)((char*)&a + sizeof(int)));
0X699efcd8
0X699efccc
0X699efccc
0X699efccc
请按任意键继续. . .
例3:以下程序的运行结构是ga。
#include <stdio.h>
#include <windows.h>
int main()
{
char a[] = { "programming" }, b[] = { "language" };
char *p1, *p2;
int i;
p1 = a, p2 = b;
for (i = 0; i < 7; i++)
{
if (*(p1 + i) == *(p2 + i))
{
printf("%c", *(p1 + i));
}
}
system("pause");
return 0;
}
例4:下面程序执行的结果是编译错误。
error C2106: “+=”: 左操作数必须为左值
#include <stdio.h>
#include <windows.h>
int main()
{
char s[] = "abcde";
s += 2;
printf("%c\n", s[0]);
system("pause");
return 0;
}
例5:以下程序执行后的输出结果是4。
#include <stdio.h>
#include <windows.h>
void sum(int *a)
{
a[0] = a[1];
}
int main()
{
int aa[10] = { 1,2,3,4,5,6,7,8,9,10 }, i;
for (i = 2; i >= 0; i--)
{
sum(&aa[i]);
}
printf("%d\n", aa[0]);
system("pause");
return 0;
}
指针运算在高维数组中的应用
例1:下列关于数组的初始化正确的是?
#include <stdio.h>
#include <windows.h>
int main()
{
char str1[2] = { "a","b" };//error C2078: 初始值设定项太多
char str2[2][3] = { "a","b" };
char str3[2][3] = { {'a','b'},{ 'e','f' },{ 'g','h' } };//error C2078: 初始值设定项太多
char str4[] = { "a","b" };//error C2078: 初始值设定项太多
system("pause");
return 0;
}
例2:数组int a[3][4];则下列能表示a[1][2]元素值的是。
printf("%d\n", *(*(a + 1) + 2));
printf("%d\n", *(a + 1 + 2));
printf("%d\n", (&a[0] + 1)[2]);
printf("%d\n", *(a[0] + 1));
7
-1334248120
-1334248120
2
请按任意键继续. . .
例3:写出如下程序片段的输出结果5。
int a[] = { 1,2,3,4,5 };
int *ptr = (int *)(&a + 1);
printf("%d\n", *(ptr - 1));
例4:求下述代码的输出结果7_12。
int a[2][2][3] = { {{1,2,3},{4,5,6}},{ { 7,8,9 },{ 10,11,12} } };
int *ptr = (int *)(&a + 1);
printf("%d_%d\n", *(int *)(a + 1), *(ptr - 1));
例5:有以下程序,程序运行后的输出结果是Beijing。
#include <stdio.h>
#include <windows.h>
int main()
{
char str[][10] = { "China","Beijing" }, *p = str[0];
printf("%s\n", p + 10);
system("pause");
return 0;
}
1.4数组的应用
1.4.1线性表的顺序存储
例1:在n个结点的顺序表中,算法的时间复杂度是O(1)的操作是访问第i个结点(1<=i<=n)和求第i个结点的直接前驱(2<=i<=n)。
1.4.2对称矩阵的压缩
例1:将10阶对称矩阵压缩存储到一维数组A中,则数组A的长度最少为。
10阶对称矩阵共有10x10个元素,压缩到一维数组存储时,需要存储对角线以上或以下的元素共45个,加上对角线上的元素,共55个。
本章习题
1.下面选项中错误的是?
B.
int N=10;
int x[N];
C.
int x[0..10];
D.
int x[];
2.下述代码的输出结果是什么?
bcd
请按任意键继续. . .
#include <iostream>
int main()
{
char a[] = "abcd";
char *p = a;
int b = strlen(a);
*a = p[b];
++p;
std::cout << p << std::endl;
std::cout << a << std::endl;
system("pause");
return 0;
}
3.设数组定义为a[60][70],每个元素占2个存储单元,数组按照列优先存储,元素a[0][0]的地址为1024,那么元素a[32][58]的地址为?
1024+(58x60+32)x2=2048
4.设有一个二维数组A[m][n],假设A[0][0]存放位置在644(10),A[2][2]存放位置在676(10),每个元素占一个空间,问A[3][3]存放在什么位置?脚注表示用十进制表示。
A[2][2]的地址676=644+(2xn+2),求得n=15
A[3][3]的地址为644+(3xn+3)=692
5.请用文字说明p是何种类型变量。
int (*p)[n];
p是数组指针,指向一个长度为n的int型数组,p的类型为int (*)[n]。
6.若有以下说明和语句:
int c[4][5], (*p)[5];
p = c;
printf("%d\n", *(*(p + 2) + 3));
7.将以下程序补充完整。
char a[2][2][3] = { {{1,6,3},{5,4,15}},{ { 3,5,33 },{ 23,12,7 }} };;
for (int i = 0; i < 12; i++)
{
printf("%d\n", a[i / 6][i / 3 % 2][i % 3]);
}
8.有以下定义和语句:
int a[3][2] = { 1,2,3,4,5,6 }, *p[3];
p[0] = a[1];
printf("%d\n", *(p[0] + 1));//4
9.若定义int a[2][3]={},以下描述正确的有?
458357204
8
8
458357192
请按任意键继续. . .
printf("%d\n", *(a + 1));
printf("%d\n", *(a[1] + 1));
printf("%d\n", **(a + 1) + 2);
printf("%d\n", a[0]);
10.int A[2][3] = { 1,2,3,4,5,6 };,则A[1][0]和*(*(A + 1) + 1)的值分别是4 5?
11.以下程序打印的两个字符分别是c g。
#include <stdio.h>
#include <windows.h>
struct object
{
char data[3];
};
int main()
{
object obj_array[3] = { {'a','b','c'},{ 'd','e','f' },{ 'g','h','i' } };
object *cur = obj_array;
printf("%c %c\n", *(char *)((char *)(cur)+2), *(char *)(cur + 2));
printf("%c %c\n", *((char *)(cur)+2), *(char *)(cur + 2));
system("pause");
return 0;
}
12.下面程序执行结果为。
4 1101 13002 60
请按任意键继续. . .
#include <stdio.h>
#include <windows.h>
int main()
{
int a[4][4] = {
{1,2,3,4},
{ 50,60,70,80},
{ 900,1000,1100,1200 },
{ 13000,14000,15000,16000 } };
int(*p1)[4] = a;
int(*p2)[4] = &a[0];
int *p3 = &a[0][0];
printf("%d %d %d %d\n", *(*(a + 1) - 1), *(*(p1 + 3) - 2) + 1, *(*(p2 - 1) + 16) + 2, *(p3 + sizeof(p1) - 3));
system("pause");
return 0;
}
13.对于数组元素a[3][4],下列哪个不能表示a[1][1]?
6
6
590149912
5
请按任意键继续. . .
#include <stdio.h>
#include <windows.h>
int main()
{
int a[3][4] = {
{1,2,3,4},
{ 5,6,7,8},
{ 9,10,11,12} };
printf("%d\n", *(&a[0][0] + 5));
printf("%d\n", *(*(a + 1) + 1));
printf("%d\n", *(&a[1] + 1));
printf("%d\n", *(&a[0][0] + 4));
system("pause");
return 0;
}
14.将一个二维N*N矩阵顺时针旋转90°,例如a[2][2] = { 1,2,3,4 },旋转过后a[2][2] = { 4,1,3,2 }。
#include <stdio.h>
#include <windows.h>
#define N 4
void rotate(int matrix[][N])
{
for (int layer = 0; layer < N / 2; ++layer)
{
int first = layer;
int last = N - 1 - layer;
for (int i = first; i < last; ++i)
{
int offset = i - first;
int top = matrix[first][i];//save top
matrix[first][i] = matrix[last - offset][first];//left->top
matrix[last - offset][first] = matrix[last][last - offset];//bottom->left
matrix[last][last - offset] = matrix[i][last];//right->bottom
matrix[i][last] = top;//top->right
}
}
}
int main()
{
int a[N][N] = { {1,2,3,4},
{ 5,6,7,8 },
{ 9,10,11,12},
{ 13,14,15,16 } };
for (int i = 0; i < N; i++)
{
for (int j = 0; j < N; j++)
{
printf("%d ", a[i][j]);
}
printf("\n");
}
printf("\n");
rotate(a);
for (int i = 0; i < N; i++)
{
for (int j = 0; j < N; j++)
{
printf("%d ", a[i][j]);
}
printf("\n");
}
system("pause");
return 0;
}
15.数组乘积
输入:一个长度为n的整数数组input;
输出:一个长度为n的整数数组result,满足result[i]=input数组中除了input[i]之外所有数的乘积(假设不会溢出)。比如输入:input={2,3,4,5},输出result={60,40,30,24}。
程序要求:具有线性复杂度,且不能使用除法运算符。
int *cal(int *input, int n)
{
int i;
int *result = new int[n];
result[0] = 1;
for (i = 1; i < n; ++i)
{
result[i] = result[i - 1] * input[i - 1];
}
result[0] = input[n - 1];
for (i = n - 2; i > 0; --i)
{
result[i] *= result[0];
result[0] *= input[i];
}
return result;//注意result需要由此函数调用方调用“delete[]”来释放内存
}
16.在有n个整数的序列中找出最大值和最小值,最少需要的比较次数是?
3n/2
17.从n个数里面找最大的两个数理论最少需要比较?
n+logn-2
18.一个int数组,里面数据无任何限制,要求求出所有这样的数a[i],其左边的数都小于等于它,右边的数都大于等于它。
int arr[100], rightMin[100];
void smallLarge(int *arr, int *rightMin, int n)
{
int i, leftMax;
rightMin[n - 1] = arr[n - 1];
for (i = n - 2; i >= 0; --i)
{
if (arr[i] < arr[i + 1])
{
rightMin[i] = arr[i];
}
else
{
rightMin[i] = rightMin[i + 1];
}
}
leftMax = 0x80000000;
for (i = 0; i < n; ++i)
{
if (arr[i] >= leftMax)
{
leftMax = arr[i];
if (leftMax == rightMin[i])
{
printf("%d\n", leftMax);
}
}
}
}
19.数组中有一个数字出现的次数超过了数组长度的一半,请找出这个数字。
#include <stdio.h>
#include <windows.h>
int funtion(int data[], int length)
{
int currentAxis;
int currentNum = 0;
for (int i = 0; i < length; i++)
{
if (currentNum == 0)
{
currentAxis = data[i];
currentNum = 1;
}
else
{
if (currentAxis == data[i])
{
currentNum++;
}
else
{
currentNum--;
}
}
}
return currentAxis;
}
int main()
{
int data[] = { 0,1,2,1,1 };
int axis = funtion(data, 5);
printf("%d\n", axis);
system("pause");
return 0;
}