练习1:
方法一:
#include <stdio.h>
int main(){
char str[50]={0};
char *p_ch=str;
int temp = 0,sum = 0;
printf("请输入字符串:");
fgets(str,50,stdin);
while(*p_ch){
if(*p_ch >= '0' && *p_ch <= '9'){
temp = 10 * temp + *p_ch - '0';
}
else{
sum += temp;
temp = 0;
}
p_ch++;
}
printf("求和结果是%d\n",sum);
return 0;
}
方法二:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(){
char str[50]={0};
char *p_ch=str;
int temp = 0,sum = 0;
printf("请输入字符串:");
fgets(str,50,stdin);
while(1){
sum += atoi(p_ch);
strstr(p_ch,",");
if(!p_ch){
break;
}
else{
p_ch++;
}
}
printf("求和结果是%d\n",sum);
return 0;
}
练习2:
#include <stdio.h>
#include <string.h>
int main(){
char str[10]={0};
char num=0;
for(num = 1;num <= 3;num++){
printf("请输入用户名:");
fgets(str,10,stdin);
if(strlen(str) == 9 && str[8] !='\n'){
scanf("%*[^\n]");
scanf("%*c");
}
if(strcmp(str,"admin\n")){
continue;
}
printf("请输入密码:");
fgets(str,10,stdin);
if(strlen(str) == 9 && str[8] !='\n'){
scanf("%*[^\n]");
scanf("%*c");
}
if(strcmp(str,"123456\n")){
continue;
}
break;
}
if(num <= 3){
printf("登录成功\n");
}
else{
printf("登录失败\n");
}
return 0;
}
1.指针数组里每个存储区的类型都是指针。
2.字符指针 数组里包含多个字符类型的指针,每个指针可以代表一个字符串。
字符指针数组可以用来表示多个相关字符串。
例子:
运行结果:
例子:改成二维字符数组
运行结果:
二维字符数组也可以用来表示多个相关字符串。
通常采用字符指针数组记录多个相关字符串。
例子:主函数参数演示
运行结果:
主函数的第二个参数是一个字符指针数组,其中每个指针代表一个字符串。所有这些字符串的内容都来自于用户输入的命令。
主函数的第一个参数是一个整数,它表示第二个参数里的指针个数。
练习:
#include <stdio.h>
#include <stdlib.h>
int main(int argc,char *argv[]){
int legs = 0,heads = 0,num = 0;
if(argc < 3){
printf("命令错误\n");
return 0;
}
heads = atoi(argv[1]);
legs = atoi(argv[2]);
for(num = 0; num <= heads;num++){
if(4*num + 2*(heads-num) == legs){
printf("兔子有%d只,鸡有%d只\n",num,heads-num);
break;
}
}
return 0;
}
运行结果:
3.#define预处理指令可以用来定义宏
宏可以用来给数字起名字。
例子:宏演示
运行结果:
定义宏的时候要把宏名称写在前面,把它所代表的数字写在后面。
宏名称通常由全大写英文字母构成。
宏名称里不可以包含空格
用宏给数字起名字的时候不可以使用赋值操作符。
编译器会把程序里所有宏名称替换成它所代表的数字。
可以在编译命令里使用-D选项决定宏名称代表的数字。
例子:
编写程序的时候有些数字只能在编译的时候才能知道具体数值,程序中应该用宏名称代表这种数字。
例子:
运行结果:
宏还可以用来给计算公式起名字。
计算公式里包含未知数字,宏的参数用来表示计算公式的未知数。
例子:
运行结果:
编译器采用二次替换的方式处理参数的宏。
宏的参数不一定代表数字所以没有类型名称。
如果宏有多个参数也应该用逗号把相邻的参数名称分隔开。
宏不能使用自己的存储区和函数之间进行数据交换。
宏没有形式参数也没有用来存放返回值的存储区。
例子:
运行结果:
能当作数字使用的宏必须编写成表达式(因为宏没有用来存放返回值的存储区。)
例子:
运行结果:
宏的参数可以直接代表函数的存储区,对宏的参数内容的修改就是对函数存储区内容的修改。
练习:
#include <stdio.h>
#define SUB(x,y) x-y
int main(){
printf("SUB(10,5)是%d\n", SUB(10,5));
printf("20-SUB(10,5)是%d\n", 20-SUB(10,5));
return 0;
}
运行结果:20-SUB(10,5)是先计算20-10=10,然后再计算10-5=5;就是20-10-5=5;因为宏没有用来记录返回值的存储区,所以不能保证优先计算宏里面的操作符。
所有能当作数字使用的宏必须编写在一对小括号中间。
例子:
#include <stdio.h>
#define SUB(x,y) (x-y)
int main(){
printf("SUB(10,5)是%d\n", SUB(10,5));
printf("20-SUB(10,5)是%d\n", 20-SUB(10,5));
printf("SUB(20,10-5)是%d\n", SUB(20,10-5));
return 0;
}
运行结果:SUB(20,10-5)是5,是先计算20-10=10再计算10-5=5;因为宏没有形式参数所以不能保证优先计算参数里面的操作符。
编写宏的时候所有能当作数字使用的参数也必须写在小括号里面。
例子:
#include <stdio.h>
#define SUB(x,y) ((x)-(y))
int main(){
printf("SUB(10,5)是%d\n", SUB(10,5));
printf("20-SUB(10,5)是%d\n", 20-SUB(10,5));
printf("SUB(20,10-5)是%d\n", SUB(20,10-5));
return 0;
}
运行结果:
练习:
#include <stdio.h>
#define SQUARE(n) ((n)*(n))
int main(){
int num = 5;
printf("SUB(num)是%d\n", SQUARE(num));
return 0;
}
运行结果:
例子:
#include <stdio.h>
#define SQUARE(n) ((n)*(n))
int main(){
int num = 5;
printf("SUB(num)是%d\n", SQUARE(num));
printf("SUB(++num)是%d\n", SQUARE(++num));
return 0;
}
运行结果:SUB(++num)的值可能是42也可能是49,因为在一条语句里对一个数字多次进行自增自减运算结果是不确定的,所以最好不要使用自增自减的结果作为宏的参数。
不要把自增自减的结果作为宏的参数使用。
编写宏的时候可以使用一些特殊的符号,它们叫做宏操作符。
4. #是一个宏操作符,它可以把宏的一个参数转换成字符串字面值 ,就是在参数前后加 " 符号
例子:
预处理结果:使用gcc -E +文件名称(-E 只处理预处理指令。)
5.##也是一个宏操作符号,它可以把一个代表标识符的参数连接其它内容得到一个新的标识符。
例子:p_##n就表示一个指针变量名称p_n,加上##计算机才知道n是代表的指针变量的参数。
预处理结果:使用gcc -E +文件名称(-E 只处理预处理指令。)
练习:
#include <stdio.h>
#define CASE(n) ((ch) >= 'a' && (ch) <= 'z' ? (ch)-'a'+'A' : (ch) - 'A' +'a')
int main(){
char ch = 0;
printf("请输入一个英文字符:");
scanf("%c",&ch);
printf("转换结果是%c\n",CASE(ch));
return 0;
}
运行结果:
请输入一个英文字符:a
转换结果是A
进程已结束,退出代码为 0