Home > database >  Copy information from file to variables
Copy information from file to variables

Time:04-29

#include <iostream>
#include <stdio.h>
using namespace std;

struct Table{
    char fullname [100];
    int group;
    int firstMarks[5];
    int secondMarks[5];
};

void ReadTable (Table *&data, int N);
void ShowTable (Table *data, int N);


int main() {

    int N = 5;


    Table *data = new Table[N]{
            {},
            {},
            {},
            {},
            {}

    };

    ReadTable(data, N);
    ShowTable(data, N);
    

}



void ReadTable (Table *&data, int N){


    FILE *fl = fopen("table.txt","r");



    if (!fl) {
        cout << "Помилка";
        exit(1);
    }


    for (int i = 0; i < N; i  ) {

        for (int j = 0; j < N; j  ) {

            fscanf(fl, "%[^|] | %d | %d %d %d %d %d  | %d %d %d %d %d ", &data[i].fullname, &data[i].group,
                   &data[i].firstMarks[j], &data[i].firstMarks[j], &data[i].firstMarks[j], &data[i].firstMarks[j], &data[i].firstMarks[j],
                   &data[i].secondMarks[j], &data[i].secondMarks[j], &data[i].secondMarks[j], &data[i].secondMarks[j], &data[i].secondMarks[j]);



       }

        fscanf(fl, "\n");

    }


    fclose(fl);

    }



void ShowTable (Table *data, int N){

    for (int i = 0; i < N; i  ) {

        cout << data[i].fullname << " ";
        cout << " | ";

        cout << data[i].group << " ";
        cout << " | ";

        for (int j = 0; j < N; j  ) {

            cout << data[i].firstMarks[j]  << " ";

        }

        cout << " | ";

        for (int j = 0; j < N; j  ) {

            cout << data[i].secondMarks[j] << " ";

        }

        cout << endl;

    }
}

file table.txt:

Новикова Аделина Максимовна | 1151 | 5 2 3 1 2  | 1 2 1 3 2 
Воронина Анна Леоновна | 2151 | 2 4 3 2 1  | 5 4 5 5 4 
Медведева Елена Михайловна | 4452 | 4 2 1 3 4  | 2 4 5 2 1 
Зайцев Пётр Миронович | 1148 | 2 3 4 5 1  | 5 2 1 5 5 
Кочергин Алексей Семёнович | 3252 | 4 4 3 4 5  | 2 1 3 4 2 

Console output:

Кочергин Алексей Семёнович   | 3252  | 2 1 4 1 5  | 2 4 1 5 2 
  | 0  | 0 0 0 0 0  | 0 0 0 0 0 
  | 0  | 0 0 0 0 0  | 0 0 0 0 0 
  | 0  | 0 0 0 0 0  | 0 0 0 0 0 
  | 0  | 0 0 0 0 0  | 0 0 0 0 0 

Hi all, there is a table, one row of the table corresponds to one student and contains the following information: student's name, group number, exam grades for the first semester, exam grades for the second semester.

How do I read the information from the file into my structure variables? My attempts are unsuccessful, hope for your help!

CodePudding user response:

C is an old, mutating language. Thus, it is hard for new users to discern, which language features belong to which state of mutation of the language.

First, you can do everything with <iostream>. Mixing in <stdio> just complicates matters, IMHO.

Second, you declare your Table struct (naming! it is one RECORD in a table, only) in C style (very old mutation) and you could make good use of newer C features. Assuming, of course, you do not sit on an ancient tool chain like BorlandC 6.0 or something (which would be your first mistake).

Now, with <iostream>, solving such tasks is always following the same pattern, repeatedly:

  • For input from a stream to a type, write yourself an overloaded operator>>.
  • For output to a stream for a type, write yourself an overloaded operator<<.

A further complication of your task is, that you use kyrillic names (utf8 file encoding?!). This can be a pitfall, but sometimes, as long as you do not try to dissect the name string, you get away with ignoring this.

See below a modernized (in terms of C mutation progress) version of your code, which, at least worked on my machine after copy and pasting your data into emacs and saving it.

#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <array>
#include <vector>
#include <stdexcept>
#include <algorithm>
#include <cctype>
#include <locale>

using MarksArray = std::array<int,5>;

struct Data {
  std::string fullname;
  int group;
  MarksArray firstMarks;
  MarksArray secondMarks;
};

using DataVector = std::vector<Data>;

// trim functions taken from:
// https://stackoverflow.com/a/217605/2225104

// trim from start (in place)
static inline void ltrim(std::string &s) {
    s.erase(s.begin(), std::find_if(s.begin(),
                    s.end(),
                    [](unsigned char ch) {
                      return !std::isspace(ch);
                    }));
}

// trim from end (in place)
static inline void rtrim(std::string &s) {
    s.erase(std::find_if(s.rbegin(),
             s.rend(),
             [](unsigned char ch) {
               return !std::isspace(ch);
             }).base(), s.end());
}

// trim from both ends (in place)
static inline void trim(std::string &s) {
    ltrim(s);
    rtrim(s);
}

std::istream& operator>> (std::istream& stream, Data& data) {
  bool success = true;
  auto verify = [&success](const char* step) {
    if (!success) {
      std::cerr
    << "reading " << step << " failed!" << std::endl;
      throw std::runtime_error(step);
    }
  };
  success = success && std::getline(stream, data.fullname, '|');
  verify("fullname");
  trim(data.fullname);
  std::string temp;
  success = success && std::getline(stream, temp, '|');
  verify("group");
  data.group = std::stoi(temp);
  success = success && std::getline(stream, temp, '|');
  verify("firstMarks");
  std::istringstream ss1(temp);
  for (size_t i = 0; i < data.firstMarks.size(); i  ) {
    ss1 >> data.firstMarks[i];
  }
  success = success && std::getline(stream, temp);
  verify("secondMarks");
  std::istringstream ss2(temp);
  for (size_t i = 0; i < data.secondMarks.size(); i  ) {
    ss2 >> data.secondMarks[i];
  }
  return stream;
}

std::ostream& operator<< (std::ostream& stream,
              const MarksArray& data) {
  bool first = true;
  for (const auto& x : data) {
    if (first) {
      stream << x;
      first = false;
    } else
      stream << " " << x;
  }
  return stream;
}

std::ostream& operator<< (std::ostream& stream, const Data& data) {
  stream << data.fullname << " | "
     << data.group << " | "
     << data.firstMarks << " | "
     << data.secondMarks << std::endl;
  return stream;
}

template <class T>
std::ostream& operator<< (std::ostream& stream,
              const std::vector<T> & data) {
  for (const auto &x : data) {
    stream << x;
  }
  return stream;
}

DataVector ReadTable(const std::string& inPath) {
  DataVector result;
  std::ifstream stream(inPath);
  size_t line = 1;
  while (!std::ws(stream).eof()) {
    try {
      Data d;
      stream >> d;
      result.push_back(d);
      line  ;
    }
    catch (std::runtime_error& ex) {
      std::cerr
    << "reading line " << line << " failed." << std::endl;
      throw;
    }
  }
  return result;
}

void WriteTable(std::ostream& stream, const DataVector& data) {
  stream << data;
}

int main (int argc, const char* argv[]) {
  std::string inputFilePath{"./data.txt"};
  if (argc > 1) {
    inputFilePath = argv[1];
  }
  std::cout << "reading "
        << inputFilePath << "..." << std::endl;
  auto dv = ReadTable(inputFilePath);
  std::cout << "... done" << std::endl
        << "number of records: " << dv.size() << std::endl;

  //std::cout << dv << std::endl;
  WriteTable(std::cout, dv);
  return 0;
}

  •  Tags:  
  • c
  • Related