轉載自本人Open-open部落格:http://www.open-open.com/home/space-43816-do-blog-id-8837.html
====》IO
INPUT與OUTPUT
正常下用scanf/printf即可;從輸入/輸出緩沖區讀
#include <stdio.h>
int main()
{
printf("立馬顯示出來");
fflush(stdout);//重新整理顯示
printf("hello");
sleep(10);//在windows裡面編譯不能通過
printf("world");
return 0;
}
scanf 字元串===》資料
printf 記憶體裡的資料====》字元序列
什麼時候會立馬輸出到螢幕上
1、有輸入請求的時候,會立馬輸出到螢幕
2、輸出有換行符的時候,也會馬上輸出到螢幕上
3、程式結束的時候也會馬上輸出到螢幕上
4、輸出緩沖區滿的時候
#include <stdio.h>
//sscanf,sprintf
int main()
{
char buf[100];
sprintf(buf,"hello,i'm %s ,today is %d-%d-%d\n",
"wow",2012,05,16);
//把資訊放到buffer數組中
puts(buf);
int age;
char name[20];
double salary;
const char * str="21 sxl 2000" ;
sscanf(str,"%d%s%lf",&age,&name,&salary);
printf("我是%s,今年%d,月薪%g\n",name,age,salary);
return 0;
}
1、從鍵盤輸入5各日期,用一個日期數組儲存,寫一個通用排序函數,能夠根據傳入的排序規則對日期進行排序,再寫一個函數用來輸出排序
後的日期。要求寫3個排序規則:一個按年從大到小,一個按月從小到大,一個按整個日期從早到晚。
2、寫一個過濾函數,根據傳入的過濾規則對一組整數進行過濾,輸出所有符合規則的資料并傳回符合規則的資料的個數。
3、寫一個函數,用來傳回一個檔案名字元串,格式為imageXXX.jpg,其中XXX是從000開始的三位整數。每次傳回一個檔案名,每一次跟上一次
不一樣,到999之後回到000。
記憶體配置設定
代碼區
——————————————————————————
靜态全局資料區
——————————————————————————
堆區(自由,一般自己收回)
——————————————————————————
棧區-----一般局部變量;受作用範圍限制
malloc 與 free成對出現
了解指針:
指向數組的指針
指向函數的指針
指向結構變量的指針
指向堆空間的指針
堆空間----用3個函數之一來配置設定空間malloc/calloc/realloc
棧空間
指針隻能儲存位址
memset(位址,數值,位元組數)
sscanf--->sscanf(字元串
---->fscanf(檔案,===》檔案用FILE*指針來表示
sprintf--->sprintf(字元數組
--->fprintf(檔案,
-------------------------------------------
作業系統級别一般用一個int fd來表示檔案;
C語言用file*指針來表示檔案
c++用對象來表示檔案
———————————————————————————————————————————
在C語言中file*指針有3個可用:stdout标準輸出檔案,stderr标準錯誤檔案,stdin标準輸入檔案
其中stderr是沒有緩沖的;而stdout與stdin是有緩沖的
而标準輸入和輸出是可以重定向的
fflush(stdout);//重新整理标準輸出檔案
#include <stdio.h>
int main()
{
int n;
double d;
char str[100];
fsprintf(stdout,"請輸入姓名、年齡和體重:");
fscanf(stdin,"%s%d%lf",str,&n,&d);
fprintf(stdout,"%s:%d歲,%g公斤\n",str,n,d);
return 0;
}
打開檔案用fopen,關閉用fclose
FILE *fopen(const char *path,const char *mode);
FILE *Fdopen(int fildes,const char *mode);
FILE *freopen(const char *path,const char *mode,FILE*stream);
FILE*代表一個檔案
打開方式
r從檔案開始讀取
r+讀和寫,從檔案開始
w清0從頭開始寫
w+如果不存在建立新的,否則将清空,定位在檔案開始
a追加
a+
有時間一定去man一下看看
man stdio.h
stdlib.h
string.h
time.h
math.h
如何實作FILE*呢?
FOPEN
類型 * 位址
vi fio.c
#include <stdio.h>
int main()
{
FILE* fi=fopen("in","r");//會傳回一個FILE*,代表的是一個檔案
//檢查打開檔案是否成功?
if(fi==NULL)
{
printf("打開檔案in失敗\n");
return 1;
}
char name[20];
int age;
double weight;
fscanf(fi,"%s",name);
fscanf(fi,"%d%lf",&age,&weight);
fclose(fi);
printf("姓名:%s,年齡:%d,體重:%g\n",name,age,weight);
FILE* fo=fopen("out","w");
if(fo=NULL){
printf("打開檔案out失敗\n");
return 2;
}
fprintf(fo,"向檔案寫内容\n");
fprintf(fo,"姓名:%s,年齡:%d,體重:%g\n",name,age,weight);
fclose(fo);
return 0;
}
//一定要記得關閉,因為寫的檔案可能在緩沖區中并沒有寫到檔案裡面,否則有可能丢失
格式串,在輸出的時候還有些格式控制:
1、整數:%與%之間可以指定寬度,用什麼來填充;
2、%%之間:如果是小數還可以指定寬度.小數位數f
3、可以指定靠左還是靠右,-表示靠左;預設靠右
4、%寬度.字元數s
以上規則:對于鍵盤,螢幕以及檔案都适用
#include <stdio.h>
int main()
{
char * s="helloworld"
printf("%d,%10d,%-10d,%010d,%+d\n",123,123,123,123,123);
printf("%f,%10f,%-10f,%6.2f\n",1.2,1.2,1.2,1.2);//%f固定6位小數
printf("%s,%10s,%-10s,%6.3s\n",s,s,s,s);
int w=10;
for(w=10;w<15;w++)
{
printf("%c,%*c\n",'a',w,'a');
}
//在這裡寬帶使用*,可變寬度
printf("input an integer:");
int x,y;
scanf("%3d%5d",&x,&y);
printf("x=%d,y=%d\n",x,y);
//輸入1234567890,輸出為x=123 y=45678
//輸入12 3,輸出x=12 y=3
//輸入12345 輸出x=123 y=45
scanf("%*d%d",&x);//在scanf中這個*表示抛棄;而在上面printf中表示參數
printf("x=%d\n",x);
char str[100],st[100];
scanf("%[a-z]%[^a-z]",str,st);//讀取在方括号内的字元,比如讀取小寫字元
//[^]表示不是這個範圍的
printf("str=%s,st=%s\n",str,st);
return 0;
}
//其他的輸出格式:
可以通過man printf來看
從檔案讀和從鍵盤讀
scanf/printf fopen==>FILE* fclose
puts/gets fgets/fputs
gets會抛棄換行符
puts在寫時會加上換行符
自動換行
fgets從檔案讀取一行,不會抛棄換行符,把它作為字元串的一部分
fputs向檔案寫的時候不會加換行符
一般情況下puts/fgets;fputs/gets交叉使用。
#include <stdio.h>
int main()
{
char buf[1000];
printf("請輸入一行文字:\n");
//gets(buf);
//scanf("%[^\n]%*c",buf);
fgets(buf,sizeof(buf),stdin);
buf[strlen(buf)-1]='\0';//去掉末尾換行符
puts(buf);
printf("%s",buf);
fputs(buf,stdout);//fputs本身并不換行
return 0;
}
//配置檔案,使用者資訊檔案/etc/passwd 一般都是一行一行的。
讀寫一個字元
getchar/putchar
等價scanf("%c" / printf("%c")
fgetc/fputs
getc/putc
fgetc一定是一個函數;getc有可能是個函數也可能是個宏
傳回值為int而非char
不管什麼字元都讀取
#include <stdio.h>
int main()
{
int i;
int d;
for(i=0;i<3;i++)
{
// printf("請輸入一個整數:");
// scanf("%d",&d);
// scanf("%*[^\n]");scanf("%*c");
// printf("您輸入的是%d\n",d);
// getchar();
d=getchar();
if(d==EOF){
printf("讀取終止\n");
break;
}
printf("%c(%d)\n",d,d);
}
return 0;
}
#include <stdio.h>
//int fgetc(FILE*)/int fputc(int,FILE*)
int main(int argc,char* argv[])
{
//a.out filename copyfile
if (argc!=3){
printf("%s filename copyfile\n",*argv);
return 0;
}
FILE * fi=fopen(argv[1],"r");
if(fi==NULL){
printf("無法打開檔案%s"\n,argv[1]);
return 1;
}
FILE* fo=fopen(argv[2],"w");
if(fo==NULL){
printf("無法打開檔案%s\n",argv[2]);
return 2;
}
char c;
while((c=fgetc(fi))!=EOF){//EOF在編譯前會替換成-1
putchar(c);
fputc(c,fo);
}
fclose(fi);
fclose(fo);
return 0;
}
vi position.c
#include <stdio.h>
int main()
{
FILE* fp=fopen("file","r+");
if(fp==NULL)
{
printf("無法打開檔案file\n");
return 1;
}
int c;
while((c=fgetc(fp))!=EOF){
fputc(c,fp);
}
fclose(fp);
return 0;
}
vi file
abcdefghijklmnopqrstuvwxyz
如何定位檔案目前的讀寫呢?fseek函數,設定目前讀寫位置
feek(哪個檔案,位置參數,從哪裡算起的偏移量)
可以從目前位置或者某個特定的位置開始的偏移量seek_set,seek_cur,seek_end
ftell取目前位置
rewind把目前位置設定為檔案的最開頭
什麼時候使用呢?比如1、音頻或視訊的播放器;2、資料庫
我們讀取file檔案,把第10個和第20個字元交換位置
1、打開檔案
2、讀取出第10個字元
3、讀取出第20個字元
4、
#include <stdio.h>
int main()
{
FILE* fp=fopen("file","r+");
if(fp==NULL){
printf("無法打開檔案file\n");
return 1;
}
fseek(fp,9,SEEK_SET);
char c10,c20;
c10=getc(fp);
fseek(fp,9,SEEK_CUR);//getc讀取完畢後,其位置加1,是以是9
c20=getc(fp);
fseek(fp,-11,SEEK_CUR);//用負數,是代表向前
putc(c20,fp);
fseek(fp,-8,SEEK_END);//為什麼是-8,需要考慮換行符
putc(c10,fp);
fclose(fp);
return 0;
}
在記憶體和檔案進行大量的讀寫時,則用fread/fwrite;從檔案到記憶體叫讀;将記憶體的東西放到檔案裡面叫寫。
size_t fread(void *ptr,size_t size,size_t nmemb,FILE* stream);
size_t fwrite(const void *ptr,size_t size,size_t nmemb,FILE* stream);
對于記憶體中的資料,主要關注位址而非類型
vi fwrite.c
#include <stdio.h>
//fread(記憶體位址,每條記錄的位元組數,記錄的個數,哪個檔案)
//fwrite
typedef struct person{
char name[20];
char gender;
int age;
double salary;
}person;
int main()
{
person a[5]={{"abc",'F',18,3500},{"def",'M',20,4500},{"ghi",'F',20,3000},{"jkl",'F',23,2000},{"mno",'M',22,8000}};
FILE* fp=fopen("person.dat","wb",);//b在這裡的意思是不做任何轉換
if(fp==NULL){
printf("打開person.dat檔案失敗\n");
return 1;
}
int b[10]={11,22,33,44,55,66,77,88,1010};
short s=12345;
fwrite(a,sizeof(person),5,fp);
fwrite(b,sizeof(int),10,fp);
fwrite(&s,sizeof(short),1,fp);
fclose(fp);
return 0;
}
以上是将相關資訊寫到了person.dat檔案中去了。
我們通過fread将資訊從person.dat中讀到記憶體中去
vi fread.c
#include <stdio.h>
typedef struct person{
char name[20];
char gender;
int age;
double salary;
}person;
int main()
{
person a[5]={};
int b[10]={};
short s=0;
FILE* fp=fopen("person.dat","rb");
if (fp==NULL){
printf("打開person.dat檔案失敗\n");
return 1;
}
fread(a,sizeof(person),5,fp);
fread(b,sizeof(int),10,fp);
fread(&s,sizeof(short),1,fp);
fclose(fp);
int i;
for (i=0;i<5;i++){
printf("%s:%s,%d,^g\n",a[i].name,a[i].gender='M'?"man":"women",a[i].age,a[i].salary);
}
for (i=0;i<10;i++){
printf("%d ",b[i]);
}
printf("\n");
printf("%hd\n",s);
return 0;
}
//ungetc向檔案裡面退出一個字元;下一次就讀這個字元
舉例:讀取172.18.9.6或者ftp.xxx.xxx.xxx
vi ungetc.c
#include <stdio.h>
int main()
{
printf("請輸入一些内容\n");
char str[1000];
double data;
register int c;
for(;;){
c=getchar();
if(c==EOF) break;
if(isspace(c)) continue;//isblank是不是空白
ungetc(c,stdin);
if(c>='0'&&c<='9'){
scanf("%lf",&data);
printf("data=%lf\n",data);
}
else{
scanf("%s",str);
printf("str=%s\n",str);
}
}
return 0;
}
//fgetc(),fgets(),fread(),fwrite()
//feof(FILE*)//是否超越了檔案末尾