Help with Delimiter

Pages: 12
Ok so I have this project for school in which I have to read in a .txt file into an array then spit it out into a bubble sorter and sort it accordingly. I have the program opening the file, and reading the array in and printing out the array. But I'm not sure how to incorporate a delimiter. I think this is somewhat it, maybe?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
int Delim (string fileName){

  char string[] = "" ;
  char * cut;
  printf (string);
  cut = strtok (string," ,.-");

  while (cut != NULL)
  {
    printf ("%s,",cut);
    cut = strtok (NULL, " ,.-");
  }
  return 0;
}



This is my code for the int main so far. I'm not too sure where to put the delimiter part. Then on top of all of that I still have to incorporate the sorter.

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
int main () {
	
	string array[15];
	int loop=0;
	string textFile, Line;

	ifstream iFile;
	

	cout << "Please enter the name of the file you wish to open:\n";
	cin >> textFile;

	iFile.open ( textFile.c_str());

	if (iFile.good())
	{
		while (iFile.good())
		{
		getline(iFile, Line);

		

		array[loop]=Line;		// copies the Line to an array
		loop++;					// Update Loop Counter to read in new line

		cout << Line << endl;

		}
	}

	else{						// Let user know if can't open the input file.
	
	cout << "Unable to open file." << endl;
	}

// Dump the array to screen
	for (int out = 0 ; out <= loop-1 ; out++) {

		cout << array[out] << endl;

	}

iFile.close();
return 0;
system("PAUSE");


}




I hate how everything is in the int main{} also, although we havent learned about different functions in class yet. Thanks in advance for the help!
getline, by default has a delimiter of '\n'( new line )

If you want something else, try: getline( iFile, Line, ',' ); etc.
The third parameter being the delimiter.
Last edited on
So if the .txt file he gives us is serperated by |'s then I would just put
getline( iFile, Line, '|');

Is it really that easy?
Yeah! Until you hit the end line( '\n' ).

When I read multiple variables, from one line within a text( or other )file. I tend to collect the whole line in one loop.

i.e.
Sample text file:
name,surname,23
name,surname,19
name,surname,25


1
2
3
4
5
6
7
8
9
10
11
12
13
//Either use a string for each getline, or do something inbetween the getline function.
std::string input = "";

while( iFile.good() )
{
    std::getline( iFile, input, ',' );
    //Do something here with the input, or use different variables.

    std::getline( iFile, input, ',' );
    //Same as line 7

    std::getline( iFile, input, '\n' ); //Note the '\n', to get up to the end only! And not up until the next ',', which could be on the next line!
}


Edit:
These are the same!
1
2
getline( iFile, input ); //default
getline( iFile, input, '\n' );
Last edited on
Ok. So now I'm running into the problem of when it goes through the delimiter it stores every value that was seperated by the "|" and puts them onto a seperate line in the array. however, I'm not supposed to keep every bit of info that he gave us, only 5 of the 13 fields... I don't know how to make it so I just hit certain values.
If you know which fields you need...

1
2
3
4
5
6
7
while( iFile.good() )
{
    getline( iFile, input, ',' ); // Not needed, so do another getline.

    getline( iFile, input, ',' ); // Need this one? Do something with it.
    array[ loop ] = input;
}


Edit:
If you don't need the first, say 5, fields. Maybe use a for-loop to get to where you need to be.
Last edited on
Well that's the thing. 3 fields are strings, and the other 2 are integer's. Do I have to declare variables in the beginning of the function in order to set it up correctly? And another thing the variables wont be the same every time, they change every line.
And another thing the variables wont be the same every time, they change every line.

Do you mean the format changes?
1
2
3
int | string | string
string | int | string
//... 


If so, then the best bet is to read everything as a string, and then figure out which ones are numbers later.

If you have
1
2
3
int | string | string
int | string | string
//... 


Then I would set up something just for that file:
1
2
3
4
5
6
7
8
int x;
string str01;
string str02;

in >> x;
in.ignore(80, '|'); // ignore all until '|', extracting delim
getline(in, str01, '|'); // also extracts delim
getline(in, str02);

Using getline, in the current way, only reads in to a sting. To copy the string to an integer, you may want to look up "stringstream".

1
2
3
4
5
6
7
8
9
10
11
12
13
int integer = 0;

while( iFile.good() )
{
    getline( iFile, input, ',' ); // Expecting an int. So do the following.

    stringstream ss( input ); //Create a stringstring object and pass it 'input'.

    if( ss >> integer )
        // Was converted to int.
    else
        // Not able to convert.
}


And if the fields are going to move around. You may want to read the whole line in to a string getline( iFile, input, '\n' ); then parse it first.
Hmm alright, thank you so much! I will work with it and see if I can get it working lol.
LowestOne:

They are str | str|int| int| int| ... so on, but every line the numbers and strings are different So they same string and numbers wont be there every line.
Ohhh! 'input' is just a temporary holder of the data!

say you have a struct:
1
2
3
4
5
6
struct people
{
    string name;
    string surname;
    int age;
};


Then, each getline, you'd just save to here!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
people students[ 5 ]; //Create an array of your struct.
int i = 0; //indexer for your array.

while( iFile.good() )
{
    getline( iFile, input, ',' );
    students[ i ].name = input; //Save the first name.

    getline( iFile, input, ',' );
    students[ i ].surname = input; //Save the surname.

    getline( iFile, input, '\n' );
    //stringstream here for age. - Convert and save to age.

    ++i; //Move to the next index. ( Error prone with this code. as I have an array of 5, whereas the file could contain more lines than index's!! )
}


Same sample text file as before:
name,surname,23
name,surname,19
name,surname,25
Last edited on
You want a container of classes. Have you learned about vectors or classes?

If so, each line is a class. For each line, you instantiate a class and push it on to your vector.

Otherwise... You need a bunch of parallel arrays which, in the best case, are sized to the amount of lines in your file. If you don't know about dynamically allocating arrays, and you feel your teacher might use a different file than yours as data, then make the arrays much larger than you will need.
Lynx, they aren't inputs, they are values of a .txt file. here is what each line looks like.

1061698|OH|Torch|ppl|Athens|39|009|391422N|0814457W|39.23944|-81.74917|||||730|||Lubeck


I need the State, City, latitude, longtitude and one other one.
Okay.. what's with the 5 '|''s? Seems like your teacher is screwing with you, unless those fields are allowed to be empty. =/ The previous advise still seems to apply though. Parse it as a string and when you encounter a '|' then break it into another string in a loop structure. Though.. I can't easily identify the structure the way you described it.
Technically, they are inputs, from a file. But... You're taking too much notice of the name 'input'. Just remember, it's just a temporary variable!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
people students[ 5 ]; //Create an array of your struct.
int i = 0; //indexer for your array.

//Change the variable 'input's name!
string thisIsATemporaryVariableToHoldDataFromAFile = "";

while( iFile.good() )
{
    getline( iFile, thisIsATemporaryVariableToHoldDataFromAFile, ',' );
    students[ i ].name = thisIsATemporaryVariableToHoldDataFromAFile; //Save the first name.

    getline( iFile, thisIsATemporaryVariableToHoldDataFromAFile, ',' );
    students[ i ].surname = thisIsATemporaryVariableToHoldDataFromAFile; //Save the surname.

    getline( iFile, thisIsATemporaryVariableToHoldDataFromAFile, '\n' );
    //stringstream here for age. - Convert and save to age.

    ++i; //Move to the next index. ( Error prone with this code. as I have an array of 5, whereas the file could contain more lines than index's!! )
}
Ok I see what your saying now, So what would I do if I needed to skip certain fields? Sorry I'm new at this programming thing, I don't mean to keep asking you the same stuff over and over lol... But this is a great help.


Where are you getting the students[i].name from?
The array of students came from an earlier post.
Have a look through this.

Edit:
Don't worry about all the std::'s. It's because I don't include using namespace std;

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
// read from a file, save to a struct.

#include <iostream>
#include <sstream> // This also includes 'string', so no need to include that too!
#include <fstream>

struct people
{
    std::string name;
    std::string surname;
    int age;
};


int main()
{
	//Create a const int that cannot be changed.
	//This will serve as the amount of students and the loop for output.
	const int count = 5;

	people students[ count ]; //Create an array of your struct.
	int i = 0; //indexer for your array.

	//Change the variable 'input's name!
	std::string input = "";

	//Create an ifstream and open it.
	std::ifstream iFile;
	iFile.open( "myTextFile.txt" );

	if( iFile.is_open() )
	{
		while( iFile.good() )
		{
			std::getline( iFile, input, ',' );
			students[ i ].name = input; //Save the first name.

			std::getline( iFile, input, ',' );
			students[ i ].surname = input; //Save the surname.

			std::getline( iFile, input, ',' ); //This is the field we don't want to save!
			//So here, we don't do anything with 'input', then get the next field below.

			getline( iFile, input, '\n' );//This is the age
			
			//Create a stringstream object.
			std::stringstream ss( input );

			if( ! ( ss >> students[ i ].age ) )//If the conversion fails... To test, comment out the above /getline'
				std::cout << "Error saving the age of student " << i + 1 << '\n';

			++i; //Move to the next index. ( Error prone with this code. as I have an array of 5, whereas the file could contain more lines than index's!! )

			//Break fron the while loop in case the file contains more than we need.
			if( i == 5 )
				break;
		}

		//Always close the files you open!
		iFile.close();
	}
	else //If the file open failed...
		std::cout << "Sorry! Unable to open the specified file.\n";

	//Now we output the students.
	for( int i = 0; i < count; ++i )
	{
		std::cout << "Student " << i + 1 << ":\n";

		std::cout << students[ i ].name << " " << students[ i ].surname << " is " << students[ i ].age << "\n\n";
	}

	return 0;
}


This in the infile:
Dave,Smith,Car,28
Ava,Rogers,Bike,32
Carl,Potter,Bike,20
Sonia,Swan,Car,38
Peter,Jonson,Walk,34
Mason,Foster,Bike,21
Last edited on
Ohh, ok now it makes sense what your doing. I didn't know you could just tell it not save a certain chunk of info. So can I just put as many
getline( iFile, input, ',' );

as I need then?
Yes. Then each time you re-use the getline statement, 'input' will just be re-written with the next chunk of data that's being read in. (:
Pages: 12