一、gets
gets是个不安全的函数,应该坚决不用。它每遇到换行符就会返回,即使是一开始就遇到一个换行符。返回后会将换行符变为'\0'。由于gets()无法知道字符串的大小,必须遇到换行字符或文件尾才会结束输入,因此容易造成缓存溢出的安全性问题。
二、fgets
char *fgets(char *buf, int bufsize, FILE *stream);
当遇到换行符或者缓冲区已满,fgets就会停止,返回读到的数据。注意换行符会被保存在缓冲区中,只是后面再加个'\0'。
注意,对于fgets来说,'\n'是一个特别的字符,而'\0'并无任何特别之处,如果读到'\0'就当作普通字符读入。如果文件中存在'\0'字符(或者0x00字节),调用fgets之后就无法判断缓冲区中的'\0'究竟是从文件读上来的字符还是由fgets自动添加的结束符,所以fgets只适合读文本文件而不适合读二进制文件,并且文本文件中的所有字符都应该是可见字符,不能有'\0'。
补充:glibc提供的getline函数:参考http://man7.org/linux/man-pages/man3/getline.3.html
可以读取不定长的“行”,能正确处理各种情况,但是它返回的是malloc分配的内存,需要用户自己free掉。
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
int
main(void)
{
FILE *fp;
char *line = NULL;
size_t len = 0;
ssize_t read;
fp = fopen("/etc/motd", "r");
if (fp == NULL)
exit(EXIT_FAILURE);
while ((read = getline(&line, &len, fp)) != -1) {
printf("Retrieved line of length %zu :\n", read);
printf("%s", line);
}
free(line);
fclose(fp);
exit(EXIT_SUCCESS);
}
三、scanf
char str[100]; scanf("%s", str);
如果scanf在开头遇到前次函数留下的空格或换行符,scanf一律跳过, 继续运行;如果在中间遇到空格或遇到换行符,scanf将会停止。在读取的字符串后加上'\0'。
四、puts与fputs
int puts(const char *string);
int fputs(const char *str, FILE *fp); //注意区别于fputc(c, fin).
fputs向指定的文件写入一个字符串,puts向标准输出写入一个字符串。
缓冲区s中保存的是以'\0'结尾的字符串,fputs将该字符串写入文件stream,但并不写入结尾的'\0'。与fgets不同的是,fputs并不关心的字符串中的'\n'字符,字符串中可以有'\n'也可以没有'\n'。puts将字符串s写到标准输出(不包括结尾的'\0'),然后自动写一个' \n'到标准输出。
五、read是一个系统调用,其他函数会调用该函数
ssize_t read(int filedes, void *buf, size_t nbytes); 从终端读可以char data[100]; n = read(STDIN_FILENO, data, 100);
read 函数从 filedes 指定的已打开文件中读取 nbytes 字节到 buf 中。以下几种情况会导致读取到的字节数小于 nbytes :
A. 读取普通文件时,读到文件末尾还不够 nbytes 字节。例如:如果文件只有 30 字节,而我们想读取 100 字节,那么实际读到的只有 30 字节,read 函数返回 30 。此时再使用 read 函数作用于这个文件会导致 read 返回 0 。
B. 从终端设备(terminal device)读取时,一般情况下每次只能读取一行。
C. 从网络读取时,网络缓存可能导致读取的字节数小于 nbytes 字节。
D. 读取 pipe 或者 FIFO 时,pipe 或 FIFO 里的字节数可能小于 nbytes 。
E. 从面向记录(record-oriented)的设备读取时,某些面向记录的设备(如磁带)每次最多只能返回一个记录。
F. 在读取了部分数据时被信号中断。
注意:read不会自动加上'\0';对于\n,它也是原封不动的读入,当做普通字符。
六、readline库
#include <readline/readline.h>
#include <readline/history.h>
char *line_read = (char *)NULL;
line_read = readline("Please Enter:");
readline 是一个强大的库,只要使用了它的程序,都可以用同一个配置文件配置,而且用同样的方法操作命令行,让你可以方便的编辑命令行。
七、strlen
返回字符串的长度。该字符串可能是自己定义的,也可能是内存中随机的,该函数实际完成的功能是从代表该字符串的第一个地址开始遍历,直到遇到结束符NULL。返回的长度大小不包括NULL。
八、C的关于打开、读取、关闭文件的api
std::string s;
FILE *fin=fopen("e:\\in.txt","r");
FILE *fout=fopen("e:\\out.txt","w");
while(fscanf(fin,"%c",&c)!=EOF)
{
s+=c;
fprintf(fout,"%s",s.c_str());
fputc(c,fout);
}
fclose(fin);
fclose(fout);
九、C++部分
http://www.cnblogs.com/JCSU/articles/1190685.html
1、逐词读取, 词之间用空格区分
ifstream fin("data.txt"); //#include <fstream>
string s; //#include <string>
while( fin >> s )
{
cout << "Read from file: " << s << endl;
}
fin.close(); //最后别忘了关闭
2、行读取, 将行读入字符数组, 行之间用回车换行区分
ifstream fin("data.txt");
const int LINE_LENGTH = 100;
char str[LINE_LENGTH];
while( fin.getline(str,LINE_LENGTH) ) //如果是终端,就是cin.getline(str, LINE_LENGTH)
{ //默认遇到\n即结束读取,最多读取99个字符,并在结尾自动加\0.
cout << "Read from file: " << str << endl;
}
3、逐行读取, 将行读入字符串, 行之间用回车换行区分
ifstream fin("data.txt");
string s;
while( getline(fin,s) ) //如果是终端,就是getline(cin, s)
{ //注意这里s必须是string,而不能是字符数组。s的末尾会自动有\0.
cout << "Read from file: " << s << endl;
}