C语言输入输出
scanf() & printf()
头文件:#include<stdio.h>
1 | //in: 1 2 |
当扫描到文件结束符后,就自动结束输入
x为正确接收到值的变量个数。当scanf函数的第一个变量格式不正确时返回值为0,即,当scanf函数的第n个变量格式不正确时,返回值为n-1;当scanf在扫描到了合法字符之前扫描到了输入结束符,则返回-1。
输入浮点数
1 | double f; |
上面的lf格式对应double数据类型,f格式对应float数据类型。
输入16进制数
1 | //int: A |
输入多个单词
1 | while(scanf("%d",&a) > 0){ |
输出填充字符
1 | int main() |
getchar() & putchar()
头文件:#include<stdio.h>
函数 int getchar(void) 函数读取下一个可用的字符,若到达了文件的结尾,则返回-1。
1 |
|
int putchar(void) 函数在同一个时间把一个字符输出到屏幕上。
fgets()和cin.get()
头文件:#include<stdio.h>
函数 char *fgets(char *str, int n, FILE* stream) 从指定的流 stream 读取一行,并把它存储在 str 所指向的字符串内。当读取 (n-1) 个字符时,或者读取到换行符时,或者到达文件末尾时,它会停止。
1 |
|
1 | //输入 |
cin.ignore()
cin.ignore()函数是C++标准输入流(cin)中的一个方法。cin.ignore()函数中有两个参数,分别为数值型的a 和 字符型的 ch ,即cin.ignore( a, ch )。它表示从输入流 cin 中提取字符,提取的字符被忽略,不被使用。而每抛弃一个字符,它都要进行计数和比较字符:如果计数值达到 a 或者被抛弃的字符是 ch ,则cin.ignore() 函数执行终止;否则,它继续等待。
它的一个常用功能就是用来清除以回车结束的输入缓冲区的内容,消除上一次输入对下一次输入的影响。例如可以这么用,cin.ignore(1024, ‘\n’),通常把第一个参数设置得足够大,这样实际上是为了只有第二个参数 ‘\n’ 起作用,所以这一句就是把回车(包括回车)之前的所以字符从输入缓冲流中清除出去。
1 | cin.ignore(INT_MAX, '\n'); |
例子:
1 |
|
getline()
需要额外引入string包。
只能用来给string类型输入字符串。
不把分隔符读入string中,同时把分隔符从缓冲区中移出。
1 |
|
sscanf() & sprintf()
1 | char str[] = "123" |
从字符串中读入数组。由此看来,sscanf()和scanf()有很多相似之处。
1 | double a = 12.123; |
将数字输出到字符串中。
C语言字符串
头文件:#include<string.h>
C语言字符串操作要保证给字符串开足够大的空间。
strcpy()
1 | char s1[10]; |
strcat()
1 | char s1[10]; |
strlen()
1 | strlen(s1); //返回s1的长度 |
strcmp()
1 | strcmp(s1,s2); |
strchr()
返回字符首次出现的指针位置。
1 | char s1[10] = "123"; |
可以通过strchr()函数实现C++中string对象的find()函数的操作。
strncpy()
函数格式:char *strncpy(char *dest, const char *src, size_t n)
n:要从源中复制的字符数
1 |
|
注意:strncpy不会在最后加上\0结束符。
指针
void*指针
在使用C语言进行开发的过程中,经常会遇到void*这样一个特殊的指针。
下面是void *指针的使用场景。
用作泛型,接收任意数据类型指针
void*用于指向特定地址,而无需关心这个地址上存放着什么类型的数据。例如常见的memcpy等函数就用到void*,函数原型如下:
1 | void *memcpy(void *des, void *src, size_t n); |
此处的void des和void src可以接收任意类型的数据类型指针,既然是内存拷贝,入参就不应该限制传入什么类型的指针,逻辑上十分合理。
动态内存申请与释放
动态内存申请函数返回值一般都是void*,如果申请成功则返回的是申请的内存块的首地址,申请失败则返回一个空指针NULL,NULL相当于(void *)0。C库的malloc函数原型如下:
1 | void *malloc(size_t size); |
一般申请完内存之后会与指针类型强制转换一起使用,如下所示。
1 | typedef struct |
函数指针
如果在程序中定义了一个函数,那么在编译时系统就会为这个函数代码分配一段存储空间,这段存储空间的首地址称为这个函数的地址。而且函数名表示的就是这个地址。既然是地址我们就可以定义一个指针变量来存放,这个指针变量就叫作函数指针变量,简称函数指针。
定义一个指向函数的指针变量 p,p的类型是int(*)(int,int):
1 | int(*p)(int, int); |
例子:
1 |
|
输出:
1 | please enter a and b:3 4 |
指向函数的指针变量没有 ++ 和 — 运算
预处理语句
ifndef
在.h文件中,经常会看到这样的代码:
1 | // a.h |
假如:
1 | // b.h |
1 | // c.c |
当我们编译a.h,a.c,b.h,b.c, c.c时,如果没有a.h文件中的预处理语句ifndef,那么a.h中的代码就会出现两次,导致重复声明;当有了ifndef预处理语句时:包含a.h会使得__A_H_常量被定义并且将它的代码包含再c.c中,然后再包含b.h时由于__A_H_时,就由于__A_H_被定义,所以不会再包含重复的代码了。