chapter 8 文件


大學C語言程序設計

chapter 8 文件

對於輸入輸出,一般我們分兩種:

  1. 標准輸入輸出,也就是通過鍵盤和顯示器控制台來輸入輸出。
  2. 文件輸入輸出,無需手動輸入,程序會自動讀寫相關文件。

總的來講文件操作形式有三種:
一、freopen文件重定向
二、fopen文件輸入輸出
三、fstream文件輸入輸出流
(部分競賽不允許使用文件重定向,但是信息學競賽專門考察文件重定向,可能是因為它更簡單)。

1. freopen文件重定向

一、freopen文件重定向
 需要使用freopen函數,包含於標准庫 <stdio.h>中,使用格式如下:
    freopen ( filename, mode, stream);
譯:freopen ( 文件名, 文件打開模式, 文件流);
例:
    freopen("data.in", "r", stdin);
    freopen("data.out", "w", stdout);
    //....
    fclose(stdin);    //關閉文件輸入流
    fclose(stdout); //關閉文件輸出流

重定向樣例

#include<stdio.h>

int main(){
    freopen("data.in", "r", stdin);
    freopen("data.out", "w", stdout);

    int a,b,ans;
    scanf("%d%d", &a, &b);
    ans = a+b;
    printf("%d", ans);

    fclose(stdin);
    fclose(stdout);
    return 0;
}

2. fopen文件輸入輸出

二、fopen
 需要使用fopen函數,包含於標准庫 <cstdio>中,使用格式如下:
    FILE *file = fopen( filename, mode);
譯:FILE *file = fopen( 文件名, 文件打開模式);
例:
    FILE *fin,*fout;
    fin = fopen("data.in", "rb");
    fout = fopen("data.out", "wb");
    //注意:使用fopen的讀寫方式為文件讀寫 fscanf/fprintf
    fclose(fin);   //關閉文件
    fclose(fout);  //關閉文件

 fopen改寫為標准輸入輸出只需:fin=stdin; fout=stdout; 不需要fopen和fclose。

fopen樣例

#include<stdio.h>

int main(){
    FILE *fin, *fout;
    fin = fopen("data.in", "rb");
    fout = fopen("data.out", "wb");

    int a,b,ans;
    fscanf(fin, "%d%d", &a, &b);
    ans = a+b;
    fprintf(fout, "%d\n", ans);

    fclose(fin);
    fclose(fout);
    return 0;
}

3. fopen標准輸入輸出

#include<stdio.h>

int main(){
    FILE *fin, *fout;
    fin = stdin;
    fout = stdout;

    int a,b,ans;
    fscanf(fin, "%d%d", &a, &b);
    ans = a+b;
    fprintf(fout, "%d\n", ans);

    //fclose(fin);//標准輸入輸出不需要fopen/fclose
    //fclose(fout);
    return 0;
}

4. fstream文件輸入輸出流

三、文件輸入輸出流
 需要使用流操作以及設定輸入輸出對象到那個文件,二類的定義在標准庫 <fstream>中,所以需要導入該頭文件。

例:用fin作為輸入對象,fout作為輸出對象,可以使用如下定義:

    ifstream fin("data.in");    //定義輸入文件名
    ofstream fout("data.out");  //定義輸出文件名

    fin.close();  //關閉文件
    fout.close(); //關閉文件

文件輸入輸出流樣例

#include<fstream>
using namespace std;
int main(){
    ifstream fin("data.in");
    ofstream fout("data.out");

    int a,n,ans;
    fin>>a>>b;
    ans=a+b;
    fout<<ans<<endl;

    fin.close();
    fout.close();
    return 0;
}

5. scanf/printf and fscanf/fprintf and sscanf/sprintf

scanf/printf 表示從控制台輸入輸出
fscanf/fprintf 表示從文件輸入輸出
sscanf/sprintf 表示從字符串中輸入輸出(或者說賦值)給另外的字符串
當兩者混用時,相互不影響,但是其作用都能表現出來。

#include<stdio.h>

int main(){
    FILE *fin, *fout;
    fin = fopen("data.in", "rb");
    fout = fopen("data.out", "wb");

    int a,b,ans;
    fscanf(fin, "%d%d", &a, &b);
//    scanf("%d%d", &a, &b);
    ans = a+b;
    fprintf(fout, "%d\n", ans);
    printf("%d\n", ans);

    fclose(fin);
    fclose(fout);
    return 0;
}
#include<stdio.h>
#include<string.h>

void fun1(){
    char buf[100], buf2[100], buf3[100];
    scanf("%s", buf);
    sscanf(buf, "%s", buf2);//從 buf中以格式 %s 讀入賦給 buf2

    sprintf(buf3, "%s", buf2);//從 buf2中以格式 %s 讀入賦給 buf3
    printf(" buf=%s\n buf2=%s\n buf3=%s\n",buf, buf2, buf3);
}

void fun2(){
    char ip[100]="192.168.1.1:8080", buf[100];
    int a,b,c,d,e;
    sscanf(ip, "%d.%d.%d.%d:%d", &a, &b, &c,&d, &e);
    sprintf(buf, "%d.%d.%d.%d:%d", a, b, c,d, e);
    printf("a=%d\n",a);
    printf("b=%d\n",b);
    printf("c=%d\n",c);
    printf("d=%d\n",d);
    printf("e=%d\n",e);
    printf("strcmp(ip,buf)=%d\n", strcmp(ip,buf));
}

void fun3(){
    char buf[]="`1234567890-=qwertyuiop[]\asdfghjkl;'zxcvbnm,./";
    printf("%d\n", strlen(buf));
    for(int i=0; i<strlen(buf); i++){
        printf("%c", buf[i]);
    }printf("\n");

    int a;
    char buf2[100], buf3[100];
    sscanf(buf, "%*c%d%s", &a, buf2);// *表示跳過
    sprintf(buf3, "%d", a); //將 a的數據存入字符數組 buf3
    printf(" a=%d\n buf2=%s\n buf3=%s\n", a, buf2, buf3);
}

int main(){
    fun1();
    fun2();
    fun3();
    return 0;
}

6. 頭文件.h - 項目的形式

前面我們所學的都是通過單個頁面書寫程序,但是這樣會使得程序主體過於復雜,
於是我們可以將部分關聯性較強的程序封裝另外一個文件中,在通過頭文件導入的形式使用。
這樣的形式在項目開發中更為常見,平時很少使用這樣的習慣,但是我們也應當明白如何操作。

首先,我們要理解 頭文件(head.h)的作用:封裝一段具有完整功能的程序,可以直接調用。
頭文件(head.h) 更接近於我們認識的函數聲明,它更多的是告訴我們存在這個函數,並不做實現。

於是我們還需要一個對應的 函數方法實現文件 (head.c),用於將頭文件中的函數聲明進行實現。

舉例:本次文件全部放在同一目錄,如果是使用Dev-C++軟件,需要選擇項目創建的形式/ 如果是VSCode直接放在同一目錄即可。
假設我們的頭文件名為:lib
則 :( lib.h )文件下存放

#ifndef _LIB_H
#define _LIB_H
#define ll long long

ll fastpow(ll a, ll n, ll p); // a^n % p
ll halfpow(ll a, ll n, ll p); // a^n % p

#endif

(lib.c)文件下存放

#include "lib.h"
#define ll long long

ll fastpow(ll a, ll n, ll p){
    ll ans=1;
    while(n){
        if(n&1) ans = ans*a%p;
        a = a*a%p;
        n >>= 1;
    }
    return ans;
}

ll halfpow(ll a, ll n, ll p){
    if(n==0) return 1;
    ll ans = halfpow(a, n/2, p);
    ans = ans*ans%p;
    if(n&1) ans = ans*a%p;
    return ans;
}

主體程序,中存放

#include <stdio.h>
#include <windows.h>
#include "lib.h"
#include "lib.cpp" // vscode不是項目形式需要加上, Dev-C++項目形式不加
#define ll long long

int main(int argc, char** argv) {
    ll a=2, n=10, p=1e7;
    ll ans1 = fastpow(a, n, p);
    ll ans2 = halfpow(a, n, p);
    printf("ans1 = %lld\n", ans1);
    printf("ans2 = %lld\n", ans2);
    system("pause");
    return 0;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM