C语言 如何从C中的文本文件中删除特定行?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20716785/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 10:31:45  来源:igfitidea点击:

How do I delete a specific line from text file in C?

c

提问by Hansen Derrick

Example:

例子:

George 50 40
Lime 30 20
Karen 10 60

乔治 50 40
莱姆 30 20
凯伦 10 60

do {
    printf("\nInput player name:[1..10] ");
    fgets(name,10,stdin);
}

Input name: Lime

输入名称:石灰

Then the text file will be:

然后文本文件将是:

George 50 40
Karen 10 60

乔治 50 40
凯伦 10 60

回答by user3115056

Try this:

尝试这个:

 /* C Program Delete a specific Line from a Text File
 */
#include <stdio.h>

int main()
{
    FILE *fileptr1, *fileptr2;
    char filename[40];
    char ch;
    int delete_line, temp = 1;

    printf("Enter file name: ");
    scanf("%s", filename);
    //open file in read mode
    fileptr1 = fopen(filename, "r");
    ch = getc(fileptr1);
   while (ch != EOF)
    {
        printf("%c", ch);
        ch = getc(fileptr1);
    }
    //rewind
    rewind(fileptr1);
    printf(" \n Enter line number of the line to be deleted:");
    scanf("%d", &delete_line);
    //open new file in write mode
    fileptr2 = fopen("replica.c", "w");
    ch = 'A';
    while (ch != EOF)
    {
        ch = getc(fileptr1);
        //except the line to be deleted
        if (temp != delete_line)
        {
            //copy all lines in file replica.c
            putc(ch, fileptr2);
        }
        if (ch == '\n')
        {
            temp++;
        }
    }
    fclose(fileptr1);
    fclose(fileptr2);
    remove(filename);
    //rename the file replica.c to original name
    rename("replica.c", filename);
    printf("\n The contents of file after being modified are as follows:\n");
    fileptr1 = fopen(filename, "r");
    ch = getc(fileptr1);
    while (ch != EOF)
    {
        printf("%c", ch);
        ch = getc(fileptr1);
    }
    fclose(fileptr1);
    return 0;
}

Reference - http://www.sanfoundry.com/c-program-delete-line-text-file/

参考 - http://www.sanfoundry.com/c-program-delete-line-text-file/

回答by AndersK

There are several ways you can delete a line, one simple method is to open two files, one in and one out.

有几种方法可以删除一行,一种简单的方法是打开两个文件,一个进一个出。

then copy line by line and skip the line you want to delete after you are done, delete the old file and rename the new one to the old name.

然后逐行复制,完成后跳过要删除的行,删除旧文件并将新文件重命名为旧名称。

fopen()
fgets()
fputs()
rename()
unlink()

EDIT: the above solution would work fine with a small file but as by comment it is not suitable for a large file so here comes an alternative solution (GCC C99) which reads in the whole file, finds the name then moves the lines after that line forward in the buffer.

编辑:上述解决方案适用于小文件,但根据注释,它不适用于大文件,因此这里有一个替代解决方案(GCC C99),它读取整个文件,找到名称然后在此之后移动行在缓冲区中向前行。

#include <stdio.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <stdbool.h>

static size_t deleteLine( char*, size_t, const char* );

int main(int argc, char* argv[])
{
  char file[] = "yourfile.txt";

  if ( --argc )
  { 
    struct stat st;
    if ( stat( file, &st ) != -1 )
    {
      // open the file in binary format
      FILE* fp = fopen( file, "rb" );
      if ( fp != NULL )
      {
        // allocate memory to hold file
        char* buffer = malloc( st.st_size ); 

        // read the file into a buffer
        if ( fread(buffer, 1, st.st_size, fp) == st.st_size)
        {
          fclose(fp);

          size_t newSize = deleteLine( buffer, st.st_size, argv[1] );

          fp = fopen( file, "wb" );
          if ( fp != NULL )
          {
            fwrite(buffer, 1, newSize, fp);
            fclose(fp);
          }
          else
          {
            perror(file);
          }
        }
        free(buffer);
      }
      else
      {
        perror(file);
      }
    }
    else
    {
      printf( "did not find %s", file );
    }
  }
  return 0;
}

static size_t deleteLine( char* buffer, size_t size, const char* playerName )
{
  // file format assumed to be as specified in the question i.e. name{space}somevalue{space}someothervalue\n
  // find playerName
  char* p = buffer; 
  bool done = false;
  size_t len = strlen(playerName);
  size_t newSize = 0;
  do
  {
    char* q = strchr( p, *playerName ); // look for first letter in playerName
    if ( q != NULL )
    {
      if ( strncmp( q, playerName, len ) == 0 ) // found name?
      {
        size_t lineSize = 1; // include \n already in line size

        // count number of characters the line has.
        for ( char* line = q; *line != '\n'; ++line) 
        {
          ++lineSize;
        }

        // calculate length left after line by subtracting offsets
        size_t restSize = (size_t)((buffer + size) - (q + lineSize));

        // move block with next line forward
        memmove( q, q + lineSize, restSize );

        // calculate new size
        newSize = size - lineSize;
        done = true;
      }
      else
      {
        p = q + 1; // continue search
      }
    }
    else
    {
      puts( "no such name" );
      done = true;
    }
  }
  while (!done);

  return newSize;
}

回答by Sagar Bhatt

You don't need to create a new file. You can open the original file with r+and store its contents into an array (following these steps). Then you can use a for loop to scan the array for the line you want to skip, and delete that line. Then you can overwrite the contents of the file using fseek(filename,0,SEEK_SET)(to reset the position indicator of the file) and using a for loop and fprintf to copy the contents from the modified array to the file. (However, with this method you will need to enter an extra blank line in the last for loop to overwrite the last line of the original file.)

您无需创建新文件。您可以打开原始文件r+并将其内容存储到一个数组中(按照这些步骤)。然后您可以使用 for 循环扫描数组中要跳过的行,并删除该行。然后,您可以使用fseek(filename,0,SEEK_SET)(重置文件的位置指示符)并使用 for 循环和 fprintf 将内容从修改后的数组复制到文件中来覆盖文件的内容。(但是,使用此方法,您需要在最后一个 for 循环中输入一个额外的空行以覆盖原始文件的最后一行。)