将数组每行的平均值打印出来:
#include <stdio.h>
int main(void)
{
int a[][5] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25};
int row = sizeof(a) / sizeof(a[0]);
//printf("%d\n ", row);
int col = sizeof(a[0]) / sizeof(a[0][0]);
//printf("%d\n ", col);
int i,j,sum = 0;
for(i = 0; i < row; ++i) //错误的两句 for(i = 0; i < row; ++row)
{
for(j = 0; j < col; ++j) //for(j = 0; j < col; ++col)
{
sum += a[i][j];
// printf("%d\n ", sum);
}
sum /= col;
printf("%d\n ", sum);
sum = 0;
// break;
}
return 0;
}
for 循环里面应该写为 ++i, ++j,
循环的三个要素:(1)循环变量的初始化
(2)循环执行的条件
(3)有使循环趋于结束的语句
昨天的问题在于缺少了第三点,使循环趋于结束的语句。
int i = 3; j = 3;
//上面的写法是错误的当[][]里面是变量时则不能初始化。
#define N 3
int a[N][N] = {1,2,3,4,5,6,7,8,9};
//此种写法是正确的,因为N是 define的一个常量。
//Linux 环境下,用gcc编译时可以加参数 -Wall(Warning all)来显示所有警告。
3.函数:
函数的形式: 类型标识符 函数名(形参)
{
声明部分;
语句部分;
}
//不能在函数的内部再定义函数。
//声明 :可以多次。 定义:从无到有,只有一次。
//当函数没有返回值时,默认为int类型,但比较好的方式是,写函数时一定要加类型标识符,
不管是有返回类型( int, char, double ,等)还是无返回类型( void )都要加,这样可以避免歧义。
//函数的传参有两种: (1)值传递: 只传实参的值,形参只是实参的复制品,不可以修改原来变量的值。
(2)指针传参 :其实是传地址,可以修改原来变量的值。
4.函数封装:
写一个比较三个数大小的函数:
#include <stdio.h>
int maxOfThreeNumber(int a, int b, int c) //形参可以与实参名一样也可以不一样。
{
int max;
max = a > b ? a : b;
max = max > c ? max :c;
return max;
}
int main(void)
{
int x = 10, y = 15, z = 20;
printf("%d\n",maxOfThreeNumber(x,y,z));
return 0;
}
写一个求两数和的函数:
#include <stdio.h>
int sumOfTwoNumber(int a, int b)
{
int ret;
ret = a + b;
return ret;
}
int main(void)
{
int x = 10, y = 15, z = 20;
sumOfTwoNumber(10, 15);
printf("%d\n", sumOfTwoNumber(x,y));
return 0;
}
打印星星:
int printStar(int n)
{
int i;
for (i = 0; i < n; ++i)
{
putchar('*');
}
return ;
puts("");
}
打印100以内可以被三整除的数:
int div3(int n)
{
return n % 3 == 0;
}
int main(void)
{
int i;
for(i = 0;i <= 100;++i)
{
if(div3(i))
{
printf("%d\n", i);
}
}
return 0;
}
写一个可以判断是否为闰年的函数,和可以判断每年月份有多少天的函数,然后输入年份,月份可以判断此月有多少天:
#include <stdio.h>
int isLeapYear(int year) //可以判断是否为闰年
{
return (year % 4 == 0 && year % 100 !=0 || year % 400 == 0);
}
int dayOfTheMonth(int year, int month) //可以判断某年的某月有多少天,此函数调用了上面判断是否为闰年的函数;
{
int day;
switch(month)
{
case 2:
if(isLeapYear( year))
{
day = 29;
}
else
{
day = 28;
}
break;
case 4:
case 6:
case 9:
case 11:
day = 30;
break;
default:
day = 31;
break;
}
return day;
}
int main(void)
{
int year, month;
scanf("%d%d", &year, &month);
printf("%d\n ", dayOfTheMonth(year, month));
return 0;
}
方法二:
#include <stdio.h>
int isLeapYear(int year)
{
return (year % 4 == 0 && year % 100 != 0 || year % 400 == 0);
}
int dayOfTheMonth(int year, int month)
{
int days[] = {31,0,31,30,31,30,31,31,30,31,30,31}; //存常量在这块效率高,而且下面的判断比较巧妙。
if(2 == month) //先判断是否为二月,这样可以省掉许多计算量
{
if(isLeapYear(year))
{
return 29;
}
else
{
return 28;
}
}
return days[month - 1];
}
int main(void)
{
int year, month;
scanf("%d%d", &year, &month);
printf("%d\n", dayOfTheMonth(year, month));
return 0;
}
//函数参数的传递是从右向左的。
#include<stdio.h>
int fn(int n)
{
printf("%d\n", n);
return n;
}
void swap(int a, int b)
{
int t;
t = a;
a = b;
b = t;
}
int main(void)
{
int i = 3, j = 5;
fn(i); //此处可以验证 fn();函数。 这句打印 3
fn(j); //这句打印 5
swap(fn(i),fn(j)); //此句先打印 5, 再打印3,可以验证函数传递参数是从右向左的。
return 0;
}
写一个比较两数大小的函数:
#include <stdio.h>
int compare(int a, int b)
{
if(a > b)
{
return 1;
}
else if (a == b)
{
return 0;
}
else
{
return -1;
}
}
int main(void) //此处主要验证下面同一变量再比较中,使用自增运算带来的问题
{
int i = 2;
int k;
k = compare(i, i++);
printf("%d\n", k); // k 的结果为 1
i = 2;
k = compare(i++, i); //k 的结果为 -1 (结果与预想不同)
printf("%d\n", k);
i = 2;
k = compare(i, ++i);
printf("%d\n", k); //k 的结果为 0
i = 2;
k = compare(++i, i);
printf("%d\n", k); //k 的结果为 0 (结果与预想不同)
}
重点:***分析上面出现的原因是自增运算符的先后没有一个明确的规定,因此每个编译器厂商都是按照自己的理解来定义先后的。
此处是在Linux 平台下运行的结果。换个编译器结果就会发生变化。因此,此代码的移植性就很低,所以写代码时不要这样
写否则可能带来不可预知的后果。
#include <stdio.h>
int main(void)
{
char s[1024 * 1024 * 8]; //此处这样写,程序运行时会 ,断片(专业说法程序崩溃),提示为: Segmentation fault (core dumped),
puts("");
return 0;
}
分析原因:程序的栈不够用了。栈是内存中开辟的一处空间,在Linux系统环境下,系统会给每个程序的栈划分 7M~8M字节的空间。
此处定义的局部变量就占据了 8M字节的大小 ,当执行 puts("");语句时,程序就会调用 puts();函数 ,这时候就要 ”保护现场“, 去调用函数
等到,调用完后就会返回,此处用于保护现场的指令地址也是要放到栈中的,可是这时候栈已经满了,放不下任何东西了所以会溢出。发生崩溃。
//在Windows下系统一般给一个程序分配 1MB 字节的栈空间
划区大致可以划为五大区:
(1)栈区 :主要用于存放局部变量, 函数内部的形参 ,以及函数调用的返回值。这些占用的内存,会被系统自动回收。
(2)堆区 :
(3)字符常量区 :存放字符串常量 ,如 “Hello”, 不存放’A’,它不是字符串常量。
(4)全局区 :
(5)代码区 :存放二进制指令。
写一个可以计算阶乘的函数,要求不能使用 for();循环, while 循环,等。。。
分析:此种情况一般都是让使用递归函数来实现。
此类函数要注意两点:(1)查找函数结束时的条件。
(2)函数的递归调用。
int factorial(int n)
{
if(1 == n) //此处为函数结束的条件
{
return 1;
}
else
{
return factorial(n - 1) * n; //此处为递归的调用
}
}
int main(void)
{
int m;
m = factorial(3);
printf("%d\n", m); //相当与 factorial(factorial(factorial(1)-1)-1) * 3
return 0; //结果为: 1 * 2 * 3
}
汉诺塔问题,按要求完成所需要的次数:
void move(char p1, char p2)
{
printf("%c->%c\n", p1, p2);
}
void hanoi(int n, char polo1, char polo2, char polo3)
{
if(1 == n)
{
move(polo1, polo3);
return ;
}
else
{
hanoi(n -1, polo1, polo3, polo2);
move(polo1, polo3);
hanoi(n - 1, polo2, polo1, polo3);
}
}
int main(void)
{
hanoi(64, 'A', 'B', 'C');
return 0;
}
计算出第n项的斐波拉契数字:
分析: 此处可以使用递归算法,
第一步找到退出的条件,当为第一项,第二项时,结果都为1;
第二步函数的递归调用,fib(n -1) + fib(n - 2)
#include <stdio.h>
int fib(int n)
{
if(1 == n || 2 == n)
{
return 1;
}
else
{
return fib(n - 1) + fib(n - 2);
}
}
int main(void)
{
printf("%d\n", fib(5));
return 0;
}
用函数写一个数组逆序的功能:
#include <stdio.h>
void reverse(int a[], int len)
{
int i;
for(i = 0; i < len / 2; ++i)
{
int t;
t = a[i];
a[i] = a[len - i - 1]; //此处记得要减一
a[len - i -1] = t;
}
}
void printArray(int a[], int len)
{
int i;
for(i = 0; i < len; ++i)
{
printf("%d, ", a[i]);
}
puts("\b ");
}
int main(void)
{
int a[] = {1,2,3,4,5,6,7,8,9,0};
reverse(a, sizeof(a) / sizeof(a[0]));
printArray(a, sizeof(a) / sizeof(a[0]));
return 0;
}
调用函数的方法写选择排序:
#include <stdio.h>
void printArray(int a[], int len)
{
int i;
for(i = 0;i < len;++i)
{
printf("%d ,", a[i]);
}
puts("\b ");
}
void choiceSort(int a[], int len)
{
int i, j;
for(i = 0;i < len - 1;++i)
{
for(j = i + 1;j < len;++j)
{
if(a[i] > a[j])
{
int t = a[i];
a[i] = a[j];
a[j] = t;
}
}
}
}
int main(void)
{
int a[] = {1,2,3,4,5,6,7,8,9,0};
choiceSort(a, sizeof(a) / sizeof(a[0]));
printArray(a, sizeof(a) / sizeof(a[0]));
return 0;
}
//函数调用数组时,第一个参数为数组名, 第二个参数为数组长度。