0

I want to capitalise every other word in poem.txt, starting from each line. I made a function capitalise() that receives a string (eg: "a lonely number like root three"), capitalises every other word and returns it (eg: returns "A lonely Number like Root three" ). I'm trying to read each line from poem.txt, send that line to capitalise() and then receive the updated string and replace that line with the updated string but I can't figure out how. I tested my program, it can read the contents of the file and send them to capitalise() and display line by line but it can't write and replace each line. I tried using fprintf() but it's not working. Can you guys enlighten me?

poem.txt(before execution)
i fear that I will always be
a lonely number like root three
the three is all that’s good and right,
why must my three keep out of sight
beneath the vicious square root sign,
I wish instead I were a nine
for nine could thwart this evil trick,
with just some quick arithmetic
i know I’ll never see the sun, as 1.7321
such is my reality, a sad irrationality
when hark! What is this I see,
another square root of a three
has quietly come waltzing by,
together now we multiply
to form a number we prefer,
rejoicing as an integer
we break free from our mortal bonds
with the wave of magic wands
our square root signs become unglued
your love for me has been renewed

Code:

#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 (after execution):
i fear that I will always be
I fear That I Will always Be
ee
Ee
three is all that’s good and right,
three Is all That’s good And right,
eath the vicious square root sign,
Eath the Vicious square Root sign,
ne could thwart this evil trick,
Ne could Thwart this Evil trick,
know I’ll never see the sun, as 1.7321
know I’ll never See the Sun, as 1.7321
en hark! What is this I see,
En hark! What is This I See,
e
E
s quietly come waltzing by,
S quietly Come waltzing By,
form a number we prefer,
Form a Number we Prefer,
e break free from our mortal bonds
E break Free from Our mortal Bonds
uare root signs become unglued
Uare root Signs become Unglued
edEd

poem.txt(expected execution):
I fear That I Will always Be
A lonely Number like Root three
...

1
  • You need fseek and ftell. save position by ftell before read. read line. set position by fseek and save position before write. Commented Nov 24, 2016 at 23:49

3 Answers 3

2

You can do it it in-place, but it is dangerous, you might loose data if something fails.

A slightly simplified version would be

#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);
}
Sign up to request clarification or add additional context in comments.

Comments

2

The line duplication happens because you are writing to the original file while also reading it.

It turns out that deleting and editing lines from a file can be quite difficult. If you want to edit lines in a file, one easy solution is to write to a new temporary file, rename it to the original file, and delete the temporary file.

Comments

0

if I remember correctly, you should be able to rewrite the content for the file since it already exist with the flag "w". Replace your "r+" with "w"

4 Comments

I think I only cleared up the first part of deleting the existing data so you can rewrite
I just tried an example using "w+". I created a file and then wrote a small program to overwrite the contents and it did.
I noticed that w+ works for small examples too. But when I tried it on my program, it just cleared the contents of the file.
Ah, yeah. I just tried it with yours and it did the same thing. But I saw someone gave a good answer above. Hopefully that works.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.