1. Здраво и добредојдовте на форумот на IT.mk.

    Доколку сеуште не сте дел од најголемата заедница на ИТ професионалци и ентузијасти во Македонија, можете бесплатно да се - процесот нема да ви одземе повеќе од 2-3 минути, а за полесна регистрација овозможивме и регистрирање со Facebook и Steam.
    Сокриј

Читање на фајл линија по линија?

Дискусија во форумот 'C // C++' започната од Ivica_M, 1 Февруари 2009.

  1. Ivica_M

    Ivica_M
    Intern

    226
    3
    3 oктомври 2008
    Стигнав со учењето до датотеки па сакам да направам квиз.

    Дали некој знае како може да се чита фајл ама само една линија (прашањето) од фајлот после да се бара да се внесе одговорот. Е сега дали да направам друга датотека каде што ќе бидат одговорите и да се чита само ама да не се печати иншто туку кога ќе се внесе одговорот само да се спореди дали е исто? ако е оди на следно прашање и додади 1 поен. Ако одговорот не е точен печати дека одговорот не е точен и прикажи колку поени се освоени.

    Со овој код се чита се од датотеката:
    string line;
    ifstream input("prasanja.dat");
    if(input.is_open())
    {

    while(!input.eof())
    {
    getline(input, line);
    cout << line << endl;
    }
    input.close();
    }
    else
    cout << "Unable to open file!" << endl;

    system("pause");
    return 0;

    Сега како да направам да се чита само една линија и после од кога ќе се внесе одговорот да се чита друга итн?
     
  2. Spion

    Spion
    Intern

    48
    4
    25 Септември 2007
    Направи го квизот таков да биде првата линија прашање, наредната одговор, третата прашање, четвртата одговор и така натаму. Потоа, читај по 2 линии на секој чекор во циклусот. Останатото треба да е лесно :)
     
  3. MetalGear

    MetalGear
    On your way to fame

    2,993
    504
    14 Април 2007
    Машко
    може на неколку начини да се направи
    на крај на секоја линија да имаш некој знак
    и да чита карактер по карактер се додека не дојде до тој знак

    може да се изведе и нешто како karakter!= '\n'
    \n е нов ред
     
  4. Ivica_M

    Ivica_M
    Intern

    226
    3
    3 oктомври 2008
    Ама проблемот е што не знам како се чита само една линија, а после друга. Некој код за ова?
     
  5. Spion

    Spion
    Intern

    48
    4
    25 Септември 2007
    Па мислам дека е прилично логично:
    getline(input, ednalinija);
    getline(input, drugalinija);
     
  6. MetalGear

    MetalGear
    On your way to fame

    2,993
    504
    14 Април 2007
    Машко
    ивица
    на крај на секоја линија ке ставиш по некој карактер
    и ке читаш карактер по карактер се додека не дојдеш до тој карактер што значи си дошол до дај на линијата

    или пак да пробаш со услов
    karakter!= '\n'
     
  7. Ivica_M

    Ivica_M
    Intern

    226
    3
    3 oктомври 2008
    А како да ја одредам првата линија со број не може пробав вака:
    getline(input, 1);

    пробав и вака:
    string line[3];
    ...
    getline(input, line[1]);

    и вака не може не знам како да се означат линиите зошто пред секое прашање во датотеката имам ставено број пример:
    1 прашање еден?
    2 прашање два?
    итн.
     
  8. Spion

    Spion
    Intern

    48
    4
    25 Септември 2007
    Има одреден начин на размислување по кој вообичаено (би требало да) одиш кога решаваш ваков проблем (кога сам ја дизајнираш и датотеката и програмата). Ќе го илустрирам на твојот пример.

    Значи, сакаме квиз програмче.

    На каков начин ќе работи?
    Ќе му поставува прашања на корисникот.
    Од каде ќе ги најде тие прашања?
    Од датотека.
    Од каде ќе ги најде одговорите на прашањата?
    (Точка 1 за која немаме одговор: каде да бидат сместени одговорите на прашањата)

    дигресија: секој пат кога незнаеме нешто го сместуваме на листа на непознати работи и продолжуваме понатаму

    добро, а што друго треба да прави програмчето?
    Да собира поени за корисникот.
    До кога?
    Додека корисникот не даде погрешен одговор.
    Што треба да прави кога ќе даде погрешен одговор?
    Да престане да чита прашања, да му покаже на корисникот колку поени има.
    Потоа завршува?
    Да.

    Сесија 2 - што знаеме (за да го решиме проблемот 1)
    Како знаеме да читаме од датотека?
    Линија по линија.
    Поедноставно ни е 2 датотеки или една?
    Една ако е можно.
    Како читаме линии од датотека?
    Во циклус.
    А што ако два пати во циклусот ја повикаме функцијата за читање линија?
    Ќе прочитаме 2 линии.
    Како може тоа да ни помогне за проблемот?
    Ако читаме по 2 линии одеднаш, во едната може да се наоѓа прашањето а во другата одговорот.
    Дали е поедноставно ако не користиме array?
    Поедноставно е.
    Зошто немораме да користиме array?
    Бидејќи нема зошто да ги памтиме прашањата за кои веќе е даден одговор, доволно е да ги памтиме само поените.
    Ако несакаме корисникот да гледа броеви на прашања, дали мора во датотеката да ги има броевите на прашања?
    Немора.
    Дали вака ни е поедноставена работата?
    Да, немора да најдеме начин да ги отстраниме броевите на прашањата од прочитаната линија (а тие не ни требаат бидејќи не користиме array)

    Сесија 3: правење на помал проблем

    Кој помал проблем го дефинира проблемот што сакаме да го решиме со ова програмче?
    Во каква смисла помал
    Во смисла на сличност и едноставност?
    Проблемот со едно прашање и еден одговор.
    Детален опис?
    - Корисникот добива едно прашање прочитано од датотека со 2 линии
    - Корисникот внесува одговор
    - Ја читаме наредната линија од датотеката, таа ни е точниот одговор
    - Го споредуваме точниот одговор со одговорот на корисникот
    - Ако е точен одговорот му даваме 1 поен.
    - Ако не е точен му велиме дека има 0 поени, крај.

    Циклус 3: проширување

    Што треба да смениме во едноставниот проблем за да стане опис на посложениот проблем?
    Треба да изградиме циклус.
    Што ќе се прави сосема исто внатре во циклусот споредбено со едноставниот проблем?
    Читањето на две линии одеднаш.
    Што треба да е различно?
    Однесувањето при даден точен одговор - се зголемува бројот на поени, меѓутоа не завршува програмот.
    А при даден погрешен одговор?
    И при тоа - циклусот треба да се прекине.
    Што треба да се направи при даден точен одговор?
    Наместо да се додели само еден поен, треба да се зголеми бројот на поени на корисникот.
    Дали тоа значи дека бројот на поени треба да се постави на 0 пред циклусот?
    Да.
    Што треба да биде надвор од циклусот?
    Па, бидејќи излегуваме од циклусот при даден погрешен одговор, можеме да му кажеме на корисникот колку поени добил веднаш после циклусот.

    Циклус 4: екстра размислувања кои немора да ги има, меѓутоа се nice-to-have ако сакаме да го менуваме програмот потоа:
    Дали е лесно изменувањето на програмот...
    Што ако несакаме да прекинеме да поставуваме прашања кога корисникот ќе згреши?
    Немора да излегуваме од циклусот.
    Нема потреба друго да се менува?
    Нема.
    Што ќе биде крајниот резултат?
    Корисникот ќе ги добие своите поени откако ќе даде одговори на сите прашања.
    Треба ли да се менува датотеката за оваа смена?
    Не треба.

    ---
    Размислувањево е многу долго затоа што е дадено во форма прашање и одговор, обично кога го мислиш наједноставно е (ако е можно за конкретниот проблем) да "испробаш" неколку варијанти и да ја одбереш наједноставната што ти изгледа возможна за имплементирање.

    Се извинувам за неверојатно долгиот пост :p
     
  9. Ivica_M

    Ivica_M
    Intern

    226
    3
    3 oктомври 2008
    Добро објаснување мислам дека така е најдобро во една датотека да бидат прашањата и одговорите прво прашањето па под него одговорот сепак фала за постот :D ама се уште не знам да читам само една линија од датотека :(
     
  10. Ivica_M

    Ivica_M
    Intern

    226
    3
    3 oктомври 2008
    Најдов нешто ама не работи не дава ништо

    ifstream dat;
    int a;
    char tekst[20];
    dat.open(ime);
    dat >> a >> tekst;
     
  11. MetalGear

    MetalGear
    On your way to fame

    2,993
    504
    14 Април 2007
    Машко
    ивица прво ти препорачувам да фатиш некоја книга или нешто слично за датотеки во ц++ да научиш
     
  12. Ivica_M

    Ivica_M
    Intern

    226
    3
    3 oктомври 2008
    Па учам ама нема тоа што ми треба
     
  13. Spion

    Spion
    Intern

    48
    4
    25 Септември 2007
    Веќе пејстираше код кој чита во циклус линија по линија. Внатре во циклусот тој чита по една линија. Стави две променливи со различно име и повтори ја функцијата што чита линија (getline) 2 пати, со различно име на променливата во која се вчитува линијата.

    Незнам колку поспецифичен да бидам одошто да ти го напишам кодот, а така its no fun :)
     
  14. Spion

    Spion
    Intern

    48
    4
    25 Септември 2007
    Код:
    string line;
    ifstream input("prasanja.dat");
    if(input.is_open())
    {
    
    while(!input.eof())
    {
    getline(input, line);
    cout << line << endl;
    }
    input.close();
    }
    else
    cout << "Unable to open file!" << endl;
    
    system("pause");
    return 0;
    Ова е добар старт - во тој код, функцијата getline(input, line); чита линија и ја сместува во string променливата line.

    Накратко за начинот на размислување - ако незнаеш што точно прави некоја функција, најди повеќе информации за функцијата
    На пример getline
    http://www.cplusplus.com/reference/string/getline.html
    Битни делови овде се
    - дека чита линија,
    и особено делот:
    "If the delimiter is found, it is extracted and discarded, i.e. it is not stored and the next input operation will begin after it."
    Значи ако ја повикаш пак ќе ја прочита наредната линија.

    Конечно, за да не продолжи да врти циклусот, после двете читања повикај ја getline, наместо со input (всушност input датотеката за квизот), со cin - кој што е стандардниот внес од корисникот...
    getline(cin, DadenOdgovor);
     
  15. Ivica_M

    Ivica_M
    Intern

    226
    3
    3 oктомври 2008
    Добро е направив нешто ставив надвор од циклусот while(!input.eof())
    и ја печати првата линија еве го кодот:
    getline(input, prva_linija);
    cout << prva_linija << endl;

    cout << "Odgovor: ";
    cin >> odgovor;

    if(odgovor == "prv odgovor") //prv odgovor e imeto na odgovorot
    {
    cout << "Odgovorot e tocen!" << endl;
    cout << "Vkupno poeni: " << poeni++ << endl;
    }
    else
    {
    cout << "Odgovorot ne e tocen!" << endl;
    cout << "Osvoivte " << poeni << " poeni!" << endl;
    }
    е сега кога ќе напишам prv odgovor вели дека одговорот не е точен (не го споредувам одговорот со тој од датотеката туку едноставно го напишав) и еве не сака да работи како што треба. Решение?
     
  16. Spion

    Spion
    Intern

    48
    4
    25 Септември 2007
    cin >> odgovor;
    чита само еден збор.
    getline(cin, odgovor);
    чита цела линија.

    (jfk)
     
    1 person likes this.
  17. Ivica_M

    Ivica_M
    Intern

    226
    3
    3 oктомври 2008
    Супер е! Многу интересно еве го кодот:
    getline(инпут, prva_linija);
    cout << prva_linija << endl;

    cout << "Odgovor: ";
    getline(cin, odgovor);
    if(odgovor == "prv odgovor")
    {
    poeni++;
    cout << "Odgovorot e tocen!" << endl;
    cout << "Vkupno poeni: " << poeni << endl;
    }
    else
    {
    cout << "Odgovorot ne e tocen!" << endl;
    cout << "Osvoivte " << poeni << " poeni!" << endl;
    }

    И уште нешто вака како ова ако правам ако имам 100 прашања на пример би напишал можда 3000 линии код може некако во циклус да се стави или не?

    П.С. Ако може по можност некако да се генерира рандом прашања?
     
  18. Spion

    Spion
    Intern

    48
    4
    25 Септември 2007
    Ми пукна филм, а и веќе имаш код, не се лути ако додадам :)

    Меѓутоа мислам дека поинтересно ќе ти биде ако НЕ го читаш кодов. Пробај сам да се сетиш... ако не иде, ок.

    ---
    ---
    Spoiler warning!
    ---
    ---

    Код:
    //На почеток, корисникот нема поени.
    int poeni = 0;
    // ...
    // ...
    // овдека, copy-paste na kodot за отварање датотека.
    // све исто како за читање на цела датотека линија по линија ама само до овде:
    while (!input.eof()) {
    // и после внатре, твојата логика
    getline(input, prva_linija);
    // првата линија е прашањето, го прикажуваме
    cout << prva_linija << endl;
    // јас викам, ајде да ја читаме и втората...
    // Ама пази. Бидејќи сме во циклус, наредниот пат
    // кога ќе се изврши циклусот без проблем, 
    // автоматски ќе си продолжи со читање на третата и четвртата линија!
    // Незнам како не ти текна на ова? Циклус повикува функција повеќе
    // пати, зошто мислиш дека е различно ако тие повеќе пати се прават
    // наместо по една одеднаш, по две одеднаш?
    getline(input, tocen_odgovor);
    // Бидејќи оваа е одговорот,
    // наместо да ја прикажеме, ќе почекаме корисникот
    // да внесе негов одговор...
    cout << "Odgovor: ";
    // одговорот му го читаме како цела линија, не како збор...
    getline(cin, odgovor);
    // споредуваме
    if(odgovor == tocen_odgovor)
    {
    // точен? екстра, поени за него!
    poeni++;
    cout << "Odgovorot e tocen!" << endl;
    cout << "Vkupno poeni: " << poeni << endl;
    }
    else
    {
    // Неточен? Нема поени!
    cout << "Odgovorot ne e tocen!" << endl;
    cout << "Osvoivte " << poeni << " poeni!" << endl;
    // Може и во стил на Милионер да се прекине квизот. 
    // Одкоментирај ја наредната линија за тоа.
    //break; 
    }
    }
    // овдека, доврши copy-paste од примерот со читање цела 
    // датотека линија по линија...
    
    sorry ама неможев да издржам :)
     
    1 person likes this.
  19. Ivica_M

    Ivica_M
    Intern

    226
    3
    3 oктомври 2008
    ОК Фала за помошта :D :D :D
     

Сподели

Вчитување...