Assistance with Data Validation in Character Arrays

Hello! I need some assistance with a somewhat complex code of mine. Here's the scenario:

The program is supposed to catalog the deliveries made delivery system based within our solar system, transporting objects from planet to planet. Luckily, I've gotten all of the math down-pat. Here's where I'm having trouble, however:

I'm supposed to read in the relevant information about each delivery from an input file, ignoring the data that is "corrupted" -- AKA, not in the correct format.

Here's how it's supposed to look:

<Service Code><space><Shipping Planet Code><space><Delivery Planet Code><space><Weight of Package>

An example description:

F M E 4

Or a First-Class delivery from Mars to Earth, weighing 4 pounds.

Like I said earlier, I already have all of the math figured out. What I can't seem to do, however, is skip the corrupted data. Here's a sample input I wrote. I want to skip the corrupted lined, but I can't somehow:

P M J 5
E J S 4
asdfghjk (corrupted)
zdfghjkl (corrupted)
E U N 6
F M E 5
T H U J


Below is the code I'm currently messing with to skip the irrelevant characters. I chose four characters because each description is supposed to be composed of only 4 characters.
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
  const int ARRAY_SIZE = 50;
	int datalog[ARRAY_SIZE];
	int count = 0;

	ifstream shipments_file;	// File stream object. 

	// Open the file for input.
	shipments_file.open("shipments.txt");

	while (count < ARRAY_SIZE && shipments_file >> datalog[count])
	{
		count++;
	}

	// Test for errors.
	if (!shipments_file)
	{
		cout << "Error opening file. Program aborting.\n";
		return 0;
	}
	
	cout << "Here is the information in the file:\n\n";
	char ch1, ch2, ch3, ch4;		// ch1 = Service Type, ch2 = Shipping Planet Code, ch3 = Destination Planet Code, ch4 = Shipment Weight

	for (int count = 0; count < ARRAY_SIZE; count++)
	{
		// Prepare the record.
		shipments_file.get(ch1);
		{
			if (isspace(ch1))
			{
				shipments_file.ignore();
			}

			if (isalpha(ch1))
			{
				if (!isupper(ch1))
				{
					shipments_file.ignore();
				}
			}
			else if (!isalpha(ch1))
			{
				shipments_file.ignore();
			}
		}
		shipments_file.ignore();

		shipments_file.get(ch2);
		{
			if (isspace(ch2))
			{
				shipments_file.ignore();
			}

			if (isalpha(ch2))
			{
				if (!isupper(ch2))
				{
					shipments_file.ignore();
				}
			}
			else if (!isalpha(ch2))
			{
				shipments_file.ignore();
			}
		}
		shipments_file.ignore();

		shipments_file.get(ch3);
		{
			if (isspace(ch3))
			{
				shipments_file.ignore();
			}

			if (isalpha(ch3))
			{
				if (!isupper(ch3))
				{
					shipments_file.ignore();
				}
			}
			else if (!isalpha(ch3))
			{
				shipments_file.ignore();
			}
		}
		shipments_file.ignore();

		shipments_file.get(ch4);
		{
			if (isspace(ch4))
			{
				shipments_file.ignore();
			}

			if (!isdigit(ch4))
			{
				shipments_file.ignore();
			}
		}
		shipments_file.ignore();


Thank you very much in advance for any and all assistance!

EDIT: Furthermore, I would also like to say that, for whatever reason, I am unable to put the contents of the file into an array, despite using the following while loop (featured on lines 10-13 above):

1
2
3
4
while (count < ARRAY_SIZE && shipments_file >> datalog[count])
	{
		count++;
	}
Last edited on
closed account (48T7M4Gy)
I think you can simplify it quite a lot by using the for loop better and referencing each character rather than hard coding 1, 2, 3 etc:

1. get the code from the file and store as char[] array
2. start by assuming the code fails ie bool false and if any test fails jump out of testing
3. check if the number of characters are correct and break out if false
{
4. check each character in turn and break out if false
5. if it gets to the last character without a failure then answer must be true
}

6. If the result is true or false act accordingly.

That way you are just reading in a series of codes and acting accordingly. The concept doesn't require any explicit ignore() function. Just read another code from the file and move on to the next one.

Storing the valid codes is a simple exercise especially if you are familiar with pointers and/or containers such as lists, vectors etc.
Last edited on
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
#include <iostream>
#include <string>
#include <cctype>
#include <sstream>
#include <iomanip>

// https://cal-linux.com/tutorials/strings.html
std::string trim( std::string str )
{
    while( !str.empty() && std::isspace( str.back() ) ) str.pop_back() ;

    std::size_t pos = 0 ;
    while( str.size() > pos && std::isspace( str[pos] ) ) ++pos ;
    return str.substr(pos) ;
}

bool valid_line( std::string line )
{
    line = trim(line) ; // comment out if leading/trailing white-space is not tolerated

    if( line.size() < 7 ) return false ;

    // http://www.stroustrup.com/C++11FAQ.html#for
    for( char c : { line[0], line[2], line[4] } ) if( !std::isalpha(c) ) return false ;
    for( char c : { line[1], line[3], line[5] } ) if( !std::isspace(c) ) return false ;
    for( char c : line.substr(7) ) if( !std::isdigit(c) ) return false ;

    return true ;
}

int main()
{
    std::istringstream file( "P M J 5\n" "E J?S4\n" "E J S 4  \n" "E J S 4b  \n" "  E J S 456  \n" "E J S 4 b \n" ) ;

    std::string line ;
    while( std::getline( file, line ) ) // http://www.cplusplus.com/reference/string/string/getline/
    {
        std::cout << std::quoted(line) << " => " ; // http://en.cppreference.com/w/cpp/io/manip/quoted

        if( valid_line(line) )
        {
            std::cout << "well-formed input data. processing this line...\n\n" ;

            // do something with the information in this line
            // ...
            // ...
        }
        else std::cerr  << "*** error: badly formed line is ignored\n\n" ;
    }
}

http://coliru.stacked-crooked.com/a/e2a7978c0e552a6a
Thank you both so much for your help! I realized what I had to do, and fixed it right away. Thanks again!
Topic archived. No new replies allowed.