挺久没写C了,回顾一些易错的细节
输入输出
输入和输出都要写格式控制表
输入的时候需要在变量前加一个&
,因为实际上scanf是将输入流中的数据输入到给定变量地址对应的储存单元上
但注意字符串并不需要加&
,因为字符串变量名实际上就是一个指向字符串所在地址的指针(数组变量名也是)
scanf
读取任何数据都以空格、换行为分隔符
/*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
注意:字符串不能这样,以下两者都是错的
char *str;
scanf("%s",str);
//或
gets(str);
在C中,无论字符串或数组都必须要初始化,也就是要给定初值,或者只申明长度(初值默认为NULL)
scanf
默认以空格作为分隔符
gets
默认以回车作为分隔符
数组定义
c数组声明的时候必须指定长度:int a[5]
若声明的时候有初值,那就自动计算长度:int a[]={1,2,3,4,5}
通过指针直接操作数组
数组名是常量指针,指针是变量指针
数组在空间连续,数组名即指向数组储存单元首地址的指针,然后算地址偏移量即可找到数组某元素所在储存单元,我一般都习惯用指针来直接控制数组
不过注意数组在定义的时候就已经开辟了一串相邻的空间,指针增加元素要自己额外开辟内存
返回数组的函数
C 语言不允许返回一个完整的数组作为函数的参数。
但是可以通过指定不带索引的数组名来返回一个指向数组的指针。
//举例
#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中没指针,一切变量名皆引用(基本数据类型除外)
多维数组
int [2][3];//只申明长度,默认初始化,值为NULL
int [][]={{1,2},{2,3}}//不申明长度,直接自定义初始化
字符串
其定义方式很像字符数组:
char greeting[] = "Hello";
//也可以这样定义(我常用)
char *string = "abc";
但字符串末尾是'\0'
,标志字符串的结束位,而字符数组不需要,因为字符串变量名/数组变量名实际上就是一个指向字符串所在地址的指针,所以程序必须通过'\0'
来判断读取字符串是否结束。
所以sizeof(s)-1
才是字符串s
的长度,而sizeof(array)
即是数组长度
比如对于上面定义的字符串
//字符串
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语言中,NULL
和0
的值都是一样的,但是为了目的和用途及容易识别的原因,NULL用于指针和对象,0用于数值
而Java中的null
就是个关键字,是任何引用类型的默认值
常见问题
warning: incompatible implicit declaration of built-in function ‘malloc’
头文件缺:#include<stdlib.h>