【问题标题】:Replace each line in a text file using C使用 C 替换文本文件中的每一行
【发布时间】:2016-11-24 23:35:46
【问题描述】:

我想将poem.txt 中的其他单词大写,从每一行开始。我创建了一个函数 capitalise() 接收一个字符串(例如:“一个孤独的数字,如根三”),将每个其他单词大写并返回它(例如:返回“一个孤独的数字,如根三”)。我正在尝试从诗歌.txt 中读取每一行,将该行发送到 capitalise() 然后接收更新的字符串并用更新的字符串替换该行,但我不知道如何。我测试了我的程序,它可以读取文件的内容并将它们发送到 capitalise() 并逐行显示,但它不能写入和替换每一行。我尝试使用 fprintf() 但它不起作用。各位大神能指教一下吗?

poem.txt(执行前)
我害怕我会永远
一个孤独的数字,如根三
这三个就是好的和正确的,
为什么我的三个必须躲在视线之外
在邪恶的平方根标志下,
我希望我是九岁
因为九个可以阻止这个邪恶的把戏,
只需一些快速算术
我知道我永远不会看到太阳,就像 1.7321
这就是我的现实,可悲的非理性
听的时候!我看到的这是什么
三的另一个平方根
悄悄地走过华尔兹,
现在我们一起相乘
形成一个我们喜欢的数字,
高兴为整数
我们挣脱了凡人的束缚
随着魔杖的挥动
我们的平方根标志脱胶了
你对我的爱又更新了

代码:

#define _GNU_SOURCE
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>

int reverse(int otherWord)
{
    if (otherWord)
        return 0;
    else
        return 1;
}
void capitalise(char *s)
{
     int start = 1;
     int otherWord = 1;
     for (; *s; s++)
     {
            if (start && otherWord)
                *s = toupper(*s);
            start = isspace(*s);
            if (start)
                otherWord = reverse(otherWord);

     }
}
int main(int argc, char *argv[])
{
    FILE * fp;
    char * line = NULL;
    size_t len = 0;
    ssize_t read;

    fp = fopen("poem.txt", "r+");
    if (fp == NULL)
        exit(EXIT_FAILURE);

    while ((read = getline(&line, &len, fp)) != -1) {
        capitalise(line);
        fprintf(fp, "%s", line); // Here's the problem, this line!

    }

    fclose(fp);
    if (line)
        free(line);
    exit(EXIT_SUCCESS);
}

poem.txt(执行后):
我害怕我会永远
我害怕我将永远是
ee

三是好的和正确的,
三 一切都好 对了,
吃掉邪恶的平方根符号,
吃掉邪恶的平方根标志,
无法阻止这个邪恶的诡计,
Ne可以阻止这个邪恶的把戏,
知道我永远不会看到太阳,如 1.7321
知道我永远见不到太阳,如 1.7321
听!我看到的这是什么
听!我看到的是什么,
e

s悄悄地走过华尔兹,
S静静地来华尔兹经过,
形成我们喜欢的数字,
形成我们喜欢的数字,
e挣脱我们凡人的束缚
E 摆脱我们凡人的束缚
uare根标志脱胶
Uare 根标志脱胶
编辑

poem.txt(预期执行):
我害怕我将永远是
一个孤独的数字,如根三
...

【问题讨论】:

  • 您需要fseekftell。阅读前通过ftell保存位置。读线。通过fseek 设置位置并在写入前保存位置。

标签: c


【解决方案1】:

可以就地进行,但这很危险,如果出现故障,您可能会丢失数据。

稍微简化的版本是

#define _GNU_SOURCE
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>

int reverse(int otherWord)
{
  if (otherWord) {
    return 0;
  } else {
    return 1;
  }
}

void capitalise(char *s)
{
  int start = 1;
  int otherWord = 1;
  for (; *s; s++) {
    if (start && otherWord) {
      *s = toupper(*s);
    }
    start = isspace(*s);
    if (start) {
      otherWord = reverse(otherWord);
    }
  }
}

int main(void)
{
  FILE *fp;
  char *line = NULL;
  size_t len = 0;
  ssize_t read;
  long offset = 0L;
  int res;
  // you might prefer "w+" instead
  fp = fopen("poem.txt", "r+");
  if (fp == NULL) {
    fprintf(stderr, "Opening file poem.txt failed\n");
    exit(EXIT_FAILURE);
  }

  while ((read = getline(&line, &len, fp)) != -1) {
    capitalise(line);
    // set position relative to start of file
    if ((res = fseek(fp, offset, SEEK_SET)) < 0) {
      fprintf(stderr, "fseek failed\n");
      exit(EXIT_FAILURE);
    }
    // printing line sets file pointer to end of line
    fprintf(fp, "%s", line);
    // get that position
    offset = ftell(fp);
  }
  // fclose() might fail, too, see man-page for details
  fclose(fp);
  if (line) {
    free(line);
  }
  exit(EXIT_SUCCESS);
}

【讨论】:

    【解决方案2】:

    发生行重复是因为您在写入原始文件的同时也在读取它。

    事实证明,从文件中删除和编辑行可能非常困难。如果要编辑文件中的行,一种简单的解决方案是写入新的临时文件,将其重命名为原始文件,然后删除临时文件。

    【讨论】:

      【解决方案3】:

      如果我没记错的话,你应该能够重写文件的内容,因为它已经存在带有“w”标志。用“w”替换你的“r+”

      【讨论】:

      • 我想我只是清除了删除现有数据的第一部分,以便您可以重写
      • 我刚刚尝试了一个使用“w+”的示例。我创建了一个文件,然后编写了一个小程序来覆盖内容,它确实做到了。
      • 我注意到 w+ 也适用于小例子。但是当我在我的程序上尝试它时,它只是清除了文件的内容。
      • 啊,是的。我刚刚用你的试了一下,它做了同样的事情。但是我看到有人在上面给出了一个很好的答案。希望这行得通。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-02
      • 2012-03-19
      • 2017-12-20
      • 1970-01-01
      相关资源
      最近更新 更多