Inversion of each line of a C file

Asked

Viewed 70 times

5

I am trying to make a program that basically indents each line of a text file in reverse order, that is, the line is shown from the end to the beginning. For example, the line 'hello world! ' is shown as '!dlrow olleh'

So far I’ve got this code made:

#define _GNU_SOURCE
#define ERR_IO 1

#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <assert.h>
#include <stdint.h>

#include "debug.h"
#include "memory.h"
#include "invert_line_file.h"

void invert_line_file(char *filename){

    FILE *fptr = NULL;
    fptr = fopen(filename, "r");    

    if (fptr==NULL){
        ERROR(1, "Erro ao abrir o ficheiro %s", filename);
    }

    int cont=0;
    char *line=NULL;
    size_t line_size=0;
    int i=0, j=0;
    int size;

    printf("\nFile '%s'", filename);
    while (getline(&line, &line_size, fptr)!=-1){
        size=strlen(line);
        while((size_t)i<strlen(line)){
            for (i=0 ; (line[i]!='\0') ; i++){
                for (j=0; j<i; j++){
                    char tmp = line[j];
                    line[j] = line[size-1-j];
                    line[size-1-j] = tmp;
                }
            }
            i++;
        }
        i=0;
        j=0;
        cont++;
        printf("\n%x: '%s'", cont, line);
    }

    if (!feof(fptr)){
        ERROR(1, "Erro ao ler do ficheiro %s", filename);
    }
}

My problem is that for example with a file (data.txt) with the following content:

Gabriel
Joao
Pedro
Rui
Andre
Joni
Goncalo
Ana
Silvia
Maria

The output at the end of running the program is:

File 'data.txt'
1: '
leirbaG'
2: 'Joao
'
3: '
ordeP'
4: '
iuR'
5: '
erdnA'
6: 'Joni
'
7: '
olacnoG'
8: '
anA'
9: 'Silvia
'
a: '
airaM'

1 answer

3


Its inversion of the string is too complex:

while((size_t)i<strlen(line)){
    for (i=0 ; (line[i]!='\0') ; i++){
        for (j=0; j<i; j++){
            char tmp = line[j];
            line[j] = line[size-1-j];
            line[size-1-j] = tmp;
        }
    }
    i++;
}
i=0;
j=0;

You have 3 loops to do an inversion. To be honest I couldn’t even notice exactly how you got to these 3 loops because only 1 solves your problem:

for (i = 0, j = size-1; i < size/2; ++i, j--){
    char tmp = line[j];
    line[j] = line[size-1-j];
    line[size-1-j] = tmp;
}

Note that I go half a string and change directly with the corresponding character from the end. I also did not put the i and j to 0 for the for takes care to initialize these two variables with the relevant values.

The other problem has to do with the line break that was left in the string when you read it with getline. That gives that Enter the more you see on the way out. You can solve this problem well by looking for the \n that there is putting the terminator in that same location:

line[strcspn(line,"\n")] = '\0';

The function strcspn finds the position of a given string in a string and returns it. If nothing is found, returns the string size.

This would have to be applied before the reversal, passing your code from the while(getline..) to be:

while (getline(&line, &line_size, fptr)!=-1){
    line[strcspn(line,"\n")] = '\0';
    size=strlen(line);

    for (i = 0, j = size-1; i < size/2; ++i, j--){
        char tmp = line[j];
        line[j] = line[size-1-j];
        line[size-1-j] = tmp;
    }
    cont++;
    printf("\n%x: '%s'", cont, line);
}

With these two amendments you already have the solution you want:

File 'data.txt'
1: 'leirbaG'
2: 'oaoJ'
3: 'ordeP'
4: 'iuR'
5: 'erdnA'
6: 'inoJ'
7: 'olacnoG'
8: 'anA'
9: 'aivliS'
a: 'airaM'

Browser other questions tagged

You are not signed in. Login or sign up in order to post.