1.水仙花数
#include<stdio.h>
int main() {
int i;
for ( i = 100; i < 1000; i++)
{
int i1 = i % 10;
int i2 = i / 10 % 10;
int i3 = i / 100;
if ((i1*i1*i1 + i2*i2*i2 + i3*i3*i3) == i)
printf("%d\n",i);
}
return 0;
}
2.二维数组
#include<stdio.h>
int main()
int arrary[2][3];
printf("%d\n", sizeof(arrary)); //6个元素,6个int元素,每个int 4个字节,所以答案是24
return 0;
}
3.二维数组赋值
#include<stdio.h>
int main() {
int arrary[2][3];
printf("%d\n", sizeof(arrary));
arrary[0][0] = 0;//给第0行第0列的元素赋值
arrary[0][1] = 0;//给第0行第1列的元素赋值
return 0;
}
#include<stdio.h>
int main() {
int arrary[2][3] = { {1,2,3},{2,3,4} };//创建的同时赋值
return 0;
}
#include<stdio.h>
int main() {
int arrary[2][3]=0;//将数组中每一个元素都赋值为0
return 0;
}
4.输出二维数组的值
#include<stdio.h>
int main() {
int arrary[2][3] = { {1,2,3},{4,5,6} };
int i;
int j;
for ( i = 0; i < 3; i++)
{
for ( j = 0; j < 4; j++)
{
printf("array[%d][%d] = %d\n",i,j,arrary[i][j]);
}
}
return 0;
}
这里存在数组越界的情况,但是c 与 Java不同,不会崩溃,只是越界位置输出的值毫无章法可言
输出结果
array[0][0] = 1
array[0][1] = 2
array[0][2] = 3
array[0][3] = 4
array[1][0] = 4
array[1][1] = 5
array[1][2] = 6
array[1][3] = -858993460
array[2][0] = -858993460
array[2][1] = 4193644
array[2][2] = 15343566
array[2][3] = 1
5.冒泡排序
#include<stdio.h>
int main() {
int array[10]{34,32,67,18,23,90,56,82,39};
int i;
int j;
for ( i = 0; i < 9; i++) //控制数据个数
{
for ( j = 0; j < 9 - i-1; j++) //控制每次比较的次数,-1是为了防止最后一个数组越界
{
if (array[j] > array[j+1]) //前一个数字和后一个数字比较大小
{
int temp = array[j];
array[j] = array[j + 1];
array[j+1] = temp;
}
}
}
for ( i = 0; i < 9; i++)
{
printf("%d\n", array[i]);
}
return 0;
}
简单解释冒泡排序的含义:一组数字,从第一个开始一次跟后便的数字比较大小,大的放后边,小的放前边,
第一次比较第一个和第二个比较,如果第一个大于第二个,交换两者位置,否则不变,直到比较到最后一个数字,此时,最大的值已经排在了最后边
第二次比较,第一个和第二个比较,重复第一步的操作,此时结果第二大的数字排在了右数第二个位置
。。。
直到最后一次比较
6.int arr [2][3][4][5]..支持多维数组,但是不建议使用,理解难度大。
7.字符数组和字符串
#include<stdio.h>
int main() {
char array[1000] = {'a','b','c','d'};
printf("%s\n",array);
return 0;
}
结果:abcd
#include<stdio.h>
int main() {
char array[] = "abcd";
printf("%s\n",array);
printf("%d\n",sizeof(array));
return 0;
}
结果:
abcd
5 //字符串默认以0结尾,所以末尾还有个零,sizeof 为5
请按任意键继续. . .
#include<stdio.h>
int main() {
char array[100] = "abcd";
printf("%s\n",array);
printf("%d\n",sizeof(array));
return 0;
}
结果:
abcd
100 //字符数组为abcd 大小为100
请按任意键继续. . .
C语言中数组长度这样表示sizeof(arrary)
8.c语言编译器不会检查数组脚标是否越界
9.c语言中字符串是一个在内存中以0结尾的字符数组,必须以0结尾,否则不是字符串
比如下边这个不是字符串
#include<stdio.h>
int main() {
char s[5] = { 0 };
s[0] = 'a';
s[1] = 'b';
s[2] = 'c';
s[3] = 'd';
s[4] = 'e';
return 0;
}
下边这个是字符串,因为char数组最后一个值默认为0
#include<stdio.h>
int main() {
char s[5] = { 0 };
s[0] = 'a';
s[1] = 'b';
s[2] = 'c';
s[3] = 'd';
printf("%s\n",s);
return 0;
}
打印结果为abcd ,注意后边是有0的,c语言不同于Java的一个地方,如果打印Java中一个数组的话,得到的是地址值,而C语言直接就把字符串打印出来了
10.英文倒叙打印
#include<stdio.h>
int main()
{
char buf[100] = "hello world";
int len = 0;
while (buf[len++]) {};
len--;
int min = 0;
int max = len - 1;
while (min < max)
{
int temp = buf[min];
buf[min] = buf[max];
buf[max] = temp;
min++;
max--;
}
printf("%s\n",buf);
return 0;
}
11.中文倒叙打印
汉字倒叙打印不同于英文,跟存储方式有关,直接使用以上方式会出现乱码现象
一个汉子为两个字节,一个英文字母为一个字节,正确交换的方式是第一个字节和倒数第二个字节交换
第二个字节和最后一个字节交换,这样就达到了将第一个汉字和最后一个汉字交换,以此类推。
这是windows系统下,如果是linux系统下汉字使用的是utf8的编码,每个汉字占三个字节
#include<stdio.h>
int main()
{
char buf[100] = "你好世界";
int len = 0;
while (buf[len++]) {};
len--; //char默认以0字符结尾,这样做是去掉了0的长度
int min = 0;
int max = len - 1;
while (min < max)
{
char temp = buf[min];
buf[min] = buf[max-1];
buf[max-1] = temp;
temp = buf[min + 1];
buf[min + 1] = buf[max];
buf[max] = temp;
min += 2;
max -= 2;
}
printf("%s\n",buf);
return 0;
}
12.中英混合打印
a.求中英混合长度(一个汉字占一个)
#include<stdio.h>
int main()
{
char buf[100] = "你好世界abc";
int len = 0;
int i = 0;
while (buf[i])
{
if (buf[i] < 0) //如果是汉字的话,满足小于0的条件,英文大于0,如果0表示是汉字,所以向前跳一个位置
i++;
i++;
len++;
}
printf("%d\n",len);
return 0;
}
#include<stdio.h>
int main()
{
char s[100] = "hello world";
s[4] = 0;
printf("%s\n",s);
return 0;
}
输出结果hell char默认以0结尾,将数组中的第四个设置为0相当于在那个位置结尾了,后边就没了
14.去除字符串尾部的空格
#include<stdio.h>
int main()
{
char s[100] = "hello world ";
int len = 0;
while (s[len++]); //这里的分号必不可少,不然有问题,可以运行试试
len--;
for (int i = len - 1; i >= 0; i--) //从后往前找,当找到一个不是空格的字符时,将其后的一个位置设置为0,就相当于在此作为尾部
{
if (s[i] != ' ')
{
s[i + 1] = 0;
break;
}
}
printf("(%s)\n",s); //(%s)表示将打印的用括号括起来
return 0;
}
15.去除字符串头部的空格
a.
#include<stdio.h>
int main()
{
char s[100] = " hello";
int len = 0;
while (s[len++] == ' ');
len--; //得到空格的数量
printf("%d\n", len);
int i = len; //从第一个不是空格的位置开始,将这个位置的字符移动到第一个位置
while (s[i])
{
s[i-len]=s[i];
i++;
}
printf("(%s)\n",s);
return 0;
}
结果为(helloello) //由于将字符串整体前移后,还需要将后边遗留的字符去掉,所以如下程序
b.
#include<stdio.h>
int main()
{
char s[100] = " hello";
int len = 0;
while (s[len++] == ' ');
len--;
printf("%d\n", len);
int i = len;
while (s[i])
{
s[i-len]=s[i];
i++;
}
s[i - len] = 0; //将最后一位设置为尾部,置0去除多余字符
printf("(%s)\n",s);
return 0;
}
16.随机数产生函数 rand 和 srand,可以对比java中的random函数学习 需要引入stdlib.h
#include<stdio.h> //没有引用stdlib.h但是也没有出错,?
int main()
{
int i = 0;
for ( i = 0; i < 10; i++)
{
int value = rand();
printf("%d\n",value);
}
return 0;
}
产生了随机数,但是每次得到的随机数都是相同的,所以rand称为伪随机数生成器,要生成每次不同的怎么做呢?
使用srand函数,设置种子值
#include<stdio.h>
#include<stdlib.h> //经测试在vs中即使不引用这两个头文件,同样可以运行
#include<time.h>
int main()
{
time_t tm = time(NULL); //得到系统时间
srand(tm); //种子发生器,只要每次修改srand函数的参数,就可一达到每次产生不同随机数的效果
int i = 0;
for ( i = 0; i < 10; i++)
{
int value = rand();
printf("%d\n",value);
}
return 0;
}
17。字符串的输入操作
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main()
{
char s[100] = {0}; //将数组大小设置为2048,就可以防止键盘输入溢出了
scanf("%s",s); //输入一个字符串,以回车键作为输入完成的标识,但是回车键本身不会作为字符串的一部分
printf("%s\n",s); //scanf存在安全问题,加入用户在键盘输入的内
//容超过scanf参数中的数组长度,就会内存溢出,发生奔溃
//这也就是微软在使用scanf函数时需要加上顶部#define _CRT_SECURE_NO_WARNINGS的原因
return 0;
}
18.字符串的结束标识
scanf将回车空格都当作字符串结束的标志
继续使用以上的程序,运行输入
abc ddd
输出结果是:abc
请按任意键继续. . .
可见空格后的ddd没有了
19.gets函数(用这个可以实现输出带空格的字符串,但是gets也存在缓冲区溢出的问题)gets参数只能接受一个数组
#include<stdio.h>
int main()
{
char s[100] = {0};
//scanf("%s",s);
gets(s);
int i = 0;
for ( i = 0; i < 10; i++)
{
printf("%d\n",s[i]);
}
return 0;
}
运行输入hello world
输出
hello world
104
101
108
108
111
32
119
111
114
108
请按任意键继续. . .
可见,gets函数解决了scanf的问题,gets函数是以回车为尾部标识的
20.gets实现整数加法
#include<stdio.h>
#include<stdlib.h>
int main()
{
char a[100] = { 0 };
char b[100] = {0};
gets(a);
gets(b);
int i1 = atoi(a);
int i2 = atoi(b);
printf("%d\n",i1+i2);
return 0;
}
由于gets无法接收整数作为参数,只能接收数组,所以使用atoi函数将字符串转化为一个整数 后实现加法
gets不能用类似“%d”或者“%s”之类的字符串转义
21.fgets函数
#include<stdio.h>
int main()
{
char a[10] = { 0 };
fgets(a,10,stdin);
//fgets(a, sizeof(a), stdin); //第一个参数是char的数组,第二个参数是数组的大小,单位:字节,第三个参数stdin
printf("%s\n",a); //代表标准输入,fget是安全的,不存在缓冲区溢出的问题,只要能保证第二个参数小 //于(不能等于(也不是绝对的,最好小于),char以0结尾)数组实际的大小
return 0;
}
22.puts函数
#include<stdio.h>
int main()
{
char a[10] = { 0 };
fgets(a,10,stdin);
puts(a); //只能打印字符串,并且会在输出完成后再后边打印一个'\n'(换行)
return 0;
}
输出结果
hello //输入后回车,可以看到换了两行
hello
请按任意键继续. . .
23.字符串操作函数(需要包含头文件 #include<string.h>)
a.获取有效长度
#include<stdio.h>
#include<string.h>
int main()
{
char a[100] = "hello world";
int len = strlen(a); //得到字符串长度,返回一个字符串中有效字符的数量(不包含字符串结尾的0),sizeof是获取到数组的大小,概念是不同的
printf("%d\n", len);
return 0;
}
b.字符串的追加
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
int main()
{
char a[100] = "hello world";
char a2[100] = "abcd";
strcat(a, a2); //将两个字符串合并,结果放在第一个参数里边,存在缓冲区溢出的问题(当第一个数组不够大 //到足以装的下两个数组中的东西的时候,所以需要第一个数组容量足够大)
printf("%s\n", a);
return 0;
}
安全追加
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
int main()
{
char a[100] = "hello world";
char a2[100] = "abcd";
strncat(a, a2,3); //合并的时候可以限制追加多少个字符,可以防止溢出
printf("%s\n", a);
return 0;
}
c.字符串的比较
#include<stdio.h>
#include<string.h>
int main()
{
char a[100] = "abcd";
char a2[100] = "abcd";
//if (a == a2); 错误的模型,字符串不能通过==比较
if (strcmp(a, a2) == 0) //这个函数比较的是ASCII码,如果第一个参数的码值小于第二个
//返回值为-1,反之则返回值为1
{
printf("相同\n");
}
else
{
printf("不相同\n");
}
return 0;
}
只比较指定数量的字符
#include<stdio.h>
#include<string.h>
int main()
{
char a[100] = "abcd";
char a2[100] = "abcdef";
//if (a == a2); 错误的模型,字符串不能通过==比较
if (strncmp(a, a2,5) == 0) //只比较前5个字符
{
printf("相同\n");
}
else
{
printf("不相同\n");
}
return 0;
}
d.字符串的拷贝
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
int main()
{
char a[100] = "abcd";
char a2[100] = "abcdef";
strcpy(a, a2); //将a2的内容拷贝到a中,注意缓冲区溢出的问题
printf("%s\n", a);
return 0;
}
拷贝指定数量的字符
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
int main()
{
char a[100] = "kkjedftk";
char a2[100] = "abcdef";
strncpy(a, a2,3); //将a2的内容拷贝到a中,注意缓冲区溢出的问题
printf("%s\n", a);
return 0;
}
结果:
abcedftk
请按任意键继续. . .
e.sprintf函数,格式化字符串
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
int main()
{
char a[100] = {0};
int i = 200;
sprintf(a,"i = %d",i); //将格式化后的字符串输出到第一个参数中去
printf("%s\n", a);
return 0;
}
f.字符串和整数的转换
整数转字符串 atoi函数
字符串转整数 (itoa函数不是标准的C语言库函数),可以使用sprintf就可以转换了
g.sscanf函数
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
int main()
{
char a[100] = "56+98=";
int c = 0;
int b = 0;
sscanf(a, "%d+%d", &c, &b); //从一个字符串中接收内容,对比scanf函数学习
printf("%d\n", c+b);
return 0;
}
h.strchr 查找字符
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
int main()
{
char a[100] = "56+98=";
int c = 0;
int b = 0;
strcpy(a, "hello world"); //当一个字符数组已经初始化后,重新给他复制不能直接使用=
//,而应该使用这种方式
const char *buf = strchr(a, 'o'); //在都吐个参数a中查找指定字符,找到后返回从这个字符开始的知道结尾的字符
//找不到返回null
printf("%s\n",buf);
return 0;
}
输出结果
o world
请按任意键继续. . .
i.strstr函数,原理同上,只不过查找的内容换成了字符串
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
int main()
{
char a[100] = "56+98=";
int c = 0;
int b = 0;
strcpy(a, "hello world");
const char *buf = strchr(a, 'o');
buf = strstr(a, "wor");
printf("%s\n",buf);
return 0;
}
j.strtok字符串分割函数
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
int main()
{
char a[100] = "abc_12345_efg";
const char *buf = strtok(a, "_");
printf("%s\n", buf);
buf = strtok(NULL, "_"); //没调用一次回得到第一个符合要求的字符串,从第二个开始参数要穿NULL
printf("%s\n", buf);
buf = strtok(NULL, "_");
printf("%s\n", buf);
return 0;
}
以循环的方式分割得到所有
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
int main()
{
char a[100] = "abc_12345_efg";
const char *buf = strtok(a, "_");
while (buf) 1 //如果找不到buf,会返回null,如果以此为循环结束条件
{
printf("%s\n", buf);
buf = strtok(NULL, "_");
}
return 0;
}
k.字符串转换为其他类型(stdlib.h)
a. atoi -> int
b. atof -> float
c.atol -> long
24.C语言自定义函数标准使用方式
第一种方式
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
int getMax(int a, int b) //自定义函数在main函数的上方定义,也就是在使用之前就定义
{ //在vs中,将自定义函数放在main函数的后边也是可以,但是会有警告
// warning C4013: “getMax”未定义;假设外部返回 int
int c = a > b ? a : b;
return c;
}
int main()
{
int a = 10;
int b = 20;
int d = getMax(a, b);
printf("%d\n", d);
return 0;
}
第二种方式
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
int getMax(int a,int b); //先声明自定义函数,然后在后边定义函数结构,不会有警告,
int main()
{
int a = 10;
int b = 20;
int d = getMax(a, b);
printf("%d\n", d);
return 0;
}
int getMax(int a, int b)
{
int c = a > b ? a : b;
return c;
}
如果C语言一个函数没有明确的返回类型,那么默认是int
在C语言中实参与形参的数据传递是“值传递”,即单向传递,只有实参传递给形参,不能有形参传递给实参,如果参数是数组,那么是可以通过形参传递给实参的,和java中的基本数据类型传递和引用数据类型传递相同
24.size_t的类型(表示unsigned int 是一种无符号整数,不是c语言的关键字,很多函数,如果确认不会返回负数,都可以用size_t类型接收)
#include<stdio.h>
#include<string.h>
_ main()
{
char s[100] = "hello world";
size_t len = strlen(s);
printf("%d\n", len);
return;
}
25.将一个正数或者一个负数在不借助于C语言库函数的条件下转换为字符串
#include<stdio.h>
#include<string.h>
void int2String(int n,char s[])
{
int status = 0; //0 = 正数,1 = 负数
if (n<0)
{
status = 1;
n = 0 - n; //如果是负数,先把他转化为正数
}
else
{
status = 0;
}
int i = 0;
while (n)
{
int a = n % 10;
char c = a + '0';
s[i] = c;
i++;
n /= 10;
}
int min = 0;
int max = i - 1;
while (min < max)
{
char temp = s[min];
s[min] = s[max];
s[max] = temp;
min++;
max--;
}
if (status == 1)
{
for (int a = i-1; a >=0; a--)
{
s[a + 1] = s[a];
}
s[0] = '-';
}
printf("%s\n", s);
}
int main()
{
char sa[100] = { 0 };
int2String(1234567890, sa);
}
26.#include 与#define的意义
#include就是简单的文件内容替换,使用这个引入头文件,在预编译阶段会将头文件中的内容替换到这个文件中
#define就是简单的文本替换,假设你定义了一个常量代表一个数字,那么在预编译的阶段,会直接将这个常量表示的值替换到文件中
27.#ifndef与#ebdif
#ifndef的意思就是条件预编译如果#ifndef后面的条件成立,那么就预编译从ifndef开始到#endif之间的代码,否则不会去预编译这段代码 ,在一个头文件中都是这样的格式:是为了防止头文件被重复引用,如果不加这三行,那么如果重复引用了就会在预编译的时候引入好几次,造成不必要
#ifndef RZM (宏的名字,由自己定义,保持唯一性,不与别的宏重复)
#define RZM (这两句就是如果没有定义这个宏,那么就在本行定义一下)
。。。
#endif
28.多文件编译
第一种方式:创建一个a.c,里面定义一个方法
#include<stdio.h>
int print(int num) {
printf("%d\n", num);
}
在主函数中调用这个方法
#include<stdio.h>
int print(int num); //将函数进行声明然后使用
int main()
{
print(10);
}
第二种方式:通过头文件的方式调用函数(推荐这种方式)
同样创建一个a.c,里面定义一个方法
#include<stdio.h>
int print(int num) {
printf("%d\n", num);
}
创建一个b.h头文件
#ifndef __RZM__
#define __RZM__
int print(int num); //在头文件中进行函数的声明
#endif
在主函数中调用这个方法,只需要引入这个头文集即可
#include<stdio.h>
#include "b.h" //引入这个头文集
int main()
{
print(10);
}