THIS CODE WONT READ TEXT DATA TO 2D VECTOR. HELP TO EDIT

I created a text file using a 2D string vector. It contains data arranged as here below.

I want to read the whole text file.


LR UNIT NUMBER: RTI3866996L
NAME OF PROPRIETOR: MWANGI ELIJAH
NATIONAL ID CARD NUMBER: 4568786990
ADDRESS OF PROPRIETOR: BOX 234 NAIROBI
PIN NUMBER OF PROPRIETOR: B143233556367P
DATE_OF_ACQUISITION: 23-01-2016
DATE_OF_ISSUE_OF_TITLEDEED: 30-01-2016
CATEGORY: PRIVATE LAND
TYPE_OF_OWNERSHIP: ABSOLUTE
COUNTY_LOCATED: NAIROBI
DISTRICT_LOCATED: ROYSAMBU
DIVISION_LOCATED: GIRHURAI
LOCATION_LOCATED: SECTION 44
SUBLOCATION_LOCATED: WAIHENYA
VILLAGE_LOCATED: SONIC
------------------------------------------------------------------------------------------------------------
LR UNIT NUMBER: GJ4758869LT
NAME OF PROPRIETOR: TEST DATA
NATIONAL ID CARD NUMBER: 234536374
ADDRESS OF PROPRIETOR: KENYA
PIN NUMBER OF PROPRIETOR: RT474785859L
DATE_OF_ACQUISITION: TODAY
DATE_OF_ISSUE_OF_TITLEDEED: FUTURE DATE
CATEGORY: PUBLIC LAND
TYPE_OF_OWNERSHIP: LEASEHOLD
COUNTY_LOCATED: LAIKIPIA
DISTRICT_LOCATED: NARO MORU
DIVISION_LOCATED: EQUATOR
LOCATION_LOCATED: GWA KUNGU
SUBLOCATION_LOCATED: MUCII
VILLAGE_LOCATED: GWITU
------------------------------------------------------

i have written the following code to read the whole file and display the information and retain the whole format as above but this code cant read it.

Kindly help me identify and correct the errors. I welcome even a new idea to read the whole text file database and display to screen.

#include <iostream>
#include <fstream>
#include <string>
#include <iomanip>
#include <sstream>
#include <vector>
#include <stdio.h>

using namespace std;
int colA = 0;
int rowA = 0;

int main (){

string readCursor, tempholder;;

ifstream myFile;

myFile.open ("My_Land register.txt");

vector < vector<string> >readto;


if (myFile.fail ())
{
cerr<<"Problem opening My_Land register file !\n";

system ("pause");
exit (1);
}

//reading the text file
cout<<"\n"<<endl;

while (myFile.is_open())
{
while(!myFile.eof())
{
while (getline (myFile,readCursor))
{
istringstream streamer (readCursor);
colA = 0;

while (streamer>>tempholder) //strings are read to variable
{readto [rowA][colA] = tempholder;
cout<<"Reading strings from file"; //checking compilation...
colA++;
}
rowA++;
}
}
}

//Display data
cout<<"Number of rows is ------>"<<rowA<<endl;

cout<<"Number of columns is ------>"<<colA<<endl;

cout<<" "<<endl;

for (int i = 0; i<rowA; i++){
for (int j = 0;j<colA; j++)
{
cout<<left<<setw(6)<<readto [i][j]; // display text data to screen
}
cout<<endl;
myFile. close ();
}

system ("pause");

return 0;

}
Last edited on
Don't loop on EOF. http://www.cplusplus.com/forum/general/24288/#msg128344

Assuming your file format is FIXED, here's something you can play with:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
#include <algorithm>
#include <fstream>
#include <iostream>
#include <string>
#include <vector>

typedef std::string         field;
typedef std::vector<field>  record;
typedef std::vector<record> table;

// Read an individual record (composed of fields)
std::istream& read_record( std::istream& f, record& rec )
{
  std::string line;
  rec.clear();
  while (std::getline( f, line ))
  {
    std::size_t n = line.find( ':' );
    if (n == line.npos)
    {
      if (rec.size()) break;
      else            continue;
    }
    rec.emplace_back( line.substr( n+2 ) );
  }
  return f;
}

// Read a complete file of records (a complete table)
table read_table( std::istream& f )
{
  table  tab;
  record rec;
  while (read_record( f, rec ))
  {
    tab.emplace_back( rec );
  }
  return tab;
}

inline table read_table( std::istream&& f ) 
{ 
  return read_table( f );
}

// Names of fields in a record
const char* field_names[] = 
{
  "LR UNIT NUMBER",
  "NAME OF PROPRIETOR",
  "NATIONAL ID CARD NUMBER",
  "ADDRESS OF PROPRIETOR",
  "PIN NUMBER OF PROPRIETOR",
  "DATE_OF_ACQUISITION",
  "DATE_OF_ISSUE_OF_TITLEDEED",
  "CATEGORY",
  "TYPE_OF_OWNERSHIP",
  "COUNTY_LOCATED",
  "DISTRICT_LOCATED",
  "DIVISION_LOCATED",
  "LOCATION_LOCATED",
  "SUBLOCATION_LOCATED",
  "VILLAGE_LOCATED"
};

// Write an individual record (composed of fields)
std::ostream& write_record( std::ostream& f, const record& rec )
{
  std::size_t n = 0;
  for (const field& field_value : rec)
  {
    f << field_names[n++] << ": " << field_value << "\n";
  }
  return f << std::string( 55, '-' ) << std::endl;
}

// Write a complete file of records (a complete table)
std::ostream& write_table( std::ostream& f, const table& data )
{
  for (const record& rec : data )
  {
    write_record( f, rec );
  }
  return f;
}

inline std::ostream& write_table( std::ostream&& f, const table& data )
{
  return write_table( f, data );
}

int main()
{
  // Read the file
  table data = read_table( std::ifstream("data.txt") );
  
  // Let's sort it by LR UNIT NUMBER
  std::sort( data.begin(), data.end(), 
    []( const record& a, const record& b ) -> bool
    {
      return a[0] < b[0];
    }
  );
  
  // Write the new file
  write_table( std::ofstream("data-sorted-by-LR_UNIT_NUMBER.txt"), data );
}

If you expect that each record could be different (either how the fields are arranged or by the names or number of fields), then you'll need a different solution.

Enjoy.
Hi,

This seems a very similar problem to your other post:

http://www.cplusplus.com/forum/general/183560/


It's better to keep related things in one Topic. Please use code Tags, then we can compile it right here with cpp.sh, and refer to line numbers.

Have you considered making a struct which contains the information for 1 row of data? Then have a std::vector of your struct.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <string>
#pragma once // not standard C++, but widely supported, could use header guard instead

// LandRecord.hpp

struct LandRecord {

// I made them all public, so it's easier for now, should be private, or the vector should be.
public:

// these might be eaier on the eye, if lower case(put more _ in, so it's one word) ,  or PascalCase
std::string LR_UNIT_NUMBER
std::string NAME_OF_PROPRIETOR
std::string NATIONAL_ID_CARD NUMBER
std::string ADDRESS_OF_PROPRIETOR
std::string PIN NUMBER OF PROPRIETOR
std::string DATE_OF_ACQUISITION
std::string DATE_OF_ISSUE_OF_TITLEDEED
std::string CATEGORY
std::string TYPE_OF_OWNERSHIP
std::string COUNTY_LOCATED
std::string DISTRICT_LOCATED
std::string DIVISION_LOCATED
std::string LOCATION_LOCATED
std::string SUBLOCATION_LOCATED
std::string VILLAGE_LOCATED
};


In the .cpp file:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
std::vector<std::string> LandDataBase; // a cadastre

//or better than this read them from file into a struct, then push_back the struct
LandDataBase.push_back({"RTI3866996L",
"MWANGI ELIJAH",
"4568786990",
"BOX 234 NAIROBI",
"B143233556367P",
"23-01-2016",
"30-01-2016",
"PRIVATE LAND",
"ABSOLUTE",
"NAIROBI",
"ROYSAMBU",
"GIRHURAI",
"SECTION 44",
"WAIHENYA",
"SONIC"});


Hope this helps :+)
Wow ! This forum is indeed educative.

Thanks Duoas (10063). I would have wanted to make the database look like an excel worksheet with one common row at top bearing the column headings - LR UNIT NUMBER, NAME OF PROPRIETOR, NATIONAL ID CARD NUMBER... about 16 column headings but was short of idea on costructs that can do it.

I would have liked each record to be read as one row under those headings/ fields and therefore have a list of rows (as records) with specific details under each of the column headings just like in excel.


I am a student and therefore not endowed with much on detailed implementations.


TheIdeasMan (4000), thank tou too. I have not been using structs but now that you advised, i will look into them and see if they can simplify the problem.



Hi,

Well I definitely was ninja'd there :+)

I made a mistake as well, I meant std::vector<LandRecord> LandDataBase; // a cadastre

I have not been using structs but now that you advised, i will look into them and see if they can simplify the problem.


A big thing there is that struct and class are almost identical, struct is public: by default, whereas class is private: by default.Anyway you can read all about it :+)

Good Luck !!
Mwangi Elijah wrote:
I would have wanted to make the database look like an excel worksheet with one common row at top bearing the column headings
That's not the format you posted above...

Here's the CSV-style format you want, right?
LR UNIT NUMBER, NAME OF PROPRIETOR, NATIONAL ID CARD NUMBER, ADDRESS OF PROPRIETOR, PIN NUMBER OF PROPRIETOR, DATE_OF_ACQUISITION, DATE_OF_ISSUE_OF_TITLEDEED, CATEGORY, TYPE_OF_OWNERSHIP, COUNTY_LOCATED, DISTRICT_LOCATED, DIVISION_LOCATED, LOCATION_LOCATED, SUBLOCATION_LOCATED, VILLAGE_LOCATED
RTI3866996L, MWANGI ELIJAH, 4568786990, BOX 234 NAIROBI, B143233556367P, 23-01-2016, 30-01-2016, PRIVATE LAND, ABSOLUTE, NAIROBI, ROYSAMBU, GIRHURAI, SECTION 44, WAIHENYA, SONIC
GJ4758869LT, TEST DATA, 234536374, KENYA, RT474785859L, TODAY, FUTURE DATE, PUBLIC LAND, LEASEHOLD, LAIKIPIA, NARO MORU, EQUATOR, GWA KUNGU, MUCII, GWITU

Making that work requires relatively few changes:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
#include <algorithm>
#include <ciso646>
#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>

typedef std::string         field;
typedef std::vector<field>  record;
typedef std::vector<record> table;

// Read an individual record (composed of fields)
std::istream& read_record( std::istream& f, record& rec )
{
  std::string s;
  field       field_value;
  rec.clear();
  
  f >> std::ws;  
  std::getline( f, s );
  std::istringstream ss( s );
  
  while ((ss >> std::ws) and (std::getline( ss, field_value, ',' )))
  {
    rec.emplace_back( field_value );
  }
  return f;
}

// Read a complete file of records (a complete table)
table read_table( std::istream& f )
{
  table  tab;
  record rec;
  while (read_record( f, rec ))
  {
    tab.emplace_back( rec );
  }
  return tab;
}

inline table read_table( std::istream&& f ) 
{ 
  return read_table( f );
}

// Write an individual record (composed of fields)
std::ostream& write_record( std::ostream& f, const record& rec )
{
  std::size_t n = 0;
  for (const field& field_value : rec)
  {
    f << (n++ ? ", " : "") << field_value;
  }
  return f << std::endl;
}

// Write a complete file of records (a complete table)
std::ostream& write_table( std::ostream& f, const table& data )
{
  for (const record& rec : data )
  {
    write_record( f, rec );
  }
  return f;
}

inline std::ostream& write_table( std::ostream&& f, const table& data )
{
  return write_table( f, data );
}

int main()
{
  // Read the file
  table data = read_table( std::ifstream("b-data.txt") );
  
  // Let's sort it by LR UNIT NUMBER
  std::sort( data.begin() + 1, data.end(), 
    []( const record& a, const record& b ) -> bool
    {
      return a[0] < b[0];
    }
  );
  
  // Write the new file
  write_table( std::ofstream("b-data-sorted-by-LR_UNIT_NUMBER.txt"), data );
}

It has a new caveat, however: fields cannot contain commas. A more advanced CSV parser is required to handle quoted fields.

Enjoy.

TheIdeasMan, then to receive user input one would implement the vector how ?
int main (){
struct LandRecord obj;
LandDataBase.push_back (obj);


That is it Duoas ! You are right on point ! Thanks for making it easy for me brother !
Topic archived. No new replies allowed.