Storing Strings in arrays

Hi! I have a tab delimited file that looks like this


NAME AGE HEIGHT WEIGHT REMARKS
Pupil1 15 176 190 overweight - diet plan
Pupil2 16 190 150 normal
Pupil3 15 187 165 Normal


How can I store the names and remarks in some sort of "array" for further reference? I can store the age, height and weight in arrays using int array[]. Also, I need to get the side comments in the remarks like in the first entry. Please help. Thanks in advance. :))
Last edited on
The TAB character is a very poor choice for a delimiter.
So the first idea would be to use something else instead of TAB, for instance a comma:

http://en.wikipedia.org/wiki/Comma-separated_values

Then an input file such as:
Jessie Jenkins	17	178	200	should cut on the fried chicken and pork chops

can become:
Jessie Jenkins,17,178,200,should cut on the fried chicken and pork chops


If you want to go ahead with TAB's anyway, you can use std::strtok() from the cstring header, as in the example below:
http://cplusplus.com/reference/cstring/strtok/

(I am interested to see other people suggesting a more modern approach for this.)
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
#include <cstddef>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <iostream>
#include <istream>
#include <ostream>
#include <string>

struct Pupil
{
    std::string name;
    int age;
    int height;
    int weight;
    std::string comments;	
};

// teching input streams to read Pupil objects
std::istream & operator >> (std::istream &is, Pupil &p)
{
    char buffer[512];
    char *token;

    is.getline(buffer, sizeof buffer);
    token = std::strtok(buffer, "\t");
    p.name = token;
    token = std::strtok(NULL, "\t");
    p.age = std::strtol(token, NULL, 10);
    token = std::strtok(NULL, "\t");
    p.height = std::strtol(token, NULL, 10);
    token = std::strtok(NULL, "\t");
    p.weight = std::strtol(token, NULL, 10);
    token = std::strtok(NULL, "\t");
    p.comments = token;
    return is;
}

// teaching output streams to write Pupil objects
std::ostream & operator << (std::ostream &os, const Pupil &p)
{
    os << "*** Pupil information ***\n";
    os << "Name: " << p.name << '\n';
    os << "Age: " << p.age << '\n';
    os << "Height: " << p.height << '\n';
    os << "Weight: " << p.weight << '\n';
    os << "Comments: " << p.comments << "\n\n";
    return os;
}

int main()
{
    std::ifstream input_file("fatcamp.txt");
    Pupil p;

    input_file >> p;
    std::cout << p;
}
Rather than having multiple arrays you could define a struct to consist of
string name
int age
int height
int weight
string remarks
then just have a single array of this struct.


Since the fields are tab delimited, you could use getline with the tab character as a delimiter for the string fields. Remember the last field on the line is delimited by the newline character, rather than a tab.
http://www.cplusplus.com/reference/string/string/getline/

The numeric fields could be read using the same method, where the value is first read as a string, then converted to an integer (for example by using a stringstream, or the atoi() function).
Example of using atoi here:
http://www.cplusplus.com/forum/beginner/98960/#msg531953

Or read the numeric fields using the usual >> extraction operator.
http://www.cplusplus.com/reference/istream/istream/operator%3E%3E/

Note, when you mix getline() and >> input operations, you need to remember that these behave slightly differently. getline will remove the delimiter, while >> leaves it remaining in the buffer.
Last edited on
"Some sort of array" depends on how you are going to access elements, whether the elements shall be ordered and so on.
If you need indeed something as array you can use std::vector.

You can define a record of the file as a structure as it was said already,
For example

1
2
3
4
5
6
7
8
struct Person
{
    std::string name;
    unsigned int age;
    float height;
    float weight;
    std::string comments;	
};

And you can overload operator >> for this structure. For exmple

1
2
3
4
5
6
7
std::istream & operator >>( std::istream &is, Person &p )
{
   is >> p.name >> p.age >> p.height >> p.weight;
   std::getline( is, p.comments );

   return is;
}


If you are able to estimate the approximated number of records in the file you can use std::vector<Person> the following way

1
2
3
4
5
6
7
8
9
std::vector<Person> people;

people.reserve( ApproximatedNumber );

std::ifstream is( "MyFileNmae" );

Person p;

while ( is >> p ) people.push_back( p );
Last edited on
Topic archived. No new replies allowed.