C - Получение неверных символов после чтения файла и печати в файл, -maybe- Переполнение буфера - PullRequest
0 голосов
/ 26 декабря 2018

У меня есть файл с именами, фамилиями, идентификаторами и адресами электронной почты в произвольном порядке.Я должен организовать эти данные, записать в структуры и в выходной файл, как организовано.Может быть более одного имени и фамилии.Вот пример disordered.txt:

abc@gmail.com Andee Kenny SMITH 1234
ADAM ADAM abc@gmail.com Andeee 21654
Anderea abc@gmail.com SAMMY 3524654
abc@gmail.com Andi BROWN 1245
Andie abc@gmail.com KNOWY 2485
Andra abc@gmail.com BRUCE 52445
Andrea abc@gmail.com 246574 DENNIS
2154 Andreana abc@gmail.com CHASE
Andree 21524 SIERRRA abc@gmail.com
Andrei 154 MONDY abc@gmail.com
4564765 Andria LE BARC abc@gmail.com
78 Andriana abc@gmail.com WALLS

Мой код отлично работает с этими 12 людьми, но если я скопирую и вставлю его много раз или добавлю новых людей, после 33 человек он напечатает недопустимые символы передимена и фамилии повторяются.

Вот снимок экрана: organiz.txt

Я предпочел использовать в своей структуре указатели на символы.

Вот мой код:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define TRUE 1
#define WORD_SIZE 30
#define NAME 1
#define SURNAME 2
#define EMAIL 3
#define ID 4

typedef struct ppl {
    char* name;
    char* surname;
    char* eMail;
    int id;
} PEOPLE;

int whichDataType (char* buffer);
void writeData (PEOPLE* person, char* buffer, int whichData, int* nameTimes, int* surnameTimes, int personNumber);  
void printData (PEOPLE* person, FILE* sptr, int personNumber);

int main (void) {
    FILE* fptr = NULL;

    fptr = fopen("disorganized.txt", "r");
    if (fptr == NULL) {
        printf ("Disorganized file couldn't open\n");
        printf ("Exiting the program\n");
        exit(TRUE);
    }

    FILE* sptr = NULL;

    sptr = fopen("organized.txt", "w");
    if (sptr == NULL) {
        printf ("Organized file couldn't open\n");
        printf ("Exiting the program\n");
        exit(TRUE);
    }

    int whichData;
    int personNumber = 0;
    int* nameTimes;
    int* surnameTimes;
    int forOnce = 0;
    char* buffer;
    int* buffer2;
    PEOPLE* person;

    person = (PEOPLE*) malloc (sizeof(PEOPLE));     
    buffer = (char*) malloc ( WORD_SIZE * sizeof(char));
    nameTimes = (int*) malloc ( sizeof(int));
    surnameTimes = (int*) malloc (sizeof(int));

    *nameTimes = 0;
    *surnameTimes = 0;

    //gets word 'till EOF
    while ((fscanf(fptr, "%s", buffer)) == 1) {
        if (personNumber != 0) {
            //creates new structure
            person = (PEOPLE*) realloc (person, personNumber * sizeof(PEOPLE));
        }
        //looks what type of data
        whichData = whichDataType(buffer);
        //allocates inside of structures and writes
        writeData(person, buffer, whichData, nameTimes, surnameTimes, personNumber);

        buffer2 = (int*) malloc (sizeof(int));
        *buffer2 = fgetc(fptr); //checks what's coming next

        if (*buffer2 == '\n') {
            if (forOnce == 0) {
                //to open a place for next person in my structure pointer, since personNumber = 0; increasing it with 1 and reallocating it with 1*sizeof(PEOPLE) would be the allocating memory for person 1 twice.
                personNumber = personNumber + 2;
                free(buffer2);
                free(buffer);
                buffer = (char*) malloc ( WORD_SIZE * sizeof(char));
                *nameTimes = 0;
                *surnameTimes = 0;
                ++forOnce;
            }
            else {
                ++personNumber;
                free(buffer2);
                free(buffer);
                buffer = (char*) malloc ( WORD_SIZE * sizeof(char));
                *nameTimes = 0;
                *surnameTimes = 0;
            }
        }
        else if (*buffer2 == ' ' || *buffer2 == '\t') {
            free(buffer2);
            free(buffer);
            buffer = (char*) malloc ( WORD_SIZE * sizeof(char));
        }
    }

    --personNumber; //my algorithm increases it 1 more time which is redundant

    printData (person, sptr, personNumber);
    int i;

    for (i = 0; i<personNumber; ++i) {
        free((person+i)->name);
        free((person+i)->surname);
        free((person+i)->eMail);
    }

    free(person);
    free(buffer);
    free(buffer2);
    free(nameTimes);
    free(surnameTimes);

    fclose(fptr);
    fclose(sptr);

    return 0;
}

int whichDataType (char* buffer) {
    if (buffer[0] >= 'A' && buffer[0] <= 'Z') {
        if (buffer[1] >= 'a' && buffer[1] <= 'z') {
            return NAME;
        }
        else if (buffer[1] >= 'A' && buffer[1] <= 'Z') {
            return SURNAME;
        }
    }
    else if (buffer[0] >= 'a' && buffer[0] <= 'z') {
        return EMAIL;
    }
    else if (buffer[0] >= '0' && buffer[0] <= '9') {
        return ID;
    }
} 

void writeData (PEOPLE* person, char* buffer, int whichData, int* nameTimes, int* surnameTimes, int personNumber) {
    if (personNumber != 0) {
        --personNumber;
    }

    switch (whichData) {
    case NAME:
        if (*nameTimes == 0) {
            (person + personNumber)->name = (char*) malloc ( WORD_SIZE * sizeof(char));
            ++(*nameTimes);
        }
        break;

    case SURNAME:
        if (*surnameTimes == 0) {
            (person+personNumber)->surname = (char*) malloc ( WORD_SIZE * sizeof(char));
            ++(*surnameTimes);
        }
        break;

    case EMAIL:
        (person + personNumber)->eMail = (char*) malloc ( WORD_SIZE * sizeof(char));
        break;
    }

    char space[2];
    strcpy(space, " ");

    switch (whichData) {
    case NAME:
        if (*nameTimes == 0) {
            strcpy( (person+personNumber)->name, buffer);
        }
        else {
            strcat ( (person+personNumber)->name, space);
            strcat( (person+personNumber)->name, buffer);
        }
        break;

    case SURNAME:
        if (*surnameTimes == 0) {
            strcpy ( (person+personNumber)->surname, buffer);
        }
        else {
            strcat( (person + personNumber)->surname, space);
            strcat( (person + personNumber)->surname, buffer);
        }
        break;

    case EMAIL:
        strcpy( (person + personNumber)->eMail, buffer);
        break;

    case ID:
        (person+personNumber)->id = atoi(buffer);
        break;
    }

}

void printData (PEOPLE* person, FILE* sptr, int personNumber) {
    fprintf(sptr, "-------------------------------------------------------------------------------------------------------------------------------------------------------------------");
    fprintf(sptr, "\n|%30s\t\t", "***NAME***");
    fprintf(sptr, "|%30s\t\t", "***SURNAME***");
    fprintf(sptr, "|%30s\t\t", "***E-MAIL***");
    fprintf(sptr, "|%30s\t|\n", "***ID NUMBER***");
    fprintf(sptr, "-------------------------------------------------------------------------------------------------------------------------------------------------------------------");

    int i;

    for (i = 0; i<personNumber; ++i) {
        fprintf(sptr, "\n|%d%30s\t\t", i, (person+i)->name);
        fprintf(sptr, "|%30s\t\t", (person+i)->surname);
        fprintf(sptr, "|%30s\t\t", (person+i)->eMail);
        fprintf(sptr, "|%30d\t|\n", (person+i)->id);
        fprintf(sptr, "-------------------------------------------------------------------------------------------------------------------------------------------------------------------");
    }
}

Я пытаюсь malloc каждой новой структуре и внутри нее, освобождать свои буферы после того, как я закончу свою работу с ними, и снова распределять их для следующих.Если для одного человека существует более одного имени или фамилии, я назначаю его имя или фамилию один раз и strcpy мой буфер в соответствующем месте.Если я снова иду к своей функции writeData для имени или фамилии для того же человека, я передаю выделенную память, потому что я уже сделал это.Затем я в основном объединяю свой новый буфер (имя или фамилию) рядом со старым.

Мой вопрос: почему я получаю эти недопустимые символы, где я допустил ошибку и как ее предотвратить?

1 Ответ

0 голосов
/ 28 декабря 2018

Я увидел проблему и решил ее.Возникла проблема с алгоритмом.Когда программа переходит к выделению памяти для имени, чтобы не выделять память снова для строки имени человека, когда речь идет о втором имени, чтобы не потерять первое, я увеличивал nameTimes один раз.Затем при втором переключателе, поскольку это имя, необходимо ввести часть if (*nameTimes == 0) в strcpy.Но так как я уже увеличивал его при выделении, он никогда не входил в эту часть и всегда использовал strcat для копирования строки.Но не было последовательности для объединения, что вызывало проблемы.Я изменил состояние этой части на if (*nameTimes == 1).Затем возникла вторая проблема, которая заключалась в том, что она просто печатала фамилию только потому, что я не увеличивала ее снова, поэтому она застряла на strcpy части.Так что я увеличил его снова после strcpy.То же самое касается фамилии.Я также улучшил код благодаря @Barmar и @ user3629249.

| Новый код |

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define WORD_SIZE 30
#define NAME 1
#define SURNAME 2
#define EMAIL 3
#define ID 4


typedef struct ppl {

    char* name;
    char* surname;
    char* eMail;
    int id;

} PEOPLE;

int whichDataType (char* buffer);
void writeData (PEOPLE* person, char* buffer, int whichData, int* nameTimes, int* surnameTimes, int personNumber);  
void printData (PEOPLE* person, FILE* sptr, int personNumber);

int main (void) {

    FILE* fptr = NULL;

    fptr = fopen("disorganized.txt", "r");
    if (fptr == NULL) {

        perror("Error: ");
        exit( EXIT_FAILURE );
    }

    FILE* sptr = NULL;

    sptr = fopen("organized.txt", "w");
    if (sptr == NULL) {

        perror("Error: ");
        exit( EXIT_FAILURE );
    }



    int whichData;
    int personNumber = 0;
    int nameTimes = 0;
    int surnameTimes = 0;
    int forOnce = 0;
    char* buffer = NULL;
    int* buffer2 = NULL;
    PEOPLE* person = NULL;
    PEOPLE* realloctemp = NULL;



    person = malloc (sizeof(PEOPLE));
    if ( person == NULL ) {

        perror("Error, malloc failed for person. ");
        exit ( EXIT_FAILURE );
    }

    buffer = malloc ( WORD_SIZE * sizeof(char));
    if ( buffer == NULL ) {

        perror("Error, malloc failed for buffer. ");
        exit ( EXIT_FAILURE );
    }


    while ((fscanf(fptr, "%29s", buffer)) == 1) {

        if (personNumber != 0) {

            realloctemp = realloc (person, personNumber * sizeof(PEOPLE));
            if ( realloctemp == NULL ) {

                perror("Error, reallocating. ");
                exit ( EXIT_FAILURE );
            }

            else {

                person = realloctemp;
            }

        }

        whichData = whichDataType(buffer);

        writeData(person, buffer, whichData, &nameTimes, &surnameTimes, personNumber);

        buffer2 = malloc (sizeof(int));
        if ( buffer2 == NULL ) {

            perror("Error, malloc failed for buffer2. ");
            exit ( EXIT_FAILURE );
        }

        else {

            *buffer2 = fgetc(fptr);
        }

        if (*buffer2 == '\n') {

            if (forOnce == 0) {

                personNumber = personNumber + 2;
                free(buffer2);
                free(buffer);

                buffer = malloc ( WORD_SIZE * sizeof(char));
                if ( buffer == NULL ) {

                    perror("Error*, malloc failed for buffer. ");
                    exit ( EXIT_FAILURE );
                }

                nameTimes = 0;
                surnameTimes = 0;

                ++forOnce;

            }

            else {

                ++personNumber;
                free(buffer2);
                free(buffer);

                buffer = malloc ( WORD_SIZE * sizeof(char));
                if ( buffer == NULL ) {

                    perror("Error**, malloc failed for buffer. ");
                    exit ( EXIT_FAILURE );
                }

                nameTimes = 0;
                surnameTimes = 0;

            }

        }

        else if (*buffer2 == ' ' || *buffer2 == '\t') {

            free(buffer2);
            free(buffer);
            buffer = malloc ( WORD_SIZE * sizeof(char));
            if ( buffer == NULL ) {

                perror("Error***, malloc failed for buffer. ");
                exit ( EXIT_FAILURE );
            }

        }
    }

    --personNumber;

    printData (person, sptr, personNumber);

    int i;

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

        free((person+i)->name);
        free((person+i)->surname);
        free((person+i)->eMail);

    }

    free(person);
    free(buffer);
    free(buffer2);

    fclose(fptr);
    fclose(sptr);

    return EXIT_SUCCESS;
}

int whichDataType (char* buffer) {

    if (buffer[0] >= 'A' && buffer[0] <= 'Z') {

        if (buffer[1] >= 'a' && buffer[1] <= 'z') {

            return NAME;
        }

        else if (buffer[1] >= 'A' && buffer[1] <= 'Z') {

            return SURNAME;
        }
    }

    else if (buffer[0] >= 'a' && buffer[0] <= 'z') {

        return EMAIL;
    }

    else if (buffer[0] >= '0' && buffer[0] <= '9') {

        return ID;
    }

    else {

        perror("Invalid data type. ");
        exit( EXIT_FAILURE );

    }

} 

void writeData (PEOPLE* person, char* buffer, int whichData, int* nameTimes, int* surnameTimes, int personNumber) {

    if (personNumber != 0) {

        --personNumber;
    }

    switch (whichData) {

        case NAME:

            if (*nameTimes == 0) {

                (person + personNumber)->name = malloc ( WORD_SIZE * sizeof(char));
                if ( (person+personNumber)->name == NULL ) {

                    perror("Error. malloc failed for (person+personNumber)->name");
                    exit ( EXIT_FAILURE );
                }

                ++(*nameTimes);
            }

            break;

        case SURNAME:

            if (*surnameTimes == 0) {

                (person+personNumber)->surname = malloc ( WORD_SIZE * sizeof(char));
                if ( (person+personNumber)->surname == NULL ) {

                    perror("Error. malloc failed for (person+personNumber)->surname");
                    exit ( EXIT_FAILURE );
                }

                ++(*surnameTimes);
            }

            break;

        case EMAIL:

            (person + personNumber)->eMail = malloc ( WORD_SIZE * sizeof(char));
            if ( (person+personNumber)->eMail == NULL ) {

                perror("Error. malloc failed for (person+personNumber)->eMail");
                exit ( EXIT_FAILURE );
            }

            break;
    }


    char space[2];
    strcpy(space, " ");


    switch (whichData) {

        case NAME:

            if (*nameTimes == 1) {

                strcpy( (person+personNumber)->name, buffer);
                ++(*nameTimes);
            }

            else if (*nameTimes>1) {

                strcat ( (person+personNumber)->name, space);
                strcat( (person+personNumber)->name, buffer);
            }

            else {

                perror("Error, invalid nameTimes value. ");
                exit ( EXIT_FAILURE );
            }

            break;

        case SURNAME:

            if (*surnameTimes == 1) {

                strcpy ( (person+personNumber)->surname, buffer);
                ++(*surnameTimes);
            }

            else if (*surnameTimes>1) {


                strcat( (person + personNumber)->surname, space);
                strcat( (person + personNumber)->surname, buffer);

            }

            else {

                perror("Error, invalid surnameTimes value. ");
                exit ( EXIT_FAILURE );
            }

            break;

        case EMAIL:

            strcpy( (person + personNumber)->eMail, buffer);

            break;

        case ID:

            (person+personNumber)->id = atoi(buffer);

            break;

    }


}

void printData (PEOPLE* person, FILE* sptr, int personNumber) {

    fprintf(sptr, "-------------------------------------------------------------------------------------------------------------------------------------------------------------------");
    fprintf(sptr, "\n|%30s\t\t", "***NAME***");
    fprintf(sptr, "|%30s\t\t", "***SURNAME***");
    fprintf(sptr, "|%30s\t\t", "***E-MAIL***");
    fprintf(sptr, "|%30s\t|\n", "***ID NUMBER***");
    fprintf(sptr, "-------------------------------------------------------------------------------------------------------------------------------------------------------------------");

    int i;

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

        fprintf(sptr, "\n|%d%30s\t\t", i+1, (person+i)->name);
        fprintf(sptr, "|%30s\t\t", (person+i)->surname);
        fprintf(sptr, "|%30s\t\t", (person+i)->eMail);
        fprintf(sptr, "|%30d\t|\n", (person+i)->id);
        fprintf(sptr, "-------------------------------------------------------------------------------------------------------------------------------------------------------------------");
    }

}
...