Stream corrupts when being saved

0

I have the algorithm that simulates a type of register, but when I save the file the fields, street, city and state are lost, they simply disappear, and as I am saving it it corrupts the file already at the time of writing. I can not figure out why this is happening. This case is very specific, it only happens after inserting two elements or more, and saving the struct , if I do not save it the fields remain unchanged, I imagine that's why it is in the "save_text" function but I'm still not sure, so I'm posting all code:

/* 
 * File:   main.c
 * Author: pmargreff
 *
 * Created on 6 de Novembro de 2014, 00:25
 */
#include <stdio.h>
#include <stdlib.h>
#define MAX 100

struct end {
    char nome[100];
    char rua[100];
    char cidade[100];
    char estado[100];
    unsigned long int cep;
} *info;

/*
 * struct para conseguir comparar 
 * dois nomes em diversas funções
 */
struct compara {
    char nome[100];
} busca;

int flag = 0; // flag sinaliza é ativada quando o cadastro é acessado pela primeira vez
int tam = 0; //cria uma váriavel para que guardar o tamanho do vetor
void cria_lista(void);
void insere(void);
void apaga(void);
void pesquisa(void);
void imprime(void);
int menu(void);
int livre(void);
int busca_nome(void);
void ler_string(char palavra[100], int tamanho);
void salva_texto(void);
void le_texto(void);

int main(void) {
    int escolha;
    cria_lista();
    for (;;) {
        escolha = menu();
        switch (escolha) {
            case 1: insere();
                break;
            case 2: apaga();
                break;
            case 3: imprime();
                break;
            case 4: pesquisa();
                break;
            case 5: salva_texto();
                break;
            case 6: le_texto();
                break;
            default: return 0;
                break;
        }
    }
}

//aloca o suficiente para uma váriavel e armazena /0 na mesma

void cria_lista(void) {
    info = malloc(sizeof (struct end));
}

int menu(void) {
    int c = 0;
    do {
        printf("-- MENU:\n");
        printf("\t 1. Inserir um nome\n");
        printf("\t 2. Excluir um nome\n");
        printf("\t 3. Listar o arquivo\n");
        printf("\t 4. Pesquisar um nome\n");
        printf("\t 5. Salvar em arquivo\n");
        printf("\t 6. Abrir arquivo\n");
        printf("\t 7. Sair\n");
        printf("-- Digite sua escolha: ");
        scanf("%d", &c);
    } while (c <= 0 || c > 8);
    getchar();
    return c;
}

void ler_string(char palavra[100], int tamanho) {
    int i = 0;
    char c;
    c = getchar();
    while ((c != '\n') && (i < tamanho)) {
        palavra[i++] = c;
        c = getchar();
    }
    palavra[i] = '
/* 
 * File:   main.c
 * Author: pmargreff
 *
 * Created on 6 de Novembro de 2014, 00:25
 */
#include <stdio.h>
#include <stdlib.h>
#define MAX 100

struct end {
    char nome[100];
    char rua[100];
    char cidade[100];
    char estado[100];
    unsigned long int cep;
} *info;

/*
 * struct para conseguir comparar 
 * dois nomes em diversas funções
 */
struct compara {
    char nome[100];
} busca;

int flag = 0; // flag sinaliza é ativada quando o cadastro é acessado pela primeira vez
int tam = 0; //cria uma váriavel para que guardar o tamanho do vetor
void cria_lista(void);
void insere(void);
void apaga(void);
void pesquisa(void);
void imprime(void);
int menu(void);
int livre(void);
int busca_nome(void);
void ler_string(char palavra[100], int tamanho);
void salva_texto(void);
void le_texto(void);

int main(void) {
    int escolha;
    cria_lista();
    for (;;) {
        escolha = menu();
        switch (escolha) {
            case 1: insere();
                break;
            case 2: apaga();
                break;
            case 3: imprime();
                break;
            case 4: pesquisa();
                break;
            case 5: salva_texto();
                break;
            case 6: le_texto();
                break;
            default: return 0;
                break;
        }
    }
}

//aloca o suficiente para uma váriavel e armazena /0 na mesma

void cria_lista(void) {
    info = malloc(sizeof (struct end));
}

int menu(void) {
    int c = 0;
    do {
        printf("-- MENU:\n");
        printf("\t 1. Inserir um nome\n");
        printf("\t 2. Excluir um nome\n");
        printf("\t 3. Listar o arquivo\n");
        printf("\t 4. Pesquisar um nome\n");
        printf("\t 5. Salvar em arquivo\n");
        printf("\t 6. Abrir arquivo\n");
        printf("\t 7. Sair\n");
        printf("-- Digite sua escolha: ");
        scanf("%d", &c);
    } while (c <= 0 || c > 8);
    getchar();
    return c;
}

void ler_string(char palavra[100], int tamanho) {
    int i = 0;
    char c;
    c = getchar();
    while ((c != '\n') && (i < tamanho)) {
        palavra[i++] = c;
        c = getchar();
    }
    palavra[i] = '%pre%';
    if (c != '\n') {
        c = getchar();
        while ((c != '\n') && (c != EOF)) {
            c = getchar();
        }
    }
}

void insere(void) {

    int aux;
    int posicao = tam;


    if (flag == 1) {
        printf("-- Registro %d:\n", posicao + 1);
    } else {
        printf("-- Registro %d:\n", posicao);
    }
    printf("\t Nome: ");
    ler_string(busca.nome, 30);

    aux = busca_nome(); /*confere se já existe nome */
    if (aux != -1) { /*caso exista apenas volta ao menu anterior */
        return;
    }


    /*
     * quando a flag está ativa, aloca memória de acordo com o número de vezes que passa no vetor
     */
    if (flag == 1) {
        info = realloc(info, 1);
        tam++;
        posicao = tam;
    }

    strcpy(info[posicao].nome, busca.nome);
    printf("\t Rua: ");
    ler_string(info[posicao].rua, 40);
    printf("\t Cidade: ");
    ler_string(info[posicao].cidade, 20);
    printf("\t Estado: ");
    ler_string(info[posicao].estado, 2);
    printf("\t CEP: ");
    scanf("%lu", &info[posicao].cep);

    flag = 1; //ativa a flag
}

/*
 * percorre o vetor e se encontra alguma posição livre
 * devolve o indice dessa posição de memória, caso contrário
 * apenas retorna -1
 */
int livre(void) {
    int i;
    for (i = 0; i <= tam; i++) {
        if (info[i].nome[0] == '%pre%')
            return i;
    }
    return -1;
}

/*
 * chama a funçao busca_nome que retorna o indice
 * para a variavel posicão que devera ser apagado
 * se nenhum nome igual for encontrado retorna -1
 */
void apaga(void) {
    int posicao;
    int confirma;
    ler_string(busca.nome, 30);
    posicao = busca_nome();
    if (posicao >= 0 && posicao < tam) {
        printf("Você realmente deseja apagar %s?\n0-não\n1-sim", info[posicao].nome);
        scanf("%d", &confirma);
        if (confirma == 1) {
            info[posicao] = info[tam];
            tam--;
        }
    }
}

void imprime(void) {
    int i;
    for (i = 0; i <= tam; i++)
        if (info[i].nome[0] != '%pre%') {
            printf("-- Registro %d:\n", i);
            printf("\t Nome: %s", info[i].nome);
            printf("\t Rua: %s", info[i].rua);
            printf("\t Cidade: %s", info[i].cidade);
            printf("\t Estado: %s\n", info[i].estado);
            printf("\t CEP: %lu\n", info[i].cep);
        }
}

/*
 * função que faz a busca de um nome no programa
 * le o nome que está localizado na struct busca.nome
 * e retorna o indice se encontrar nome igual ou
 * -1 se não encontrar nome como aquele
 */
int busca_nome(void) {
    int i;
    for (i = 0; i <= tam; i++) {
        if (strcmp(busca.nome, info[i].nome) == 0) {
            return i;
        }
    }
    return -1;
}

/* função para procurar e exibir apenas o nome desejado
 * chama o função busca_nome que devolve o indice para 
 * a variavel i se for válido e se não existir devolve 
 * menos um, o a exibição só é feita quando o indice é 
 * diferente de menos um e menor que o máximo pré estabelecido
 */
void pesquisa(void) {
    int i;
    ler_string(busca.nome, 30);
    i = busca_nome();
    if (i >= 0 && i <= tam) {
        printf("-- Registro %d:\n", i);
        printf("\t Nome: %s", info[i].nome);
        printf("\t Rua: %s", info[i].rua);
        printf("\t Cidade: %s", info[i].cidade);
        printf("\t Estado: %s\n", info[i].estado);
        printf("\t CEP: %lu\n", info[i].cep);
    } else {
        printf("Nome não encontrado na lista!! \n\n");
    }
}
/*
void salva_bin(void) {
    FILE *arquivo;
    int i;

    arquivo = fopen("dados.bin", "w");

    for (i = 0; i <= tam; i++) {
        fwrite(&i, sizeof (int), 1, arquivo);
        fwrite(&info[i], sizeof (struct end), 1, arquivo);
    }
    //fwrite(&info, MAX*sizeof(struct end), 1, arquivo);
    fclose(arquivo);

}

void abre_arq(void) {
    FILE *arquivo;
    int i;

    arquivo = fopen("dados.bin", "r");

    while (!feof(arquivo)) {
        fread(&i, sizeof (int), 1, arquivo);
        fread(&info[i], sizeof (struct end), 1, arquivo);
    }
    tam = i;
    //fread(&info, MAX*sizeof(struct end), 1, arquivo);
    fclose(arquivo);
}
*/

void salva_texto() {
    FILE *arquivo;
    int i;

    arquivo = fopen("dados.txt", "w");

    for (i = 0; i <= tam; i++) {

        fprintf(arquivo, "%d\n", i);
        fprintf(arquivo, "%s\n", info[i].nome);
        fprintf(arquivo, "%s\n", info[i].rua);
        fprintf(arquivo, "%s\n", info[i].cidade);
        fprintf(arquivo, "%s\n", info[i].estado);
        fprintf(arquivo, "%lu\n", info[i].cep);
    }
    fclose(arquivo);
}

void le_texto() {
    FILE *arquivo;
    int i;

    arquivo = fopen("dados.txt", "r");

    while (!feof(arquivo)) {
        fscanf(arquivo, "%d", &i);
        fscanf(arquivo, "%[^\n]%*c", info[i].nome);
        fscanf(arquivo, "%[^\n]%*c", info[i].rua);
        fscanf(arquivo, "%[^\n]%*c", info[i].cidade);
        fscanf(arquivo, "%[^\n]%*c", info[i].estado);
        fscanf(arquivo, "%lu", &info[i].cep);
    }
    fclose(arquivo);
}
'; if (c != '\n') { c = getchar(); while ((c != '\n') && (c != EOF)) { c = getchar(); } } } void insere(void) { int aux; int posicao = tam; if (flag == 1) { printf("-- Registro %d:\n", posicao + 1); } else { printf("-- Registro %d:\n", posicao); } printf("\t Nome: "); ler_string(busca.nome, 30); aux = busca_nome(); /*confere se já existe nome */ if (aux != -1) { /*caso exista apenas volta ao menu anterior */ return; } /* * quando a flag está ativa, aloca memória de acordo com o número de vezes que passa no vetor */ if (flag == 1) { info = realloc(info, 1); tam++; posicao = tam; } strcpy(info[posicao].nome, busca.nome); printf("\t Rua: "); ler_string(info[posicao].rua, 40); printf("\t Cidade: "); ler_string(info[posicao].cidade, 20); printf("\t Estado: "); ler_string(info[posicao].estado, 2); printf("\t CEP: "); scanf("%lu", &info[posicao].cep); flag = 1; //ativa a flag } /* * percorre o vetor e se encontra alguma posição livre * devolve o indice dessa posição de memória, caso contrário * apenas retorna -1 */ int livre(void) { int i; for (i = 0; i <= tam; i++) { if (info[i].nome[0] == '%pre%') return i; } return -1; } /* * chama a funçao busca_nome que retorna o indice * para a variavel posicão que devera ser apagado * se nenhum nome igual for encontrado retorna -1 */ void apaga(void) { int posicao; int confirma; ler_string(busca.nome, 30); posicao = busca_nome(); if (posicao >= 0 && posicao < tam) { printf("Você realmente deseja apagar %s?\n0-não\n1-sim", info[posicao].nome); scanf("%d", &confirma); if (confirma == 1) { info[posicao] = info[tam]; tam--; } } } void imprime(void) { int i; for (i = 0; i <= tam; i++) if (info[i].nome[0] != '%pre%') { printf("-- Registro %d:\n", i); printf("\t Nome: %s", info[i].nome); printf("\t Rua: %s", info[i].rua); printf("\t Cidade: %s", info[i].cidade); printf("\t Estado: %s\n", info[i].estado); printf("\t CEP: %lu\n", info[i].cep); } } /* * função que faz a busca de um nome no programa * le o nome que está localizado na struct busca.nome * e retorna o indice se encontrar nome igual ou * -1 se não encontrar nome como aquele */ int busca_nome(void) { int i; for (i = 0; i <= tam; i++) { if (strcmp(busca.nome, info[i].nome) == 0) { return i; } } return -1; } /* função para procurar e exibir apenas o nome desejado * chama o função busca_nome que devolve o indice para * a variavel i se for válido e se não existir devolve * menos um, o a exibição só é feita quando o indice é * diferente de menos um e menor que o máximo pré estabelecido */ void pesquisa(void) { int i; ler_string(busca.nome, 30); i = busca_nome(); if (i >= 0 && i <= tam) { printf("-- Registro %d:\n", i); printf("\t Nome: %s", info[i].nome); printf("\t Rua: %s", info[i].rua); printf("\t Cidade: %s", info[i].cidade); printf("\t Estado: %s\n", info[i].estado); printf("\t CEP: %lu\n", info[i].cep); } else { printf("Nome não encontrado na lista!! \n\n"); } } /* void salva_bin(void) { FILE *arquivo; int i; arquivo = fopen("dados.bin", "w"); for (i = 0; i <= tam; i++) { fwrite(&i, sizeof (int), 1, arquivo); fwrite(&info[i], sizeof (struct end), 1, arquivo); } //fwrite(&info, MAX*sizeof(struct end), 1, arquivo); fclose(arquivo); } void abre_arq(void) { FILE *arquivo; int i; arquivo = fopen("dados.bin", "r"); while (!feof(arquivo)) { fread(&i, sizeof (int), 1, arquivo); fread(&info[i], sizeof (struct end), 1, arquivo); } tam = i; //fread(&info, MAX*sizeof(struct end), 1, arquivo); fclose(arquivo); } */ void salva_texto() { FILE *arquivo; int i; arquivo = fopen("dados.txt", "w"); for (i = 0; i <= tam; i++) { fprintf(arquivo, "%d\n", i); fprintf(arquivo, "%s\n", info[i].nome); fprintf(arquivo, "%s\n", info[i].rua); fprintf(arquivo, "%s\n", info[i].cidade); fprintf(arquivo, "%s\n", info[i].estado); fprintf(arquivo, "%lu\n", info[i].cep); } fclose(arquivo); } void le_texto() { FILE *arquivo; int i; arquivo = fopen("dados.txt", "r"); while (!feof(arquivo)) { fscanf(arquivo, "%d", &i); fscanf(arquivo, "%[^\n]%*c", info[i].nome); fscanf(arquivo, "%[^\n]%*c", info[i].rua); fscanf(arquivo, "%[^\n]%*c", info[i].cidade); fscanf(arquivo, "%[^\n]%*c", info[i].estado); fscanf(arquivo, "%lu", &info[i].cep); } fclose(arquivo); }
    
asked by anonymous 26.11.2014 / 04:55

1 answer

2
    info = realloc(info, 1);

This line causes info to point to a 1-byte memory space, which is not sufficient for multiple objects of type struct end .

You need to know how many elements you need (possibly one more than before calling the function) and make realloc based on that.

    struct end *tmp = realloc(info, NElems * sizeof *info);
    if (!tmp) {
        /* erro de memoria */
    }
    info = tmp; /* info aponta para um espaço capaz de guardar NElems objectos */
    
26.11.2014 / 11:27