user3350597
user3350597

Reputation: 465

Cyrillic input output, c++

Still in learning process. I have made a small program that will :

  1. Make a file with users inputs
  2. Read the file
  3. Fill struct from file, sort and than make a new file "name sorted.txt"

those are my 3 cases. Problem is occurring when I put the Cyrillic text on and try to fill the struct, sort and make a new file.(using case 3:...). Struct is not filling, if I did my test right. But it's making and reading file correctly (case 1,2)

Program is doing everything right if I only use Latin alphabet. My code if below any help is welcome...

#include "stdafx.h"
#include "iostream"
#include <fstream>
#include "string"
#include <sys/stat.h>
#include<clocale>
#include <Windows.h>
using namespace std;

#define  MAX 10000// max number of students per list

//void sortStruct(); sorting structure
//void swap(studentStruct , studentStruct ); helping with sort function
//void readFile (string );reading a .txt file (ex. Saved list)
//void printStruct(); printing the struct
//void fillStruct(string ); filling a struct from a chosen file, helpin with a sort
//void calculateGrade(ofstream , int ); calcuating average grade, under witch we sort
//void writeToFile(ofstream , string ,float ); writing to a .txt file
//void printMenu(); printing a menu to chose from

//for sorting the list
struct studentStruct{
string name;
float grade;
}student[MAX];


static void printMenu()
{
    //setlocale(LC_ALL, "Russian");
    cout<<"MENU"<<endl<<endl;
    cout<<"1. Добавить новые записи в файл или создать новый файл"<<endl;
    cout<<"2. Распечатайте файл на терминал"<<endl;
    cout<<"3. Сделать отсортированный версию текстового файла"<<endl;
    cout<<"4. Bыход"<<endl<<endl;
    cout<<"Выберите (цифры) :   ";
}
inline bool exists_test (const std::string& name) {
    ifstream f(name.c_str());
    if (f.good()) {
        f.close();
        return true;
    } else {
        f.close();
        return false;
    }   
}
void writeToFile(ofstream &outputFile, string name,float grade)
{   

    outputFile<<name<<" "<<grade<<endl;

cout << "Готово!\n";
}

void calculateGrade(ofstream &outputFile, int numProf)
{
    float sum;
    string name,last;

    cout<<endl<<endl;
    cout<<"Введите имя студента : ";
    cin.sync();
    getline(cin,name);
    cout<<endl;
    for(int i=0; i<numProf;i++)
    {
        cout<<"Введите "<<i+1<<". оценку (цифры) : ";
        cin>>sum;
        sum+=sum;
    }
    float grade=sum/numProf; 

    writeToFile(outputFile, name,grade);
}

static void fillStruct(string FileName)
{
    ifstream rdFile;    //Input Object
    bool i;
    i=exists_test(FileName);
    if(i=true)cout<<"IMA";
    rdFile.open(FileName);

    for(int i=0; i<MAX;i++)
    {
        rdFile>>student[i].name;
        rdFile>>student[i].grade;
    }

    rdFile.close();

}
static void printStruct()
{
for(int i=0;i<MAX;i++){
        if(student[i].grade!=0)
        cout<<student[i].name<<" "<<student[i].grade<<endl;}
cout<<"Готово!"<<endl;
}


static void readFile (string FileName)
{
    ifstream rdFile;    //Input Object
    rdFile.open(FileName);
    cout<<endl;
    string n;
    if (!rdFile)
    {
        cout<<"File could not be open...";exit(1);
    }
    else  
    {   
        while (rdFile && getline(rdFile, n))
        {
            if (n.length() == 0)continue;
            cout<<n<<endl;
        }
    }
    rdFile.close();
    cout<<endl<<"Готово!"<<endl;
    system("PAUSE");
}


void swap(studentStruct &x, studentStruct & y)
{
    studentStruct temp;
    temp = x;
    x = y;
    y = temp;
}

static void sortStruct()
{
    for (int i = 1; i < MAX; i++)
      {
          for (int j = 0; j < MAX-i; j++)
        {
            if (student[j].grade < student[j+1].grade)
              {
                  swap(student[j].grade, student[j+1].grade);
                  swap(student[j].name, student[j+1].name);
          }
        }    
       }
}

static void writeStructToFile(string outputFile)
{
    ofstream rdFile;
    rdFile.open(outputFile);
    for(int i=0; i<MAX; i++)
    {
        if(student[i].grade!=0)
        {
            rdFile<<student[i].name<<" "<<student[i].grade<<endl;
        }
    }
    rdFile.close();

    cout<<"Готово!"<<endl;
}

int _tmain(int argc, _TCHAR* argv[])
{
    bool check;
    int flag=0,numProf,newEntreies;
    string FileName,tempName,n;
    ofstream outputFile;
    ifstream nnn;
    SetConsoleCP(1251);
    SetConsoleOutputCP(1251);

    do 
    {
        system("CLS");
        printMenu();
        cin>>flag;

        //while(flag!=1||flag!=2||flag!=3||flag!=4){
            //system("CLS");        
            //printMenu();
            //cin>>flag;}

        switch(flag)
        {
        case 1 : 
            if(FileName=="exit") {cout<<"Program will exit now..."<<endl; flag=-2;break;}
            else if(FileName=="menu")break;
            cout<<"Выберите имя для нового текстового файла (буквы и цифры):  ";
            cin.sync();
            getline(cin,FileName);
            cout<<"Введите число профессоров (цифры):  ";
            cin>>numProf;
            cout<<"Введите число студентов (цифры) :  ";
            cin>>newEntreies;
            tempName=FileName+".txt";
            check=exists_test(tempName);
            if(check==true)
                outputFile.open(tempName, std::ios_base::app); 
            else
                outputFile.open(tempName);
            if(outputFile.fail()) 
            { //if opening fails then end program
                 cout << "Input file opening failed." << endl;
                 exit(1);
            } //exit function from cstdlib library
            system("CLS");
            for(int i=0; i<newEntreies;i++)
            {
                cout<<FileName<<" "<<numProf<<" "<<newEntreies<<endl<<endl;
                cout<<"Добавление "<<i+1<<". студента...";
                calculateGrade(outputFile,numProf);
                system("CLS");
            }
                outputFile.close();
                cout<<"Нажмите любую клавишу для продолжения..."<<endl;
            break;
        case 2 :
            if(FileName=="exit") {cout<<"Program will exit now..."<<endl;flag=-2;break;}
            else if(FileName=="menu")break;
            cout<<"Введите имя файла:  ";
            cin.sync();
            getline(cin,FileName);
            system("cls");
            cout<<"Чтение из файла "<<FileName<<".txt"<<endl;

            tempName=FileName+".txt";
            readFile(tempName);
            cout<<"Нажмите любую клавишу для продолжения..."<<endl;
            break;
        case 3 : 
            if(FileName=="exit") {flag=-2;break;}
            else if(FileName=="menu")break;
            system("CLS");
            cout<<endl<<"Изготовление отсортированного файла..."<<endl<<endl;
            cout<<"Выберите файл .txt(буквы и цифры): ";
            cin.sync();
            getline(cin,FileName);
            tempName=FileName+" SORTED.txt";
            fillStruct(FileName+".txt");
            sortStruct();
            writeStructToFile(tempName);
            cout<<endl<<endl<<"Отсортировано версия "<<FileName<<" Готово!"<<endl<<endl;
            cout<<"Нажмите любую клавишу для продолжения..."<<endl;
            system("PAUSE");
            break;
        case 4: cout<< "Program will exit now..."<<endl; flag=-2;break;
        default :cout<<"Program will exit now..."<<endl;flag=-2;break;

        }

    }while(flag!=-2);

    system ("PAUSE");
    return 0;
}

Upvotes: 1

Views: 2472

Answers (1)

DevSolar
DevSolar

Reputation: 70273

Not looking at your example code much -- too long, too poorly formatted, too badly (not at all) commented.

  • What encoding is your source file in? UTF-8? (Which I would strongly suggest, unless you go all the way and use ASCII-7 with escapes.) Or is it ISO-8859-5? Koi-8r? Something else entirely?
  • Did you tell your compiler that?

Only a very basic instruction set (basically ASCII-7 without $, @ and the backtick) is actually defined by the standard. Anything beyond that is interpreted by the compiler in an implementation-defined manner. Either you need to explicitly agree with your compiler about your source encoding, or you need to use hex / oct escapes to keep your source ASCII-7 and enforce a specific encoding manually.

Once you got your literals right for your compile time environment, you need your runtime environment to agree on things:

  • Your terminal needs to have a font with the appropriate cyrillic glyphs.
  • As you're using std::cout, you should be setting something like setlocale( LC_ALL, "ru_RU.UTF-8" ) or any other UTF-8 locale, if supported by your system (and assuming your literals use that encoding). "Russian" is unlikely to cut it as a locale...

All that being said, std::string and UTF-8 are a fragile mix. It's too easy to forget that length() doesn't give the number of glyphs, substr() might result in invalid byte sequences, toupper() doesn't really work for everything, and many other traps like that. I recommend ICU, which provides a icu::UnicodeString that "knows" about all these things.

Upvotes: 1

Related Questions