可移植意味着什么?
可移植指的是源代码无需修改就能在不同的计算机系统中成功编译的程序
解释源代码文件、目标代码文件和可执行文件有什么区别?
源代码文件包括程序员使用的任何编程语言编写的代码
目标代码文件包含机器语言代码,不必是完整的程序代码
可执行文件包含组成可执行文件的完整机器语言代码
编程的七个主要步骤:
1、定义程序目标
2、设计程序
3、编写程序
4、编译程序
5、运行程序
6、测试和调试程序
7、维护和修改程序
编译器的任务是什么:
编译器把源代码翻译成等价的机器语言代码
链接器的任务是什么:
链接器把编译器翻译好的源文件及库代码和启动代码组合起来。生成一个可执行程序。
C语言的基本模块是什么?
他们都叫作函数
语法错误和语义错误的区别:
语法错误:违反了组成语句或程序的规则
语义错误:含义错误
什么情况下用long类型的变量代替int类型的变量?
1、在系统要表达的数超过了int可表示的范围
2、如果要处理更大的值,那么使用一种在所有系统上都保证至少是32位的类型,可提高程序的可移植性。
题目:实现一个计算器,功能加减乘除
我的程序:
#include <stdio.h>
void add();
void sub();
void mul();
void div();
float a;
float b;
double result;
char p;
void add()
{
result = a + b;
}
void sub()
{
result = a - b;
}
void mul()
{
result = a * b;
}
void div()
{
result = a / b;
}
int main()
{
printf("请输入一个数:\n");
scanf("%f",&a);
printf("请再输入一个数:\n");
scanf("%f",&b);
getchar();
printf("请输入加减乘除:\n");
scanf("%c",&p);
if('+'== p)
{
add();
}
if('-'== p)
{
sub();
}
if('*'== p)
{
mul();
}
if ('/'== p)
{
div();
}
printf("result is %lf\n",result);
return 0;
}
提示:scanf有垃圾,读取的是字符 ,需要加getchar();
优化:
#include <stdio.h>
int main(int argc, char *argv[])
{
double a;
double b;
double result = 0;
char operator; //'+' "+"
printf("Please input numA:\n");
scanf("%lf", &a);
printf("Please input numB:\n");
scanf("%lf", &b);
getchar();
printf("Please input operator:\n");
scanf("%c", &operator);
//printf("a = %lf b = %lf operator = %c\n", a, b, operator);
switch (operator)
{
case '+':
{
result = a + b;
break;
}
case '-':
{
result = a - b;
break;
}
case '*':
{
result = a * b;
break;
}
case '/':
{
if(b == 0)
{
printf("error: numB is zero!\n");
break;
}
result = a / b;
break;
}
default:
{
printf("error: operator\n");
}
}
printf("result = %lf\n", result);
return 0;
}
强制类型转换:
例:
double d_num = 1.2345;
int i_num = (int) d_num;
在赋值的时候将d_num转化为int类型
char->short->short->int->long->float->double:隐式类型转换(等级由低到高)
char ch = i_num2;//int char :相关类型转换
C语言类型转换:不安全,可以将任何类型之间转换,有可能造成数据丢失;
安全的类型转换:先检查两个类型是否可以转换;
强制类型转换:(类型名称)变量名
格式化输入输出:
printf(“格式控制串”,输出表);
unsigned int usi_num;
signed int si_num;
int array[3];
char ch;
char *ptr;
char src[100]; //char src[100] = {'h','e','l','l','o','\0'};
short s_num;
long l_num;
float f_num;
double d_num;
将这些值依次用printf输出:
printf(“usi_num = %u\n”,sui_num);
printf(“si_num = %d\n”, si_num);
(数组三个整数要一个一个打印)
for (int i = 0; i < sizeof(array) / sizeof(int); i++)
{
printf(“array[%d] = %d\n”, i, array[i]);
}
printf(“ch = %c\n”, ch);
putchar(ch);(输出字符)
printf(“ptr = %s\n”, ptr);(没有*号)
puts(ptr);(输出字符串)
while(*ptr != ‘\0’)
{
printf("%c",*ptr);
ptr++;
}
printf("\n");
(ptr表示首地址,*ptr表示首地址中所保存的值)
//数组名保存的是数组的首元素的地址
printf(“src = %s\n”, src);
for(int i = 0; src[i] != ‘\0’; i++)
{
printf("%c",src[i]);
}
printf("\n");
printf(“s_num = %d\n”, s_num);
printf(“l_num = %ld\n”, l_num);
printf(“d_num = %f\n”, f_num);
printf(“d_num = %lf\n”, d_num);
printf注意事项:
printf("hello world!");
while(1);
程序编译后没有输出:
printf:行缓冲:满一行或者遇到’\n’或者缓冲区被强行刷出时,数据才会被输出;
while(1);
意义:这是一个死循环,代码不再向下执行。
while(1){ 代码 }
意义:这里将会重复执行{}中的代码
printf("hello world!");
printf("hello world!");
printf("hello world!\n");
printf("hello world!");
printf("hello world!");
现象:只打印前三个显示为一行
printf("hello world!");
printf("hello world!");
printf("hello world!\n");
printf("hello world!");
int num;
printf("hello world!");
现象:缓冲区被强行刷出
printf使用技巧(聊天室项目):
例: printf("\033[47;45mhello world\033[5m");//红色
scanf:
unsigned int usi_num;
signed int si_num;
int array[3];
char ch;
char *ptr;
char src[100]; //char src[100] = {'h','e','l','l','o','\0'};
short s_num;
long l_num;
float f_num;
double d_num;
用scanf给变量赋值:
printf(“input usi_num “);
scanf(”%u”, &usi_num);
printf(“input si_num “);
scanf(”%d”, &si_num);
printf(“input array “);
for (int i = 0; i < 3; i++)
{
scanf("%d", &array[i]);
//scanf(”%d”, array + i);
//scanf("%d", array++); //数组名是指针常量,保存数组首元素的地址;
}
getchar();
printf(“input ch”);
scanf("%c", &ch);
printf(“input ptr “);
ptr = (char *)malloc(sizeof(char) * 100);(分配空间)
scanf(”%s”, ptr); *//char ptr: 野指针
printf(“input src “);
//scanf(”%s”, src); //char src[100];
char temp;
#if 0
for(int i = 0; i < sizeof(src) / sizeof(char); i++)
{
scanf("%c", temp);
if(temp == ‘#’)
{
src[i] = ‘\0’;
break;//跳出循环
}
src[i] = temp;
}
#endif
int i = 0;
while ((temp = getchar()) != ‘#’)
{
src[i] = temp;
i++;
}
src[i] = ‘\0’;
printf(“input s_num “);
scanf(”%hd”, &s_num); //指针类型不兼容:指针不长不一致
printf(“input l_num “);
scanf(”%ld”, &l_num);
printf(“input f_num”);
scanf("%f", &f_num);
printf(“input d_num”);
scanf("%lf", &d_num);
printf(“usi_num = %u\n”, usi_num);
printf(“si_num = %d\n”, si_num);
for (int i = 0; i < sizeof(array) / sizeof(int); i++)
{
printf(“array[%d] = %d\n”, i, array[i]);
}
//printf(“array = %d\n”,array[3]);
printf(“ch = %c\n”, ch);
putchar(ch);
printf(“ptr = %s\n”, ptr);
puts(ptr);
while (*ptr != ‘\0’)
{
printf("%c", *ptr);
ptr++;
}
printf("\n");
//数组名保存的是数组的首元素的地址
printf(“src = %s\n”, src);
for (int i = 0; src[i] != ‘\0’; i++)
{
printf("%c", src[i]);
}
printf("\n");
printf(“s_num = %d\n”, s_num);
printf(“l_num = %ld\n”, l_num);
printf(“d_num = %lf\n”, d_num);
scanf的注意事项:
一、按照格式进行输入(不要加\n)
二、传递变量的地址
三、scanf产生垃圾
int num;
char ch;
scanf("%d",&num);
scanf("%c",&ch);
printf("num = %d ch = %c\n",num,ch);
运行结果为:
获取字符把\n给了scanf
解决方法:
1、用getchar()清除
2、空格 ( 例: %c)
3、+%*c(例:%*c%c)
四、数据溢出
char src[10];
scanf("%s",src);
printf("src = %s\n",src);
如果输入的长度超过数组定义的长度就会产生越界,虽然可以正常输出,但是是危险的,一旦内存空间不够用,数据有可能出现问题。
作业:
1、设定输入长度
2、密码保护
#include <stdio.h>
#include <string.h>
int main()
{
char ch [100];
char p = '*';
char src [100];
printf("pelase input your passwd:\n");
scanf("%6s",ch);
gets(ch);
for(int i = 1w;i<=6;i++)
{
src[i]= p ;
}
printf("%6s",src);
return 0;
}
gets():读取一个字符串
puts():输出一个字符串
scanf:遇到空格就停止 捕获不了句子
捕获句子可用:gets(数组名);表示获取一个字符串(警告不用去)
原因:无缓冲,没有给缓冲间来容纳数据,可能会造成缓冲间溢出
运算符和表达式:
自增自减:
i++:先使用后自加// i = i + 1;
++i:先自加后使用
例:
int i = 2;
int num = (i++) + (i++) + (i++) +(i++);
结果为:
num = 14/8;
i = 6;
int i = 2;
int num = (++i) + (++i) + (++i) + (++i);
结果为:
num = 19;
i = 6;
解析:
//i = i + 1;
//i = i + 1;
//num = i + i;
//i = i + 1;
//num = num + i; //13
//i = i + 1; 6
//num = num + i; //19
num = (i++) + (++i) + (i++) + (++i)
结果为:
num = 16;
i = 6;
解析:
//i = i + 1; 3
//int num = 3 + 3; //i = i + 1 4
//num = 6 + 4; //i = i + 1 5;
//i = i + 1; 6
//num = 10 + i = 16;
i = i * ((i++) + (++i));
结果为:
i = 24/19;
void func(int a, int b)
{
printf("a = %d\n", a);
printf("b = %d\n", b);
}
int main()
{
func(i++,++i);
}
结果为:
a=3;
b=4;
注:
从右往左开始传参
++i被替换成变量名
i++被替换成变量的值
C语言结束的三个标志:
,;和()
void func(int a, int b, int c, int d, int e)
{
printf("a = %d\n", a);
printf("b = %d\n", b);
printf("c = %d\n", c);
printf("d = %d\n", d);
printf("e = %d\n", e);
}
int main(int argc, char *argv[])
{
func(++i,i++,++i,i++,++i);
}
结果为:
7,5,7,3,7
func(i++,i,++i,i++,++i);
结果为:
5,6,6,3,6
printf("%d,%d,%d,%d,%d\n",i++, ++i, i++, ++i, ++i);
结果为:
6,7,4,7,7
char *ptr = "abcdefghgk";
printf("%c,%c,%c,%c,%c\n",*(ptr), *(ptr++), *(++ptr), *(ptr++),*(++ptr));
结果为:
e,d,d,b,b
逻辑运算:
if((ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'Z'))
if(!(ch)) //ch = ‘\0’ ch = 0; if(!0)
{
printf(“hello world!\n”);
}
**逻辑与/或:半开与/或**
int i = 2;
int j = 3;
if (i == 4 && j++)
{
}
printf("j = %d\n", j);
条件运算符:
int max = i > j ? i : j;
成立返回第一个值,不成立返回第二个值
位运算:
&:按位与:两个为1则为1,有0则为0
|:按位或
^:按位异或:两个不同的为1,相同的为0
~:按位取反
>>:按位右移
<<:按位左移
编程:统计一个整数的二进制中有多少个1:
我的程序:
#include <stdio.h>
int main()
{
int count = 0;
int a;
int i = 1;
printf("please input a number:\n");
scanf("%d",&a);
for(i;i<=a;i++)
{
if(a&1 == 1)
{
a >> 1;
count++;
}
break;
}
printf("%d",&count);
return 0 ;
}
运行错误!!!
优化:
while和for的选择:
已知循环次数用for
未知循环次数用while
#include <stdio.h>
int main()
{
int num;
int count = 0;//做统计
printf("Please input num:\n");
scanf("%d",&num);
while (num != 0)
{
if((num & 1) == 1)
{
count++;
}
num = num >> 1;
}
printf("count = %d\n",count);
return 0;
}
输入一个整数,输出这个整数32位二进制数:
从左到右:
#include <stdio.h>
void int2bin(int num)
{
for(int i = 0; i <32;i++)
{
if((num & 1) == 1)
{
printf("1");
}
else
{
printf("0");
}
if((i + 1) % 4 == 0)
{
printf(" ");
}
num = num >> 1;
}
printf("\n");
}
int main()
{
int num;
int count = 0;
printf("Please input num:\n");
scanf("%d",&num);
int2bin(num);
return 0;
}
最低位放在右边:
(从最高位判断1和0然后左移)
例:
1000 0000 0000 0000
0000 0000 0000 0101
#include <stdio.h>
void int2bin(int num)
{
unsigned int mask = 0x80000000;
for(int i = 0; i <32;i++)
{
if((num & 0x80000000) == 0x80000000)//mask
{
printf("1");
}
else
{
printf("0");
}
if((i + 1) % 4 == 0)
{
printf(" ");
}
num = num << 1;
}
printf("\n");
}
int main()
{
int num;
int count = 0;
printf("Please input num:\n");
scanf("%d",&num);
int2bin(num);
return 0;
}
unsigned int mask = 0x80000000;
0x80000000称为掩码
例:
0001 1100 0001 1101 1111 0001 1101 1100
保留/清零/置位一个整数的32位二进制数的m-n位:
8-15:
//1111 1111 1111 1111 11111 1111 1111 1111
// >> 24
//0000 0000 0000 0000 0000 0000 1111 1111
// << 8
//0000 0000 0000 0000 1111 1111 0000 0000
mask = 0000 0000 0000 0000 1111 1111 0000 0000
0000 0000 0000 0000 1111 0001 0000 0000 保留 & mask
0001 1100 0001 1101 0000 0000 1101 1100 清零 & ~mask
0001 1100 0001 1101 1111 1111 1101 1100 置位 | mask
0001 1100 0001 1101 0000 1110 1101 1110 取反 ^ mask
获取mask的代码:
#include <stdio.h>
void int2bin(unsigned int num)
{
unsigned int mask = 0x80000000;
for(int i = 0; i <32;i++)
{
if((num & 0x80000000) == 0x80000000)//mask
{
printf("1");
}
else
{
printf("0");
}
if((i + 1) % 4 == 0)
{
printf(" ");
}
num = num << 1;
}
printf("\n");
}
int main()
{
int m;
int n;
int num;
unsigned int mask = ~0;
int count = 0;
printf("please input m,n\n");
scanf("%d,%d",&m,&n);
// printf("Please input num:\n");
// scanf("%d",&num);
//int2bin(num);
mask = ~0;
mask = mask >> (32 - (n - m) - 1);
mask = mask << m;
int2bin(mask);
return 0;
}
获取num的m-n位掩码
int num = 0xffffffff;
num = num & mask;
int2bin(num);
不引入第三变量,交换两个变量的值:
#include <stdio.h>
int main(int argc, char *argv[])
{
int a = 5;
int b = 6;
//int temp;
// temp = a;
// a = b;
// b = temp;
a = a ^ b;
b = a ^ b;
a = a ^ b;
a = a + b;
b = a - b;
a = a - b;
printf("a = %d b = %d\n",a, b);
return 0;
}
作业2:公式 ?? 获取对应掩码
输入一个十进制数,转化成十六进制数
位操作训练2、3、4、5