цикл while только для чтения, первая строка из файла - PullRequest
0 голосов
/ 21 января 2019

Добро пожаловать, у меня проблема с циклом while. Он читает только первую строку из файла file.txt. Перед добавлением функции для разделения моей строки по strtok_r мои приложения не работают должным образом. Целью этого цикла while является чтение всей строки из файла и разделение строки на единицу с помощью "|" и эти части добавить в соответствующие вкладки. Что я должен делать? Это мой код:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <mem.h>
#include <assert.h>

struct movie {
    char title[100];
    int year;
    char genre[100];
};

int i = 0;
struct movie *movies[50];



int porownaj(struct movie* first, struct movie* second)
{
    if(first->year==second->year){
            if(first->title>second->title){
                return 1;
            }
            if(first->title<second->title){
                return -1;
            }
            if(first->title==second->title){
                    if(first->genre>second->genre){
                        return 1;
                    }
                    if(first->genre<second->genre){
                        return -1;
                    }
                    if(first->genre==second->genre){
                        return 0;
                    }
            }
    }
    if(first->year>second->year){
        return 1;
    }
    if(first->year<second->year){
        return -1;
    }

    if(first->title==second->title){
        if(first->year>second->year){
                return 1;
            }
            if(first->year<second->year){
                return -1;
            }
            if(first->year==second->year){
                    if(first->genre>second->genre){
                        return 1;
                    }
                    if(first->genre<second->genre){
                        return -1;
                    }
                    if(first->genre==second->genre){
                        return 0;
                    }
            }
    }
    if(first->title>second->title){
        return 1;
    }
    if(first->title<second->title){
        return -1;
    }

    if(first->genre==second->genre){
        if(first->year>second->year){
                return 1;
            }
            if(first->year<second->year){
                return -1;
            }
            if(first->year==second->year){
                    if(first->title>second->title){
                        return 1;
                    }
                    if(first->title<second->title){
                        return -1;
                    }
                    if(first->title==second->title){
                        return 0;
                    }
            }
    }
    if(first->genre>second->genre){
        return 1;
    }
    if(first->genre<second->genre){
        return -1;
    }

}


void zamien(struct movie* movies[50], int x, int y)
{
    struct movie* tmpMovie = movies[x];
    movies[x] = movies[y];
    movies[y] = tmpMovie;
}

int main()
{

    struct movie *movies[50];
    do
    {
        printf("\n");
        printf("Projekt nr 6 \n");
        printf("\n");
        printf("\b   MENU GLOWNE \n");
        printf("|-----------------| \n");
        printf("[1]Baza filmow \n");
        printf("[2]Dodaj film \n");
        printf("[3]Zakoncz Program \n");
        printf("|-----------------| \n");

        char znak;

        printf("Wybierz opcje z menu: ");
        scanf("%s", &znak);

        system("cls");

        switch (znak)
        {
        case '1':
            system("cls");
            printf("Wybrales opcje BAZA FILMOW \n");
            printf("TYTUL | ROK |  GATUNEK\n");
            printf("----------------------\n");

            FILE *baza;
            if ((baza = fopen("movies.txt", "r")) == NULL)
            {
                system("cls");
                printf("Blad otwarcia pliku\n");
                exit(1);
            }

            char tekst[512];

            char *title    = NULL;
            char *year     = NULL;
            char *genre    = NULL;

            char *buffer  = NULL;
            int x         = 0;

            while (fgets(tekst, 512, baza) != NULL)
            {
                printf("%s", tekst);

                title   = strtok_r(tekst, "|", &buffer);
                assert(title != NULL);
                strcpy(movies[x]->title, title);

                year     = strtok_r(NULL, "|", &buffer);
                assert(year != NULL);
                movies[x]->year = atoi(year);

                genre = strtok_r(NULL, "|", &buffer);
                assert(genre != NULL);
                strcpy(movies[x]->genre, genre);

                x++;


            }fclose(baza);


            do
            {
                printf("\n[1]Sortuj wg. tytulu");
                printf("\n[2]Sortuj wg. roku produkcji");
                printf("\n[3]Sortuj wg. gatunku filmu");
                printf("\n[4]Wroc do glownego menu\n");
                printf("|-----------------|\n");

                char click;

                printf("\nWybierz opcje: ");

                scanf("%s", &click);

                switch (click)
                {
                case '1':
                    system("cls");
                    printf("Sorotowanie wg. tytulu");
/*
                    for(int i=0;i<10-1;i++){
                                for(int j=0;j<10-i-1;j++){
                                    if(porownaj(&title[j],&title[j+1])>0){
                                        zamien(&title[j],&title[j+1]);
                                    }
                                }
                            }
                                for(int i=0;i<10;i++){
                                    printf("(%d, %d)", title[i].x, );
                                }
*/
                    break;
                case '2':
                    system("cls");
                    printf("Sorotowanie wg. roku produkcji");
/*
                    for(int i=0;i<10-1;i++){
                                for(int j=0;j<10-i-1;j++){
                                    if(porownaj(&year[j],&year[j+1])>0){
                                        zamien(&year[j],&year[j+1]);
                                    }
                                }
                            }
                                for(int i=0;i<10;i++){
                                    printf("(%d, %d)", year[i].x, );
                                }
*/
                    break;
                case '3':
                    system("cls");
                    printf("Sorotowanie wg. gatunku filmu");

                    break;
                case '4':
                    system("cls");
                    return main();
                default:
                    system("cls");
                    printf("Nie ma takiej opcji. Program sie wylaczy!");
                    return 0;
                }
            } while (1);

        case '2':
            system("cls");
            printf("Wybrales opcje DODAJ FILM \n");

            movies[i] = malloc(sizeof(movie));

            printf("Podaj nazwe filmu: ");
            while ((getchar()) != '\n');
            gets(movies[i]->title);

            printf("Podaj rok produkcji: ");
            scanf("%d", &(movies[i]->year));

            printf("Podaj gatunek filmu: ");
            while ((getchar()) != '\n');

            gets(movies[i]->genre);

            fflush(stdin);

            FILE *plik = fopen("movies.txt", "a+");
            fprintf(plik, "%s | %d | %s \n", movies[i]->title, movies[i]->year, movies[i]->genre);
            fclose(plik);
            i++;
            printf("Zapisane..");
            continue;
        case '3':
            system("cls");
            printf("ZAKONCZ PROGRAM \n");
            return 0;
        default:
            printf("Nie ma takiej opcji! \n");
            return main();
        }
        }while (1);

return (0);
}

movies.txt:

Title | 1234 | Scifi
Title_2 | 4321 | SciFI

Ответы [ 3 ]

0 голосов
/ 21 января 2019

Могу поспорить, что каждая строка напечатана с printf("%s", tekst);.

Но вы забываете, что strtok делает не копирование строки. Таким образом (если у вас назначения исправлены наоборот), вы все равно назначаете указатели в одну и ту же переменную tekst для всех ваших фильмов. Вместо этого выделите память и скопируйте строки:

    title   = strtok_r(tekst, "|", &buffer);
    movies[x]->title= malloc(strlen(title)+1);
    strcpy(movies[x]->title, title);

и то же самое для других строковых переменных.

0 голосов
/ 21 января 2019

В вашей программе есть несколько ошибок.

Для начала:

        char title    = NULL;
        char year     = NULL;
        char genre    = NULL;

вместе с этим:

        title   = strtok_r(tekst, "|", &buffer);
        year     = strtok_r(NULL, "|", &buffer);
        genre = strtok_r(NULL, "|", &buffer);
        int year = atoi(year);

Вы определяете title как char, но strtok_r возвращает char*. Следовательно, вы перезаписываете память, сохраняя «указатель на символ» в переменной «символ». Это может уничтожить файл-указатель. Полученная ошибка 0xC0000005 (как вы упоминаете в комментарии) может указывать на то, что:

Ошибка приложения 0xc0000005 (нарушение прав доступа) обычно вызывается тем, что ваш компьютер не может правильно обработать файлы ...

Измените определение на:

        char *title    = NULL;
        char *year     = NULL;
        char *genre    = NULL;

Далее:

        year     = strtok_r(NULL, "|", &buffer);  // A variable named year
        genre = strtok_r(NULL, "|", &buffer);
        int year = atoi(year);                    // A NEW variable with same name!!

Измените его на:

        year     = strtok_r(NULL, "|", &buffer);
        genre = strtok_r(NULL, "|", &buffer);
        int yearN = atoi(year);                // Use another name

Кроме того, перед вызовом atoi

всегда следует проверять, что year равно , а не NULL.

Поэтому я предлагаю упростить ваш код для отладки. Попробуйте:

        FILE *baza;
        if ((baza = fopen("movies.txt", "r")) == NULL)
        {
            system("cls");
            printf("Blad otwarcia pliku\n");
            exit(1);
        }

        char tekst[512];
        char* title    = NULL;
        char* year     = NULL;
        char* genre    = NULL;
        char* buffer  = NULL;
        int x         = 0;
    printf("while-loop start\n");
    while (fgets(tekst, 512, baza) != NULL)
    {
        printf("%s", tekst);
        //x++;

        //title   = strtok_r(tekst, "|", &buffer);
        //year     = strtok_r(NULL, "|", &buffer);
        //genre = strtok_r(NULL, "|", &buffer);
        //int year = atoi(year);

        //title=movies[x]->title;
        //year=movies[x]->year;
        //genre=movies[x]->genre;

    }
    printf("while-loop complete\n");

Теперь проверьте вывод, полученный из этого кода. Если это работает, как ожидалось, вы можете начать комментировать строки один за другим.

В конце концов, я думаю, что ваша функция должна выглядеть так:

        FILE *baza;
        if ((baza = fopen("movies.txt", "r")) == NULL)
        {
            system("cls");
            printf("Blad otwarcia pliku\n");
            exit(1);
        }

        char tekst[512];
        char* title    = NULL;
        char* year     = NULL;
        char* genre    = NULL;
        char* buffer  = NULL;
        int x         = 0;

    while (fgets(tekst, 512, baza) != NULL)
    {
        printf("%s", tekst);

        title   = strtok_r(tekst, "|", &buffer);
        assert(title != NULL);
        strcpy(movies[x]->title, title);            

        year     = strtok_r(NULL, "|", &buffer);
        assert(year != NULL);
        movies[x]->year = atoi(year);

        genre = strtok_r(NULL, "|", &buffer);
        assert(genre != NULL);
        strcpy(movies[x]->genre, genre);            

        x++;
    }

Выше предполагается, что вы уже выделили память для всех указателей в movies. Как:

struct movie { char title[100]; int year; char genre[100]; }; 

int main() {
    int i = 0; 
    struct movie *movies[50];
    for(i=0; i<50; ++i) movies[i] = malloc(sizeof *movies);
    . . .
0 голосов
/ 21 января 2019

из любых других возможных проблем эти строки проблематичны:

    title=movies[x]->title;
    year=movies[x]->year;
    genre=movies[x]->genre;
  • как сказано в замечании, назначения должны быть отменены (movies[x]->foo = foo;)
  • вам нужно продублировать строки, иначе вы сохраните подадреса текст , который изменяет каждый цикл и может исчезнуть, когда вы будете их использовать

так

    movies[x]->title = strdup(title);
    movies[x]->year = year;
    movies[x]->genre = strdup(genre);

Или, если movies[x]->title и movies[x]->genre являются char[], а не char*, код должен копировать, а не дублировать:

    strcpy(movies[x]->title, title);
    movies[x]->year = year;
    strcpy(movies[x]->genre, genre);

и при необходимости замените strcpy на strncpy , чтобы не переполнять

...