How to delete the specified line of a file in C++ on CUI condition.

10679 ワード

How to delete the specified line of a file in C++ on CUI condition.
Introduction:
In this article , you’ll learn about two points on file operation. 1. How to delete the specified line of a file. 2.How to replace the specified line of a file.
昨日、ファイルの中で指定された1行(コンソールの下)を削除する方法を聞かれましたが、この問題はGUIの下とCUIの下では少し違うと思います.実験してみましたが、注意すべき点が多いような気がします.だから、心得を整理して、間違いがあれば、指摘してください.
GUIでは、さまざまなコントロールでテキストを編集するときに、車に戻って改行すると2文字「r」が生成されますが、CUIでは私たちが書くフォーマットによって異なります.もちろん、CUIであれば、改行するときは「r」を改行文字にするべきではありません.私たちは完全に1つの「」だけでいいので、余分な文字を無駄にする必要はありません.もちろん、本明細書で指定した行を削除する方法は、「r」改行文字列にも適用されますが、本明細書では主にCUIについて説明します.逆に、指定したローを置き換える方法の適用には多くの制限があります.以下で具体的に説明します.
一:指定された行を削除する
考え方:削除する行の先頭にファイルポインタを位置決めし、その行の長さを算出し、各文字をスペースで置き換える2つの方法です.もう1つは、ファイル全体に1つの文字配列を入力し、文字列として処理し、改行する行の先頭と次の行の先頭を2つの位置に配置し、次の行から最後までのすべての文字を置換する行の先頭に移動します.つまり、上書き法でstrcpyで簡単に実現できます.
分析:最初の方法を使用すると、利点は、ファイル全体を読み込まないことです(通常は、削除する行の次の行を読むだけで、次のコードに解析があります.)また、削除する行の後ろにあるすべてのファイルの内容を全体的に前に移動させる必要はありません.欠点は、本当に削除するかどうかではなく、削除する行の内容をスペースで置き換えてしまうことです.ファイルサイズが小さくならないということです.もちろん、これも致命的な弱点ですが、置き換えがある場合は行の内容の必要性は、それです.2つ目の方法は、指定された行を本当に削除することです.ファイルの内容をすべて1つの文字配列に読み込み、平行移動するため、性能的には1つ目に及ばないが、それは本当に削除されます.また、2つ目の方法は、ファイルの内容を文字列として処理することです.C++ファイルストリーム出力ストリームは、ファイルに文字列を書くときに終了文字'0'を持たないものです.つまり、ファイルを書くときに「0」が表示されなければ、ファイルには「0」はありません.つまり、1つのファイルのすべての文字を1つの文字配列に読み込むと、この配列には「0」はありません.ファイルの内容を読んだ後、文字列処理関数で処理するには、最後に「0」を追加しなければなりません.まず2つ目の方法を実現しましょう
delLine関数:
例文字列:「aaaaabbbbbcccc」
考えてみれば、どのように実現するかを考えてみましょう.もう一つの問題は解決されていません.つまり、行の最初と最後の位置をどのように確定するかです.例えば、今2行目を削除するには、緑で表示された2つの位置を確定しなければなりません.それから、この2つの位置をstrcpyに伝えなければなりません.文字検索関数strchr(文字列ポインタ,')でこの2つの位置を見つけることができます.見つかった場合、関数は''を指すポインタを返します.見つからない場合はNULLを返します.ここでは、最初の行を削除する場合は、最初の''を検索するだけでいいという特例に注意してください.はい、説明します.delLine関数を書きました.原型はvoid delLine(char*pFilepath,int nLine)、1つ目はファイルパス、2つ目は削除する行です.注意してください.この関数を呼び出す前に、必ずそのファイルを開くすべてのストリームを閉じなければなりません.これはシステムファイル共有のポリシーによって決まります.delLineではファイルを読み書きしなければならないので、関数を呼び出す前に、ファイルを書くストリームが閉じられていない場合、delLine関数でファイルを書くときにファイルを開くのは失敗します.システムは複数のユーザーがファイルを書く必要がないためです.コードは次のとおりです.

   
   
   
   
void delLine( char* pFilepath ,  int nLine)

     // Open file
    ifstream file(pFilepath);
     int  i=0;
     // Allocate read buffer. Note: can't more than 1 MB
     char buff[1024*30];
     while(!file.eof()) // Read whole file
        buff[i++]=file. get(); 
    file.close();
    buff[i]='\0';
     char *pLine=buff;
     int j=0;
     // Search newline character '
'

     while(j++ < nLine-1 && pLine)
    {
        pLine=strchr(pLine+1,'
' );
    }
     if(pLine)
    {
         char *pNextLine=strchr(pLine+1,'
' );
         // Cover the line we want to delete.
         if(pNextLine){
             if (nLine==1)
                strcpy(pLine,pNextLine+1);
             else
                strcpy(pLine,pNextLine);
        }
    }
     // we did it , write  the file handled.
    ofstream  out(pFilepath);
    j=0;
    i= strlen(buff);
     while(i--)
         out.put(buff[j++]);
     out.close();
}

では、次にシナリオ1を実現します.シナリオの1つの核心は、行を置き換える長さを決定することです.どのような方法を使いますか.考えてみれば、私は2回連続してgetline関数を呼び出して、getlineを1回も呼び出していないでtellgを呼び出して現在のファイルポインタの文値を得て、それから後の位置で前の位置を減算して、このように1つの長さを得て、この長さは文字列の長さではありませんて、この文字列の“aaaaabbbbbbcccc”を見て、今2行目を置き換えることに参加して、1回目の呼び出しで得られる位置は7、すなわち1回目の「」後の文字位置、すなわち次の行の先頭アドレスであり、2回目の呼び出しgetlineで得られる位置は1回目のcの位置、すなわち14であり、私たちが置き換えるなら5つのbを置き換えるだけで、明らかに14-7-2=5であるべきであり、2回の長さ差をさらに減らさなければならない.また、getlineを2回目に呼び出すとファイルポインタが1行後ろに移動するのでseekg調整ファイルポインタを呼び出さなければなりません.同じように1行目を置き換える場合も特殊で、getlineを1回呼び出すだけで1行目の長さを決定できます.また、置き換える行の文字列は元の行の長さ以上でなければなりません.元の行の長さより大きいと、超えた部分が切り捨てられます.小さい場合は、完全に置き換えることができないので、ヒントを与える必要があります.呼び出し時に渡される新しい文字列は長いほうがいいです.有効な文字の後ろにスペースをたくさん入れることができます.これで万事順調です.コードは次のとおりです.
 

   
   
   
   
void replaceLine(  char* pFilepath ,  int nLine, char * pReplace) 
{
    nLine--;
    fstream file(pFilepath);
     char buff[100];
    fstream::pos_type pos, len;
     int i=0, k=0;
     // if the first line
     if (nLine==0)
    {
        pos=file.tellg();
         if(!file.eof())
            file.getline(buff,100);
        len=file.tellg()-pos; // work out the length of the line we want to delete
        file.seekg(pos); // set the file pointer to the start of the line to be deleted
    }
     // Not first line 
     else{
         while(i++<nLine)
        {
             if(!file.eof())
                file.getline(buff,100);
            pos=file.tellg();
             if(!file.eof())
                file.getline(buff,100);
            len=file.tellg()-pos; // work out the length of the line we want to delete
            file.seekg(pos); // set the file pointer to the start of the line to be deleted
        }
    }

    k=len;
    
     // Note: we assume there is not '\r' before '
', it's depend on the write format of you .

     if(strlen(pReplace)<k-2) 
    {
        printf("Error:new line must be longer than or equal to the original line
");
         return ;
    }
    file.write(pReplace,k-2);
    file.close();
}

では、テストを行います.
1行目をeeeee、2行目をfに置き換えます.この場合、fには1文字しかないので、長さを短くしない原則に基づいて、n個のスペースを補充し、replaceLineの内部で元の行の長さの文字を自動的に切り取り、3行目を削除します.

   
   
   
   
void main(){
     // Create a file
    ofstream  out("now.txt");
     out<<"aaaaa
"<<"bbbbb
"<<"ccccc
"<<"ddddd
";
     out.close();
     // Replace the first line 
     char *pReplace="eeeeeeeeeeeeeee";
    replaceLine("now.txt",1,pReplace);
    pReplace="f                              ";
    replaceLine("now.txt",2,pReplace);
    delLine("now.txt",3);
    ifstream  in("now.txt");
    cout<< in.rdbuf();
}

出力結果は次のとおりです.
eeeee
f
ddddd
もうペンを取るべきですか、それともその言葉ですか.転載コピーはCopyright(c)Duwenと明記してください.原作を支持してください.ありがとうございます.