gets函数,从标准输入读取一行文本,一行输入由一串字符组成,以一个换行符结尾;
gets函数丢弃换行符,并在该行的末尾存储一个NUL字符(类似‘\0’), 然后返回一个非NULL值。
当gets函数被调用但事实上不存在输入行时,它返回NULL值。
注意点:给字符串分配空间加NUL的空间;
格式字符串包含格式指定符(格式代码)以及普通字符,这些普通字符将按照原样打印出来;
但每个格式指定符将使后续参数的值按照它所指定的格式打印。
%d 十进制打印; %g 打印浮点值;
%o 八进制打印; %c 打印一个字符;
%x 十六进制打印; %s 打印一个字符串;
scanf()函数返回值是函数成功转换并存储于参数中的值个数;
perror函数以一种简单、统一的方式报告错误,perror函数简化向用户报告这些特定错误的过程,它的原型定义于stdio.h
void perror(char const *message);
如果message不是NULL并且指向一个非空的字符串。perror函数就打印出这个字符串,后面跟一个分号和一个空格。
然后打印出一条用于解释errno当前错误代码的信息;
终止执行:
exit函数,用于终止一个程序的执行,它的原型定义于stdlib.h
void exit(int status);
该函数的返回值为void;
就c程序而言,所有的I/O操作只是简单地从程序移进或移出字节的事情。 因此,毫不惊奇的是,这种字节流便称为流(stream);
程序只需要关心创建正确的输出字节数据,以及正确地解释从输入读取的字节数据,特定I/0设备的细节对程序员是隐藏;
流分为两种类型:文本(text)流 和二进制(binary)流;
stdio.h所包含的声明之一就是FILE结构。请不要把它和存储于磁盘上的数据文件相混淆。
FILE是一个数据结构,用于访问一个流,如果你同时激活量几个流,每个流都有一个相应的FILE与它关联,为了流上执行一些操作,你调用一些
合适的函数,并向它们传递一个与这个流相关联的FILE参数;
EOF: end of file , 它的实际值比一个字符要多几位,这是为了避免二进制值被错误地解释为EOF;
I/O函数以三种基本的形式处理数据:单个数据、文本行、二进制数据;
对于每种形式,都有一组特定的函数对它们进行处理。
数据类型 输入 输出 描述
字符 getchar putchar 读取(写入)单个字符
文本行 gets puts 文本行未格式化的输入(输出)
scanf printf 格式化的输入(输出)
二进制数据 fread fwrite 读取(写入)二进制数据
字符I/O宏
fgetc 和 fputc 是真正的函数,但getc、putc、getchar 和putchar 都是通过#define 指令定义的宏;
撤销字符I/O
int ungetc(int character, FILE* stream);
功能:ungetc 把 一个先前读入的字符返回到流中,这样它可以在以后被重新读入;
(应用:假如你必须从一个流中逐个读入一串数字,由于在实际读入之前,你无法知道下一个字符,你必须连续读取,直到读入一个非数字字符,
但是如果你不希望丢弃这个字符,那么你该怎么办?
使用ungetc把读入的字符退还给流,是一个不错的办法)
“退回”字符和流的当前位置有关,所以如果 用 fseek、 fsetpos、 rewind 函数改变了流的位置, 所有退回的字符都将被丢弃;
scanf家族:
scanf函数家族的原型如下所示,每个原型中的省略号表示一个可变长度的指针列表;
从输入转换而来的值逐个存储到这些指针参数所指向的内存位置;
int fscanf(FILE *stream, char const *format, ... );
int scanf( char const *format, ... );
int sscanf(char const *string, char const * format, ... );
这些函数都从输入源读取字符串并根据format字符串的格式代码对它们进行转换。
fscanf的输入源 就是作为参数给出的流。
scanf从标准输入读取,
sscanf从第1个参数所给出的字符串中读取字符;
对于scanf函数的参数前面为什么要加一个&符号?由于c的传值参数传递机制,把一个内存位置作为参数传递给函数的唯一方法是传递一个指向该位置的指针; 在使用scanf函数时,一个非常容易出现的错误是忘记加&符,省略这个符号将导致变量的值作为参数传递给函数,
而scanf函数(或者其它两个)却把它解释为一个指针,当它被解引用时,要么导致程序终止(试图修改非法的地址);要么导致一个不可预测的内存位置的数据被修改;
sscanf函数说明:int sscanf(const char *str, const char * format, .......);
sscanf()会将参数str的字符串(一定要是字符串), 根据参数format来转换并将格式化数据,转换后的结果存于对应的参数内;
返回值: 成功则返回参数数目, 失败则返回-1;错误原因存于errno中。返回0表示失败,否则,表示正确格式化数据的个数。
例如:sscanf(str , "%d %d %s", &i, &i2, &s); 如果三个均成功返回3, 如果只读入了第一个整数到i则会返回1,证明无法从str读入第二个整数;
char input[] = "10.10.aaaaaa.bbbbbb";
sscanf(input, "%d.%d.%5[a-z] %*s %f”,&i,&j,s,s);
printf(“%d %d %s ”,i,j,s);
执行: 10 10 aaaaa
常见用法:
char str[512] = {0};
sscanf("123456", "%s", str);
printf("str=%s", str);
2.取指定长度的字符串。如下:
sscanf("123456", "%4s", str);
printf("str = %s", str);
3. 取到指定字符为止的字符串。如在下例中,取遇到空格为止字符串。 //验证有问题,还是没明白其意思呢
sscanf("123456abcdedf","%[^]",str);
printf("str=%s", str);
4、取仅包含指定字符集的字符串,如下,取仅包含1到9和小写字母的字符串;
sscanf("123456abcdedfBCDEF","%[1-9a-z]",str);
printf("str=%s",str);
5、取到指定字符集为止的字符串,如下,取遇到大写字母为止的字符串;
sscanf("123456abcdedfBCDEF","%[^A-Z]", str);
printf("str=%s",str);
***************************************************************
可以用如下代码将字符串形式的ip地址转换为四个整数:
- char * inputIp
- int ip[4];
- sscanf_s(inputIp, "%d.%d.%d.%d", &ip[0], &ip[1],&ip[2],&ip[3]);
以下部分还没用到:
注意sscanf_s,当读入的类型是整数或其它长度可以确定的类型时,不能在类型后面跟上长度,但是对于字符串类型(char *)长度无法得知则必须在类型后面明确指出字符串的最大长度(即可以容纳的空间)。举例如下:
1 // crt_sscanf_s.c 2 // This program uses sscanf_s to read data items 3 // from a string named tokenstring, then displays them. 4 5 #include <stdio.h> 6 #include <stdlib.h> 7 8 int main( void ) 9 { 10 char tokenstring[] = "15 12 14..."; 11 char s[81]; 12 char c; 13 int i; 14 float fp; 15 16 // Input various data from tokenstring: 17 // max 80 character string plus NULL terminator 18 sscanf_s( tokenstring, "%s", s, _countof(s) ); 19 sscanf_s( tokenstring, "%c", &c, sizeof(char) ); 20 sscanf_s( tokenstring, "%d", &i ); 21 sscanf_s( tokenstring, "%f", &fp ); 22 23 // Output the data read 24 printf_s( "String = %s\n", s ); 25 printf_s( "Character = %c\n", c ); 26 printf_s( "Integer: = %d\n", i ); 27 printf_s( "Real: = %f\n", fp ); 28 }
对于多个字符串读入的情况,代码如下:
- sscanf_s(inputString, "%s.%s.%s.%s", s1, s1.length, s2, s2.length, s3, s3.length, s4, s4.length);