How to delete the last line of a text file in C language

Asked

Viewed 822 times

2

Guys, I’m having a question about how I should delete the last line of a file using the C language. Could someone please help me.

Below, follow my code.

int quantidadeDeUsuarios = 0;
Usuario *_usuario;



void sair() {
    free(_usuario);
}

void removerUltimoNumero() {

    FILE *arquivo;

    char *linha = (char *) malloc(256 * sizeof(char));
    char *buffer = (char *) malloc(1000 * sizeof(char));
    char *ponteiro;

    memset(buffer, 0, 1000 * sizeof(char));
    ponteiro = buffer;

    arquivo = fopen("usuarios", "r");

    if(arquivo == NULL) {
        cout << "Erro na abertura do arquivo" << endl;
        return;
    }

    while(!feof(arquivo)) {

        fgets(linha, 256, arquivo);

        if(sizeof(linha) == true) {
            strcpy(ponteiro, linha);
            ponteiro += strlen(linha);
        }
    }

    fclose(arquivo);
    rescreveArquivo(arquivo, buffer);
    free(linha);
    free(buffer);
}

void rescreveArquivo(FILE *arquivo, const char *buffer) {
    arquivo = fopen("usuarios", "w");
    fprintf(arquivo, "%s", buffer);
    fclose(arquivo);
}

void numeroDeUsuariosCadastrados() {
    cout << "Número de usuários cadastrados: " << contadorDeLinhasDeUmArquivo() << endl;
}

int contadorDeLinhasDeUmArquivo() {

    FILE *arquivo;
    int numeroDeLinhas = 0;

    arquivo = fopen("usuarios", "r");

    if(arquivo == NULL) {
        cout << "Erro na abertura do arquivo" << endl;
        return 0;
    }

    while(EOF != (scanf("%*[^\n]") && scanf("%*c"))) {
        ++numeroDeLinhas;
    }

    return numeroDeLinhas;
}

void listarUsuarios() {

    char *saida = (char *) malloc(256 * sizeof(char));
    char espaco = ' ';

    FILE *arquivo = fopen("usuarios", "r");

    if(arquivo == NULL) {
        cout << "Erro na Abertura do arquivo" << endl;
        return;
    }

    cout << "=========================================================================================================================================================" << endl;
    printf("| Nome %-25c | RG %-27c | CPF %-26c | Endereço %-41c |\n", espaco, espaco, espaco, espaco);
    cout << "=========================================================================================================================================================" << endl;

    for (int i = 1; fgets(saida, sizeof(saida), arquivo) != NULL; ++i) {
        printf("%s", saida);
    }

    cout << endl << endl;

    fclose(arquivo);

}

void cadastrarUsuario() {

    Usuario *usuario;

    usuario = _usuario;

    if(quantidadeDeUsuarios > 0) usuario = (Usuario *) realloc(usuario, quantidadeDeUsuarios * sizeof(Usuario));
    else usuario = (Usuario *) malloc(sizeof(Usuario));

    if(!usuario) {
        cout << "Exaustão de memória!" << endl;
        exit(1);
    }

    __fpurge(stdin);
    cin.clear();
    cout << "Digite seu nome: ";
    cin.getline(usuario[quantidadeDeUsuarios].nome, 100);

    __fpurge(stdin);
    cin.clear();
    cout << "Digite seu RG: ";
    cin.getline(usuario[quantidadeDeUsuarios].rg, 9);

    __fpurge(stdin);
    cin.clear();
    cout << "Digite seu CPF: ";
    cin.getline(usuario[quantidadeDeUsuarios].cpf, 11);

    __fpurge(stdin);
    cin.clear();
    cout << "Digite seu Endereço: ";
    cin.getline(usuario[quantidadeDeUsuarios].endereco, 100);

    _usuario = usuario;

    insereUsuario(_usuario);

    quantidadeDeUsuarios++;

}

void insereUsuario(Usuario *pUsuario) {

    FILE * arquivo;

    if((arquivo = fopen("usuarios", "a+")) == NULL) {
        cout << "Erro ao criar o arquivo";
    }

    fprintf(arquivo, "| %-30s | %-30s | %-30s | %-50s |\n",
            pUsuario->nome,
            pUsuario->rg,
            pUsuario->cpf,
            pUsuario->endereco
    );

    fclose(arquivo);

}
  • There’s so much wrong or bad in this code that I don’t know where to start (nor have I looked beyond what’s in the window). Will you decide whether to do it in C or C++? Can you guarantee that the line has 256 characters? I don’t think so, right? If I put all the code I might be able to do something, but I can’t promise because I don’t have a C compiler here to test.

  • https://github.com/codenome/Lista0-EstruturaDeDados/tree/master/Exericicio%207%20(MISSING%20FUN%C3%87%C3%83O%20DE%20EXCLUIR)/users Archive This is the project link! https://github.com/codenome/Lista0-EstruturaDeDados/blob/master/Exericicio%207%20(MISSING%20FUN%C3%87%C3%83O%20DE%20EXCLUIR)/users!

  • Another thing... I’m doing in C same... but in front of the teacher will use C++.

2 answers

1


I was able to solve the problem by taking the data from a text file to a dynamic allocation. Then I treated the location pointer by writing the data in the same file.

void removerUltimoUsuario() {

FILE *arquivo = fopen("usuarios.csv", "r");

if(arquivo == NULL) {
    cout << "Erro ao criar o arquivo" << endl;
}

Usuario *usuarios = (Usuario *) malloc(numeroDeUsuarios() * sizeof(Usuario));

char linha[500];
int i = 0;
for(; fgets(linha, 500, arquivo); i++) {
    linha[strlen(linha) - 1] = '\0';
    sscanf(linha, "%[^;];%[^;];%[^;];%[^;];",
           usuarios[i].nome,
           usuarios[i].rg,
           usuarios[i].cpf,
           usuarios[i].endereco
    );
}
cout << "N: " << i << endl;
fclose(arquivo);
insereUsuarios(usuarios, i);
free(usuarios);

cout << "Usuário removido com sucesso!" << endl;
}




void insereUsuarios(Usuario *pUsuario, int numUsuarios) {

FILE * arquivo;

if((arquivo = fopen("usuarios.csv", "w")) == NULL) {
    cout << "Erro ao criar o arquivo";
}

cout << "N: " << numUsuarios << endl;

for(int i = 0; i < (numUsuarios-1); i++) {
    fprintf(arquivo, "%s;%s;%s;%s\n",
            pUsuario[i].nome,
            pUsuario[i].rg,
            pUsuario[i].cpf,
            pUsuario[i].endereco
    );
}

fclose(arquivo);
}

0

It has a very simple form using its function that already counts the number of lines in the file. But first, I want to make it clear that I have not reviewed or tested your code. I will only leave a theoretical solution that is up to you to implement. Come on.

  1. First create an output file.
  2. Now having in hand the created output file and the number of lines of the original file, copy line by line from the original file to the output one.
  3. When arriving at the last line(which you want to delete) just ignore, ie do not copy it to the output file.
  4. You now have 2 files, the original and the output file. Rename or delete the original file and keep the output file as the "new original".

I think this solution is not the most recommended one. But as far as I have read your code, this is the best way to make the least impact on its implementation.

NOTE: Do not forget to treat all errors during this process. This will ensure that your output file is intact as you expected.

  • Thank you Carlos Givisiez! I will perform this procedure!

  • For nothing @Thiagocunha , comment when you have tested! I look forward.

  • I managed to solve the problem! I’ll leave in the comments below.

Browser other questions tagged

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