C-回顾一些细节问题

挺久没写C了,回顾一些易错的细节

输入输出

输入和输出都要写格式控制表

输入的时候需要在变量前加一个&,因为实际上scanf是将输入流中的数据输入到给定变量地址对应的储存单元上

但注意字符串并不需要加&,因为字符串变量名实际上就是一个指向字符串所在地址的指针(数组变量名也是)

scanf读取任何数据都以空格、换行为分隔符

1
2
3
4
5
6
7
8
9
10
11
12
/*INPUT*/
//输入格式控制
//int、float、double、char
scanf("%d",&a);
scanf("%c",&a);
//string不需要&
scanf("%s",s);

/*OUTPUT*/
//输出格式控制
printf("%d",a);
printf("%s",s);

读字符串问题

http://c.biancheng.net/view/1833.html

注意:字符串不能这样,以下两者都是错的

1
2
3
4
char *str;
scanf("%s",str);
//或
gets(str);

在C中,无论字符串或数组都必须要初始化,也就是要给定初值,或者只申明长度(初值默认为NULL)

scanf默认以空格作为分隔符

gets默认以回车作为分隔符

数组定义

c数组声明的时候必须指定长度:int a[5]

若声明的时候有初值,那就自动计算长度:int a[]={1,2,3,4,5}

通过指针直接操作数组

数组名是常量指针,指针是变量指针

数组在空间连续,数组名即指向数组储存单元首地址的指针,然后算地址偏移量即可找到数组某元素所在储存单元,我一般都习惯用指针来直接控制数组

不过注意数组在定义的时候就已经开辟了一串相邻的空间,指针增加元素要自己额外开辟内存

返回数组的函数

C 语言不允许返回一个完整的数组作为函数的参数。

但是可以通过指定不带索引的数组名来返回一个指向数组的指针

1
2
3
4
5
6
7
8
9
10
11
12
13
//举例
#include<stdio.h>
int* input()
{
int a[5] = {1,2,3,4,5};
return a;
}

int main()
{
int *a = input();
printf("%d",*a);
}

形参实参

要改变实参需传递指针(地址)给函数

像在java中就不需要考虑这个问题,因为java中没指针,一切变量名皆引用(基本数据类型除外)

多维数组

1
2
3
int [2][3];//只申明长度,默认初始化,值为NULL

int [][]={{1,2},{2,3}}//不申明长度,直接自定义初始化

字符串

其定义方式很像字符数组:

1
2
3
4
char greeting[] = "Hello";

//也可以这样定义(我常用)
char *string = "abc";

但字符串末尾是'\0',标志字符串的结束位,而字符数组不需要,因为字符串变量名/数组变量名实际上就是一个指向字符串所在地址的指针,所以程序必须通过'\0'来判断读取字符串是否结束。

所以sizeof(s)-1才是字符串s的长度,而sizeof(array)即是数组长度

比如对于上面定义的字符串

1
2
3
4
5
6
7
8
9
10
11
//字符串
char *string = "abc";
printf("%d",sizeof(string));
---
4 //'a','b','c','\0'

//字符数组
char string[] = {'a','b','c'};
printf("%d",sizeof(string));
---
3 //'a','b','c'

以下三个函数需导入#include <string.h>

字符串长度:strlen函数

将指定长度的字符串复制到字符数组中:strncpy函数

置字节字符串s的前n个字节为零:bzero函数,memset函数

文件读写:EOF问题

C中的NULL

在C语言中,NULL0的值都是一样的,但是为了目的和用途及容易识别的原因,NULL用于指针和对象,0用于数值
而Java中的null就是个关键字,是任何引用类型的默认值

常见问题

warning: incompatible implicit declaration of built-in function ‘malloc’

头文件缺:#include<stdlib.h>