概念:

  一堆相同类型的数据的有序集合

格式:

  元素类型  数组名称[ 元素个数 ]

定义数组:

    // 定义了一个名称叫做scores的数组, 数组中可以存放3个int类型的数据
int scores[];
// 只要定义一个C语言的数组, 系统就自动会给数组中的每一块小得存储空间一个编号
// 这个编号从0开始, 一次递增
// 数组中系统自动绑定的编号, 我们称之为 索引
scores[] = ;
scores[] = ;
scores[] = ;

数组初始化:

  完全初始化:

    // 依次将{}中的每一个值赋值给数组中的每一个元素
// 并且从0开始赋值
int scores[] = {,,,,};

部分初始化:

     // 默认从0开始初始化, 依次赋值
// 注意: 如果"在部分初始化中"对应的内存没有被初始化, 那么默认是0
int scores1[] = {, };

注意点:

  1.如果没有对数组进行初始化(完全和部门), 那么不要随便使用数组中的数据, 可能是一段垃圾数据(随机值)

  2.定义数组的时候, 数组的元素个数不能使用变量  变量作为数组的元素个数, 不初始化的情况下是随机值, 如果初始化会直接报错

  3.如果定义的同时进行初始化, 那么元素的个数可以省略, 省略之后, 初始化赋值几个数据, 数组就能存储几个数据,如果定义数组时没有进行初始化, 那么不能省略元素个数

  4.可以通过[索引] = 的方式, 给指定索引的元素赋值  

    int socres7[] = {[] = , [] = }; 

  5.只能在定义的同时利用{}进行初始化, 如果是先定义那么就不能使用{}进行初始化

    int scores8[];
//scores8 = {1 , 4, 19};
// 如果先定义那么就不能再进行整体赋值, 只能单个赋值
scores8[] = ;

数组遍历:

    int scores[] = {, , , , , ,  , };
// 动态计算数组的元素个数
int length = sizeof(scores) / sizeof(scores[]);
//length 不要写 6 这样的魔鬼数字
for (int i = ; i < length; i++) {
printf("scores[%i] = %i\n", i,scores[i]);
}

数组内存分配:

  存储方式:

    1)计算机会给数组分配一块连续的存储空间

    2)数组名代表数组的首地址,从首地址位置,依次存入数组的第1个、第2个....、第n个元素

    3)每个元素占用相同的字节数(取决于数组类型)

    4)并且数组中元素之间的地址是连续。        

    // 变量在内存中的存储
// 由于变量的内存寻址是从大到小, 所以存储数据时会从高字节开始存储
int num = ; // 0000 0000 0000 0000 0000 0000 0000 1010
/*
00001010 0x7fff5fbff7cc
00000000 0x7fff5fbff7cd
00000000 0x7fff5fbff7ce
00000000 0x7fff5fbff7cf
*/
// 注意: 数组的存储和变量有点不一样, 数组存储元素, 是从所占用的低字节开始存储
// 数组的元素自然的从上往下排列存储,整个数组的地址为首元素的地址。
char charValues[] = {'l', 'u', 'c', 'k'};
/*
charValues[0] = 0x7fff5fbff7c8
charValues[1] = 0x7fff5fbff7c9
charValues[2] = 0x7fff5fbff7ca
charValues[3] = 0x7fff5fbff7cb
*/ //&charValues == charValue == &charValue[0]  

数组越界问题:    

#include <stdio.h>

int main(int argc, const char * argv[]) {
int nums[] = {, };
int values[] = {, , };
// 注意点: 在使用数组的时候, 一定不要访问不属于字节的存储空间, 这样会导致数据混乱
// 有时候如果访问了不属于自己的存储空间, 程序会报错
values[] = ;
printf("values[3] = %i\n", values[]);
printf("nums[0] = %i\n", nums[]);
nums[-] = ;
printf("values[2] = %i\n", values[]);
return ;
}
/*
输出结果:
values[3] = 44
nums[0] = 44
values[2] = 88
*/

下图分析  values[3]访问到了nums[0]的空间    nums[-1] 访问到了 values[2] 的空间

       

数组练习:

    

    // 从键盘录入当天出售BTC的价格并计算出售的BTC的总价和平均价(比如说一天出售了4个比特币)
// 1.1定义数组保存每个比特币的价格
int values[] = {-};
// 1.2动态计算数组的元素个数
int length = sizeof(values) / sizeof(values[]);
// 1.3定义变量保存总和
int sum = ;
for (int i = ; i < length; i++) {
printf("请输入第%i个比特币的价格\n", i + );
scanf("%i", &values[i]);
//2.0 计算总和
sum += values[i];
}
/*
// 2.计算总和
int sum = 0;
for (int i = 0; i < length; i++) {
sum += values[i];
}
*/
// 3.计算平局值
int average = sum / length;
// 4.输出结果
printf("sum = %i, average = %i\n", sum, average);

数组与函数:

  1 数组名作为函数的参数传递, 是传递的数组的地址

    因为数组名就是数组的地址 &number = &number[0] == number

  2 如果数组作为函数的形参, 元素的个数可以省略

  3 如果形参是数组, 那么在函数中修改形参的值, 会影响到实参的值  

    void change(int values[])
{
values[] = ;
} int main(int argc, const char * argv[]) {
int nums[] = {, };
change(nums);
printf("nums[1] = %i\n", nums[]);
return ;
}
输出结果:

注意点:

  如果传递的数组的名称, 其实传递的是地址 如果传递的是地址, 其实传递的是指针  指针在64位编译环境占8个字节

   如果数组作为形参, 那么在函数中就不能通过数组的名称计算出数组元素的个数  因为系统会自动将数组形参转换为指针, 指针占用8个字节  所以只能读取到8个字节的数据

  举例:

    要求定义一个函数, 实现遍历数组. (只要别人传递数组给函数, 就要求输出数组中所有元素的值)      

        #include <stdio.h>
void printArray(int values[]); int main(int argc, const char * argv[]) {
int nums[] = { , , };
printf("size = %i\n", sizeof(nums)); // size = 12
printArray(nums); // 数组名称就是数组的地址
return ;
} void printArray(int values[])
{
printf("size = %i\n", sizeof(values)); // size = 8
// 1.动态计算数组的元素个数
int length = sizeof(values) / sizeof(values[]);
// 2.遍历数组
for (int i = ; i < length; i++) {
printf("values[%i] = %i\n", i,values[i]); // 输出: values[0] = 0 values[1] = 3
}
}  

  改正后(能正确输出数组的所有元素):    

        #include <stdio.h>
void printArray(int values[], int length); int main(int argc, const char * argv[]) {
int nums[] = { , , };
printf("size = %lu\n", sizeof(nums)); // size = 12
int length = sizeof(nums) / sizeof(nums[]);
printArray(nums, length);
return ;
} void printArray(int values[], int length)
{
printf("size = %lu\n", sizeof(values)); // size = 8
// 遍历数组
for (int i = ; i < length; i++) {
printf("values[%i] = %i\n", i,values[i]); // values[0] = 0 values[1] = 3
}
}

数组练习:    

#include <stdio.h> 

int main(int argc, const char * argv[]) {
// 要求从键盘输入6个0~9的数字,排序后输出
// 1.定义数组保存用户输入的数据
int nums[] = {};
// 2.接收用户的数据
int value = -;
for (int i = ; i < ; i++) {
printf("请输入第%i个数据\n", i + );
scanf("%i", &value);
nums[value] = nums[value] + ;
} for (int i = ; i < ; i++) {
for (int j = ; j < nums[i]; j++) {
printf("%i\n", i); // 1, 1, 2, 3, 3, 6
}
}
return ;
}
/*
1. nums[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
2. 用户输入的数组当做数组索引
3. 输入一次 索引对应的值 + 1
输入 1, 1, 2, 3, 3, 6之后
数组对应值 : nums[10] = {0, 2, 1, 2, 0, 0, 1, 0, 0, 0};
下标: 0 1 2 3 4 5 6 7 8 9
4. 然后对数组排序输出
*/

数组排序:

  冒泡排序

    

    int nums[] = {, , , , , };
int length = sizeof(nums) / sizeof(nums[]);
for (int i = ; i < length - ; i++) {
for (int j = ; j < length - - i; j++) {
if (nums[j] > nums[j + ]) {
int temp = nums[j];
nums[j] = nums[j + ];
nums[j + ] = temp;
}
}
}

  选择排序:

    

        int nums[] = {, , , , , , , };
int length = sizeof(nums) / sizeof(nums[]);
for (int i = ; i < length - ; i++) {
for (int j = i+; j < length; j++) {
if (nums[i] > nums[j]) {
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
}
}

  选择--冒泡排序优化(提取函数)

    #include <stdio.h>
void selectSort(int nums[], int length);
void printArray(int nums[], int length);
//void swap(int v1, int v2);
void swap(int nums[], int i, int j);
void bubbleSort(int nums[], int length); int main(int argc, const char * argv[])
{
// 已知一个无序的数组, 里面有5个元素, 要求对数组进行排序
int nums[] = {, , , , , , , };
int length = sizeof(nums) / sizeof(nums[]);
printArray(nums, length);
bubbleSort(nums, length);
printf("----------------\n");
printArray(nums, length);
return ;
}
// 遍历数组
void printArray(int nums[], int length)
{
for (int i = ; i < length; i++) {
printf("nums[%i] = %i\n", i, nums[i]);
}
}
void bubbleSort(int nums[], int length)
{
for (int i = ; i < length - ; i++) {
for (int j = ; j < length - - i; j++) {
if (nums[j] > nums[j + ]) {
swap(nums, j, j+);
}
}
}
}
// 选择排序
void selectSort(int nums[], int length)
{
for (int i = ; i < length - ; i++) {
for (int j = i+; j < length; j++) {
if (nums[i] > nums[j]) {
/*
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
*/
// swap(nums[i], nums[j]);
swap(nums, i, j);
}
}
}
}
// 基本数据类型作为函数的参数, 是值传递, 在函数中修改形参不会影响实参的值
/*
void swap(int v1, int v2)
{
int temp = v1;
v1 = v2;
v2 = temp;
}
*/
// 交换两个数的值
void swap(int nums[], int i, int j)
{
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}

折半查找:

  思路:

    在有序表中,取中间元素作为比较对象,若给定值与中间元素的要查找的数相等,则查找成功;

    若给定值小于中间元素的要查找的数,则在中间元素的左半区继续查找;

    若给定值大于中间元素的要查找的数,则在中间元素的右半区继续查找。

    不断重复上述查找过 程,直到查找成功,或所查找的区域无数据元素,查找失败。

      

      

  #include <stdio.h>
  #include <time.h>
  int findKey(int nums[], int key, int length);
  int findKey2(int nums[], int length, int key);
  int findKey3(int nums[], int length, int key);   int main(int argc, const char * argv[]) {
   // 现在已知一个有序的数组, 和一个key. 要求从数组中找到key对应的索引的位置
   // 对该方法进行封装, 要求找到就返回对应的索引, 找不到就返回-1
   int nums[] = {, , , , , [] = };
   int key = ;
   int length = sizeof(nums) / sizeof(nums[]);    // 消耗了1640毫秒
   clock_t startTime = clock();
   int index = findKey(nums, key, length);
   clock_t endTime = clock();
   printf("消耗了%lu毫秒\n", endTime - startTime);
   printf("index = %i\n", index);
  
   // 消耗了3毫秒
   clock_t startTime = clock();
   int index = findKey2(nums, length, key);
  
   // 消耗了2毫秒
   int index = findKey2(nums, length, key);
   clock_t endTime = clock();
   printf("消耗了%lu毫秒\n", endTime - startTime);
   printf("index = %i\n", index);
   return ;
  }     int findKey3(int nums[], int length, int key)
  {
   int min, max, mid;
   min = ;
   max = length - ;
   // 只要还在我们的范围内就需要查找
   while (min <= max) {
   // 计算中间值
   mid = (min + max) / ;
   if (key > nums[mid]) {
   min = mid + ;
   }else if (key < nums[mid])
   {
   max = mid - ;
   }else
   {
   return mid;
   }
   }
   return -;
  }   int findKey2(int nums[], int length, int key)
  {
   int min, max, mid;
   min = ;
   max = length - ;
   mid = (min + max) / ;
   while (key != nums[mid]) {
   // 判断如果要找的值, 大于取出的值, 那么min要改变
   if (key > nums[mid]) {
   min = mid + ;
   // 判断如果要找的值, 小于取出的值, 那么max要改变
   }else if (key < nums[mid])
   {
   max = mid - ;
   }
   // 超出范围, 数组中没有需要查找的值
   if (min > max) {
   return -;
   }
   // 每次改变完min和max都需要重新计算mid
   mid = (min + max) / ;
   }
   return mid;
  }     //循环遍历查找
  int findKey(int nums[], int key, int length)
  {
   for (int i = ; i < length; i++) {
   if (nums[i] == key) {
   return i;
   }
   }
   return -;
  }  

进制转换查表法:

#include <stdio.h>
void total(int value, int base, int offset);
void ptintBinary(int num);
void printfOct(int num);
void printfHex(int num); int main(int argc, const char * argv[]) {
// ptintBinary(10);
// printfOct(10);
printfHex();
return ;
}
//转十六进制
void printfHex(int num)
{
total(num, , );
}
//转八进制
void printfOct(int num)
{
total(num, , );
}
//转二进制
void ptintBinary(int num)
{
total(num, , );
}
// 转换所有的进制
// value就是需要转换的数值
// base就是需要&上的数
// offset就是需要右移的位数
void total(int value, int base, int offset)
{
// 1.定义一个数组, 用于保存十六进制中所有的取值
char charValues[] = {'', '', '', '', '', '', '', '', '', '', 'a', 'b', 'c', 'd', 'e', 'f'};
// 2.定义一个数组, 用于保存查询后的结果
char results[] = {''};
// 3.定义一个变量, 用于记录当前需要存储到查询结果数组的索引
int pos = sizeof(results)/ sizeof(results[]);
while (value != ) {
// 1.取出1位的值
int res = value & base;// 1 7 15
// 2.利用取出来得值到表中查询对应的结果
char c = charValues[res];
// 3.存储查询的结果
results[--pos] = c;
// 4.移除二进制被取过的1位
value = value >> offset;// 1 3 4
}
// 4.打印结果
for (int i = pos; i < ; i++) {
printf("%c", results[i]);
}
printf("\n");
}

C语言基础--数组及相关的更多相关文章

  1. day05<Java语言基础--数组>

    Java语言基础(数组概述和定义格式说明) Java语言基础(数组的初始化动态初始化) Java语言基础(Java中的内存分配以及栈和堆的区别) Java语言基础(数组的内存图解1一个数组) Java ...

  2. Java语言基础(数组)

    Java语言基础(数组概述和定义格式说明) A:为什么要有数组(容器) 为了存储同种数据类型的多个值 B:数组概念 数组是存储同一种数据类型多个元素的集合.也可以看成是一个容器. 数组既可以存储基本数 ...

  3. iOS开发环境C语言基础 数组 函数

    1 求数组元素的最大值 1.1 问题 创建程序,实现查询数组中最大值的功能,需求为:创建一个长度为10的数组,数组内放置10个0~99之间(包含0,包含99)的随机数作为数组内容,要求查询出数组中的最 ...

  4. [C语言基础] 数组与指针之间的引用

    通过指针引用数组,通过数组引用指针,你搞明白了么?通过下面3种情形来了解一下数组和指针 Case 1. unsigned char arry[10]; unsigned char *ptr; unsi ...

  5. C语言基础--数组

    数组 概念:在内存中连续存储的具有相同数据类型的一组数据的集合. 注意: 数组中的数据类型必须都是一致的 数组在内存中必须是连续的存储空间 定义数组时候的注意事项: 定义数组的时候,[]里面的值不能是 ...

  6. C#语言基础——数组

    数组 一.一位数组 数组初始化,创建数组,数组长度为5 int[] array = new int[5]; array[0] = 1; array[1] = 2; array[2] = 3; arra ...

  7. C语言基础:数组 分类: iOS学习 c语言基础 2015-06-10 21:40 7人阅读 评论(0) 收藏

    数组:是由一组具有相同数据类型的数据组合而来. 数组定义:元素类型修饰符 数组名[数组个数]={元素1,元素2....};  int arr[ 2 ]={1,2};    //正确 int arr[ ...

  8. R语言基础-数组和列表

    数组(array) 一维数据是向量,二维数据是矩阵,数组是向量和矩阵的直接推广,是由三维或三维以上的数据构成的. 数组函数是array(),语法是:array(dadta, dim),当中data必须 ...

  9. C语言基础——链表的相关操作

    1 #include <stdio.h> #include <malloc.h> #include <string.h> #include <math.h&g ...

随机推荐

  1. 最近在学习bootstrap的时候用bootstrap的视频教程2.0的引用bootstrap3.0突然发现很多不同,总结了一下

    bootstrap 2.3版与3.0版重要类的改变对比 Bootstrap 2.x Bootstrap 3.0 .container-fluid .container .row-fluid .row ...

  2. 解决连接VPN后无法上网问题

    解决连接VPN后无法上网问题 VPN的英文全称是“Virtual Private Network”,翻译过来就是“虚拟专用网络”.顾名思义,虚拟专用网络可以把它理解成是虚拟出来的企业内部专线. 在公司 ...

  3. Hadoop 2.0命令手册

    1.       FS Shell 1.1     简介 调用文件系统(FS)Shell命令应使用 bin/hadoop fs <args>的形式. 所有的的FS shell命令使用URI ...

  4. Thread join

    1.主线程生成并起动了子线程,而子线程里要进行大量的耗时的运算,当主线程处理完其他的事务后,需要用到子线程的处理结果,这个时候就要用到join()方法了. 2.Java Thread中, join() ...

  5. flash性能优化方案整理(最全)

    性能优化的原则 1.避免过早优化:太早优化将使代码难以设计和维护,最好是针对程序的瓶颈进行优化. 2.改进性能有时需要权衡:不能一味注重改进性能,一个项目要考虑各方面的利弊,比如代码的健壮性,结构性, ...

  6. css回忆(一)

    1.css的引入方式: a) 在head部分加入<link  rel="stylesheet" type="text/css" href="my ...

  7. Vsftpd 配置

    步骤 本次是在CentOS 6的版本上操作的. 说明:以下命令均在root用户下执行.   (1)安装vsftpd 没啥好说的一条命令搞定. $yum install vsftpd 中间会提示确认,输 ...

  8. 特征创建:Reference Characteristic、Template

    声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...

  9. css取消input、select默认样式(手机端)

    IOS端: background-color:transparent; border-color:transparent; andorid端: 仅仅使用上面的代码还不够,可以发现select框在某些浏 ...

  10. 深入浅出设计模式——建造者模式(Builder Pattern)

    模式动机无论是在现实世界中还是在软件系统中,都存在一些复杂的对象,它们拥有多个组成部分,如汽车,它包括车轮.方向盘.发送机等各种部件.而对于大多数用户而言,无须知道这些部件的装配细节,也几乎不会使用单 ...