首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何从C中的文本文件中删除特定行?

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

Stack Overflow用户
提问于 2013-12-21 07:42:24
回答 4查看 78.6K关注 0票数 10

示例:

乔治50 40 石灰30 20 凯伦10 60

代码语言:javascript
运行
复制
do {
    printf("\nInput player name:[1..10] ");
    fgets(name,10,stdin);
}

输入名称:石灰

然后,文本文件将是:

乔治50 40 凯伦10 60

EN

回答 4

Stack Overflow用户

发布于 2013-12-21 07:47:06

试试这个:

代码语言:javascript
运行
复制
 /* 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;
}

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

票数 4
EN

Stack Overflow用户

发布于 2013-12-21 08:16:47

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

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

代码语言:javascript
运行
复制
fopen()
fgets()
fputs()
rename()
unlink()

编辑:上面的解决方案在一个小文件中可以很好地工作,但是由于注释它不适合一个大文件,所以这里有一个替代解决方案(GCC C99),它读取整个文件,找到名称,然后在缓冲区中向前移动行后面的行。

代码语言:javascript
运行
复制
#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;
}
票数 4
EN

Stack Overflow用户

发布于 2021-08-27 07:59:24

考虑一个类似数组的文件。如果我们想删除数组索引I处的元素,那么将所有元素从i+1移到左边一步,然后逻辑上减小数组的大小。

我在文件上应用了同样的打印程序。最后,ftruncate()用于缩小文件的大小,因此删除file.This代码的结尾部分对于大型文件也很好,因为在任何时候只有一个字节存储在内存中。

代码语言:javascript
运行
复制
#include<errno.h>
#include<unistd.h>
#include<stdio.h>
/*
 * Description: fdelete() deletes 'bytes' bytes of data from the stream pointed to by fp. 
 *              bytes will be deleted from the CURRENT FILE POSITION.
 *              File must be opened in read + write mode while passing file pointer 
 *              to this function.
 *              File position before calling the function and after the 
 *              function returns will be the same.
 * Return Values: returns 0 on success and errno on failure. Kindly use perror("") 
 *                to print error if non-0 return value returned.
 */
int fdelete(FILE* fp, int bytes) {
    
    // to store each byte/char from file
    char byte;
    long readPos = ftell(fp) + bytes, writePos = ftell(fp), startingPos = writePos;
    // start reading from the position which comes after the bytes to be deleted
    fseek(fp, readPos, SEEK_SET);
    while (fread(&byte, sizeof(byte), 1, fp)) {
        // modify readPos as we have read right now
        readPos = ftell(fp);
        // set file position to writePos as we are going to write now
        fseek(fp, writePos, SEEK_SET);
        
        // if file doesn't have write permission
        if (fwrite(&byte, sizeof(byte), 1, fp) == 0) 
            return errno;
        // modify writePos as we have written right now
        writePos = ftell(fp);
        // set file position for reading
        fseek(fp, readPos, SEEK_SET);
    }

    // truncate file size to remove the unnecessary ending bytes
    ftruncate(fileno(fp), writePos);
    // reset file position to the same position that we got when function was called.
    fseek(fp, startingPos, SEEK_SET); 
    return 0;
}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/20716785

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档