0%

c

C语言是一门通用计算机编程语言,应用广泛。C语言的设计目标是提供一种能以简易的方式编译、处理低级存储器、产生少量的机器码以及不需要任何运行环境支持便能运行的编程语言。

基础知识

知识遗漏

字符数组的 定义 声明 初始化 赋值

** 注意 **
在下列代码中标识正确的代码定义 赋值 初始化正确 并不代表在所有的编译器中都正确,有的编译器 vs2015 就会对char a[3]="abc";报错——因为没办法自动赋值’\0’,而上述语句在gcc中就不报错,在二级C语言考试中的选择题中应该按照不能正确赋值处理。

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
26
27
28
29
30
# √
char name[10] = {"abcdefjhi"}; //只允许存放9个字符,剩下的一个存 '\0' ,编译器自动写入 '\0';当写入10个及以上的字符时,编译器可能不报错,但是由于字符串没有结尾标志,输出的时候容易出错;

# √
char name[10];
name[10] = {"abcdefjhi"}; //与上相同

# √
char name[10];
name[10] = "abcdefjhi"; //与上相同

# √
char name[10] = {'a','b','c','d','e','f','g','h','i'}; //与上相同,同样会自动添加'\0';(这里添加'\0'的情况与上不同,机制不一样,请看下一个例子体会为什么不一样,这是在 赋值9个字符的情况下才会添加'\0',若是赋值10个字符就不行了。

# √
char nmae[] = {'a','b','c','d','e','f','g','h','i'`}; //可以正常赋值,但是却不能自动添加'\0'

# ×
char name[10];
name = {"abcdefjhi"}; //字符串名(包括不带最后一个方括号的字符串名)是一个指针常量;常量不能重新赋值 ;不过也有作为形参变量使用的情况

# x
char name[10]; //与上错相同
name = {'a','b'};

# ×
char name[10]; //与上错相同
name = "abcdefjhi";

#

指针的 定义 声明 初始化

1
2
3
4
5
6
7
8
9
# √
char *str;
str = "ni hao a";

# √
char *str = "ni hao a";

# ×
char *str = {"ni hao a"}; //这个不是数组,只有数组和结构体 共用体 才使用 {} 赋值

指针 和 字符串数组的混合点

1
2
3
# ×
char str[10] = "prog.c", str2[10];
str2 = str1; //数组名是指针常量 不能赋值

** 总结 **
按照vs2015的实验结果陈述为:使用char str[20] ="abcde" 这种方式赋值方式就会自动添加\0,而且当赋值个数等于或大于字符串定义的长度时就会报错;使用char str[2]={'a','b'}这种方式赋值时不会自动添加\0,而且当赋值的个数等于字符串定义的长度时不会报错,仅当赋值的个数大于字符串定义的长度时才会报错。

字符串数组 和 指针赋值的字符串 在没有’\0’时的区别

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>
#include <stdlib.h>

int main()
{
char *ch, a[] = {'a','b','c'};
printf("%c\n", a[0]); // a
printf("%s\n", a); // abc烫烫
ch = "abc";
printf("%c\n",ch[0]); // a
printf("%s\n",ch); // abc
ch = a;
printf("%c\n",ch[0]); // a
printf("%s\n",ch); // abc烫烫
system("pause");
return 0;
}

** 总结 **
字符串指针直接指向并同时赋值的字符串在没有\0的情况下使用"%s"可以正常输出,无乱码;
字符串指针指向的没有'\0'的字符串数组在使用"%s"输出时会乱码;
字符串数组在没有'\0'的情况下,使用"%s"输出会有乱码;
使用printf("%s",a);输出的时候要求a是一个char类型的参数。

puts()和putchar()

1
2
3
4
5
6
7
8
# 
puts("a"); //正确
puts("abcd"); //正确
putchar('a'); //正确
putchar("a"); //不正确
putchar("abcd"); //不正确
putchar(n%10+'0'); //正确 相当于表达式 char a; a=n%10+'0'; putchar(a); 其中 '0'的ASCII值 48; n%10 计算的结果是什么 其ASCII就是多少,因为它是整形数据,不是字符型的。
putchar(65); //正确,输出A
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#
#include <stdio.h>
void fun(int n)
{
int i;
if((i=n/10)!=0)
fun(i);
putchar(n%10+'0'); //putchar()只能输出字符而不能输出字符串,详细解释看上方 puts() 和 putchar() 的辨析
}

main()
{
fun(256);
}

关于 &&,&,|,||的使用

1
2
3
4
5
6
# 
8 && 64 结果为 1
0 && 0 结果为 0
8 & 0 结果为 0
0 || 0 结果为 0
0 | 0 结果为 0

函数调用

设有函数定义:void sub(int k,char ch){...} 则以下对函数sub()调用语句中正确的是?
A: sub(4,”a”); //错误
B: sub(2,’97’); //错误
C: n = sub(3,’a’); //错误 n必然是一个int 或是 char 等类型,总之不可能是 void,所以错误;
D: sub(1,97); //正确

rand() 函数的使用

设有以下程序段:

1
2
int y;
y = rand()%30+1;

则变量 y 的取值范围是
A: (0,30] //正确
B: [0,30]
C: (1,30)
D: (1,30]

static标识的量

对于static标识的量 以及 static标识的 for 循环中的i 是否会在二次调用时重新赋值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 代码一 实验static 标识的普通变量
#include <stdio.h>
#include <stdlib.h>

int fun(int n)
{
static int t = 1; int i;
for (; i <= n; i++) {
t*=i;
}
return t;
}

int main()
{
int t = 1, b;
for (b = 2; b < 4; b++) {
t += fun(b)
}
printf("%d\n", t);
system("pause");
return 0;
} // => 15 ,t 在fun的二次调用中不会重新赋值,而 i 会重新赋值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 代码二 主要实验 
int fun(int n)
{
static int t = 1, i = 1;
for (; i <= n; i++) {
t*=i;
}
return t;
}

int main()
{
int t = 1, b;
for (b = 2; b < 4; b++) {
t += fun(b)
}
printf("%d\n", t);
system("pause");
return 0;
} // => 9 ,t 在fun函数的二次调用中不会重新赋值,而且 i 也不会重新赋值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

int fun(int n)
{
static int t = 1,i;
for (i = 1; i <= n; i++) {
t*=i;
}
return t;
}

int main()
{
int t = 1, b;
for (b = 2; b < 4; b++) {
t += fun(b)
}
printf("%d\n", t);
system("pause");
return 0;
} // => 15 ,t 在fun函数的二次调用中不会重新赋值,而且 i 也不会重新被赋值,但是 当i被二次调用到 for 循环中的i处是就会被二次调用。

** 总结 **

  • 凡是使用static标识的变量,在函数结束调用后其值不会清空,而且该函数被二次调用时,也不会再重新初始化赋值。
  • for(i=0;i<len;i++){... ...}i 在循环中不会重新执行i =0,但是所有的循环完成后,第二次调用for循环i 就会被重新初始化赋值,无论 i 在定义时是否被标识为 static

指针和数组的混合使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>
#include <stdlib.h>

int main()
{
char a[5] = {'1','2','3','4'};
char *pa;
pa = a;
printf("%s\n",pa+1); // => 234
printf("%s\n",pa); // => 1234
system("pause");
return 0;
}

printf(“%d”,a+1); 是输出a还是输出a+1

1
2
3
4
5
6
7
8
9
10
11
12
#include <stdio.h>
#include <stdlib.h>

int main()
{
int a = 2;
printf("%d",a+1); // => 3 也就是说输出的识 a+1

system("pause");
return 0;
}

指针的移动取值

1
2
3
4
5
6
7
8
9
10
11
12
#include <stdio.h>

int main()
{
char *p, old_str[10] = "wind";
p = old_str;
printf("%c", *(p+1)); // => i ; 指针的移动
printf("%c", *p+1); // => x ; 'w'+'1' = 'x'
system("pause");
return 0;
} //这和运算符的优先级有关

结构体数组的赋值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# include <stdio.h>
struct S
{
int x,y;
}; // 这里必需";" , 自定义函数不需要 ";"也不同于 if,for 在 函数中 不需要";",struct 在任何地方都需要";"。

main()
{
struct S data[2] = {4,3,1,9}; //这种结构体数组的赋值方式 是可行的
int i;
for (i = 0;i<2;i++)
printf("%d,%d;",data[i].x,data[i].y>>1);
printf("\n");
}