For Loop not Working

Hello

My for loop seems not to be working. I am meant to get the first 8 characters of a name excluding spaces nor alphanumeric character.
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
  
//Create an input file called employee.txt with the following data:
//SS van der Merwe;PJ Ferreira;HW du Plessis;DF Kodisang;AA Papoudopolous;G Mhlanga;TRF Schoeman;LJ Marais-Le Roux;CG Roux;B Nicholaidis;TT Tshabalala;RV Mississipi;

#include <iostream>
#include <fstream>
#include <cstdlib>
using namespace std;

int main()
{
    ifstream fin;
    fin.open("EmployeeNames.txt");
    if(fin.fail())
    {
        cout<<" Error in opening Input file...."<<endl;
        exit(1);
    }
    else
    {
        cout<<" Opening Input file ..."<<endl;
        cout<<" Reading from Input file ... please wait... "<<endl;
    }

    ofstream fout;
    fout.open("EmailIDs.txt");//ios::app)
    if (fout.fail())
    {
        cout<<"Error in creating output file..."<<endl;
        exit(1);
    }
    else
    {
        cout<<" Creating Email IDs from employee names....please wait."<<endl;
    }

char nextSymbol,semiColon = ';';
const int limit = 8;
int i=0, count = 0;


while (fin>>nextSymbol)
{
        for( i=0; i<=limit; i++)  // to get the first 8 characters
        {

            cout<<nextSymbol;
            fout.put(nextSymbol);
            i=count;
            count++;
        }

}
            if ( i == limit)
            {
                cout<<";";
                fout.put(semiColon);
            }


    if ( nextSymbol == isalpha(1) || nextSymbol == isspace(1) ) // checking if next char is an empty space or alphanumeric
    {

            count += 1;                                     //skip it and move to the next
            i -= 1;                                         // ensuring limit of 8 characteres is maintained
                                                            //copy the next symbol that is not alphanumeric or a space
    }

    if ( nextSymbol == semiColon )                      // if semi colon is encountered create email ID
    {
        // create newid
        count = limit ;
    }
    else
    {

    }
    fin.close();
    fout.close();
    return 0;

}

This might be a case where the indentation is misleading you. Here is the code indented to match the actual block structure:

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
//Create an input file called employee.txt with the following data:
//SS van der Merwe;PJ Ferreira;HW du Plessis;DF Kodisang;AA Papoudopolous;G Mhlanga;TRF Schoeman;LJ Marais-Le Roux;CG Roux;B Nicholaidis;TT Tshabalala;RV Mississipi;

#include <iostream>
#include <fstream>
#include <cstdlib>
using namespace std;

int
main()
{
    ifstream fin;
    fin.open("EmployeeNames.txt");
    if (fin.fail()) {
	cout << " Error in opening Input file...." << endl;
	exit(1);
    } else {
	cout << " Opening Input file ..." << endl;
	cout << " Reading from Input file ... please wait... " << endl;
    }

    ofstream fout;
    fout.open("EmailIDs.txt");			 //ios::app)
    if (fout.fail()) {
	cout << "Error in creating output file..." << endl;
	exit(1);
    } else {
	cout << " Creating Email IDs from employee names....please wait." << endl;
    }

    char nextSymbol, semiColon = ';';
    const int limit = 8;
    int i = 0, count = 0;

    while (fin >> nextSymbol) {
	for (i = 0; i <= limit; i++)		 // to get the first 8 characters
	{
	    cout << nextSymbol;
	    fout.put(nextSymbol);
	    i = count;
	    count++;
	}
    }

    if (i == limit) {
	cout << ";";
	fout.put(semiColon);
    }

    if (nextSymbol == isalpha(1) || nextSymbol == isspace(1))	// checking if next char is an empty space or alphanumeric
    {
	count += 1;   // skip it and move to the next
	i -= 1;	      // ensuring limit of 8 characteres is maintained
		      // copy the next symbol that is not alphanumeric or a space
    }

    if (nextSymbol == semiColon)		 // if semi colon is encountered create email ID
    {
	// create newid
	count = limit;
    } else {
    }

    fin.close();
    fout.close();
    return 0;
}

The loop at line 35 reads the input file 1 character at a time.

The loop at lines 36-42 executes for each character. The first time, it prints the first character 8 times. But upon entering the loop the second time, count == 9 because it wasn't reset from the first time. At line 40, i gets set to 9, which means the loop executes just once. This behavior continues for each pass through the loop at line 35: the loop at lines 36-42 executes just once.

Eventually you get to line 45. By now i is some large value, because it kept getting set to count, which kept getting incremented. Whatever it is, it isn't limit.

At line 50 are you trying to see if nextSymbol is an alpha or a space? That would be if (isalpha(nextSymbol) || isspace(nextSymbol))

Your description of the problem isn't completely clear to me, especially considering the comment at the beginning of the code. Could you post an example of the input and expected output?
I'm meant to get Employee names contained in a file. Employee names are separated by semicolons. The process of creating a userid is as follows: The first 8 characters, excluding spaces and non-alphabetical characters becomes the userid. An input file called employee.txt contains the following data:

SS van der Merwe;PJ Ferreira;HW du Plessis;DF Kodisang;AA Papoudopolous;G Mhlanga;TRF Schoeman;LJ Marais-Le Roux;CG Roux;B Nicholaidis;TT Tshabalala;RV Mississipi;

so i must get email ids as follows :
SSvande;PJFerrei;HWduPles;DFKodisa;AAPapoud;GMhlanga;TRSchoe;LJMarais;CGRoux;BNichola;TTTshaba;RVMissip;

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

#include <iostream>
#include <fstream>
#include <cstdlib>
using namespace std;

int main()
{
    ifstream fin;
    fin.open("EmployeeNames.txt");
    if(fin.fail())
    {
        cout<<" Error in opening Input file...."<<endl;
        exit(1);
    }
    else
    {
        cout<<" Opening Input file ..."<<endl;
        cout<<" Reading from Input file ... please wait... "<<endl;
    }

    ofstream fout;
    fout.open("EmailIDs.txt");//ios::app)
    if (fout.fail())
    {
        cout<<"Error in creating output file..."<<endl;
        exit(1);
    }
    else
    {
        cout<<" Creating Email IDs from employee names....please wait..."<<endl;
        cout<<endl;
    }

char nextSymbol,semiColon = ';';
const int limit = 8;
int i=0, count = 0;


while (fin>>nextSymbol)
{
        for( i=0; i<=limit; i++)  // to get the first 8 characters
        {

            cout<<nextSymbol;
            fout.put(nextSymbol);
            i=count;
            count++;
        }

}
            if ( i == limit)
            {
                cout<<";";
                fout.put(semiColon);
            }


    if ( nextSymbol == isalpha(1) || nextSymbol == isspace(1) ) // checking if next char is an empty space or alphanumeric
    {

            count += 1;                                     //skip it and move to the next
            i -= 1;                                         // ensuring limit of 8 characteres is maintained
                                                            //copy the next symbol that is not alphanumeric or a space
    }

    if ( nextSymbol == semiColon )                      // if semi colon is encountered create email ID
    {
        // create newid
        count = limit ;
    }
    else
    {

    }
    fin.close();
    fout.close();
    return 0;

}




Thanks for the explanation. I would read the whole employee name first, then extract the 8-character userID from the name. If you do it this way, then it will be much easier to test: first you write and test the code that gets the employee names, then you add and test the code that extracts a userID from an employee name.

If the real world this would be a better design also: If you have a function that gets an employee's userID from their name, then you could use it regardless of where the name came from. That would make the code much more flexible.
Hello pumzye,

It looks like you are trying to make this harder than it needs to be. Consider this instead:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
	while (std::getline(fin, name, ';'))
	{
		count = 0;  //  Zero count bfore each use.

		for (i = 0; i <= name.length(); i++)  // <---To read the entire string.
		{
			if (isspace(name[i])) continue;  // <--- If space or digit goto next character
			if (isdigit(name[i])) continue;
			if (isalpha(name[i]))
			{
				cout << name[i];
				fout.put(name[i]);
				count++;
				if (count == limit) break;
			}
		}  //  End for loop

		std::cout << std::endl;
		fout.put(semiColon);  // < After creating ID put a semicolon to output.
	}  //  End while loop 


Hope that helps,

Andy

P.S. In your EmployeeNames.txt file remove the semicolon at the end. It is not needed there. It will give you an extra semicolon in your output file. Although the last "fout" statement still needs some work because it will put a semicolon at the end of the file.
Last edited on
Handy Andy , Thanks a million.

I was brave enough to have started this all again since it was trying to make it harder as you figured out. The new code i wrote seems to be a little better and smarter. I only need to exclude the trailing characters up to the next semi colon;

Its getting the first one right but the rest need to exclude characters after the limit of 8 has been identified.

Please advise how i can achieve that on this refreshed code.

Thank again, Andy

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


#include <iostream>
#include <fstream>
#include <cstdlib>
#include<cctype>
using namespace std;

int main()
{
    ifstream fin;
    fin.open("EmployeeNames.txt");
    if(fin.fail())
    {
        cout<<" Error in opening Input file...."<<endl;
        exit(1);
    }
    else
    {
        cout<<" Opening Input file ..."<<endl;
        cout<<" Reading from Input file ... please wait... "<<endl;
    }

    ofstream fout;
    fout.open("EmailIDs.txt");//ios::app);

    if (fout.fail())
    {
        cout<<"Error in creating output file..."<<endl;
        exit(1);
    }
    else
    {
        cout<<" Creating Email IDs from employee names....please wait..."<<endl;
        cout<<endl;
    }

char nextSymbol,semiColon = ';';

int  count = 0, check = 0 ;

const int limit = 8;

fin.seekg(0);

while( fin>>nextSymbol)

    {

    fout.put(nextSymbol);
    cout<<nextSymbol;
    count++;

    if ( count == limit)
    {
    cout<<"*";
    fout.put(semiColon);
    count=0;

       if ( nextSymbol == semiColon)
    {

        check = 1;
        fout.put(nextSymbol);
        cout<<nextSymbol;
        count++;
        check = 0 ;

            }
    else

    {
        check = 0;
        count = 0;


    }
    }
    }


   
     fin.close();
    fout.close();
    return 0;

}
Hello pumzye,

I have not worked it out yet, but I am thinking the general Idea is to use a while loop after you write the semicolon to the output file to read the rest of the characters up to the next semicolon before starting the outer while loop again.

Andy
Hello pumzye,

After some thought and a little work I came up with this. The only problem I have is the name "B Nicholaidis". It is only picking up the "B" and not the rest of the letters needed. But when I move it to the first or second name it works fine. and when I two names together it will get the "B" from the first and process the second correctly. Not sure what the problem is yet.

Here is my revised while loop. Notice the changes I made comments about.

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
	while (fin >> nextSymbol)
	{
		fout.put(nextSymbol);
		cout << nextSymbol;
		count++;

		if (count == limit)
		{
			cout << "*";  // <--- Do not see any use for this, but it works.
			//fout.put(semiColon);  <--- Puts two semicolons at the end of each Id.
			count = 0;

			while (1)
			{
				fin >> nextSymbol;
				if (nextSymbol == ';' || fin.eof()) break;
			}

			if (nextSymbol == semiColon)
			{
				check = 1;
				fout.put(nextSymbol);
				cout << nextSymbol;
				//count++;  // <--- Makes the 2nd ID on only have 7 letters.
				check = 0;
			}
			else

			{
				check = 0;
				count = 0;
			}
		}
	}


Hope that helps,

Andy
Brilliant !

Its working Andy. Thanks for being Handy with code. as you say we need to figure out that the other name on how t fix it.

This is exactly how i was thinking but needed an expert to logically arrange the code.

Thank you very much Andy.

Bueonos Dias !
Hello pumzye,

The problem I figured out is the name before "B Nicholaidis" only has six letters and that is causing the problem. Here is what I came up with to fix the probmem. Yet something else may show up later.

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
	std::ifstream fin;
	fin.open("EmployeeNames.txt");
	if (fin.fail())
	{
		std::cout << " Error in opening Input file...." << std::endl;
		exit(1);
	}
	else
	{
		std::cout << " Opening Input file ..." << std::endl;
		std::cout << " Reading from Input file ... please wait... " << std::endl;
	}

	std::ofstream fout;
	fout.open("EmailIDs.txt");//ios::app);

	if (fout.fail())
	{
		std::cout << "Error in creating output file..." << std::endl;
		exit(1);
	}
	else
	{
		std::cout << " Creating Email IDs from employee names....please wait..." << std::endl;
		std::cout << std::endl;
	}

	char nextSymbol, semiColon = ';';

	int  count = 0, check = 0, ln{ 1 };
	std::string name{ "" };
	const int limit = 8;

	fin.seekg(0);  // <--- Not necessary as th file pointer is at the beginning when the file opens.

	//std::cout << " " << std::setw(2) << ln << ". ";  // <--- Added for testing.
	//fout << " " << std::setw(2) << ln++ << ". ";     // <--- Added for testing.

	while (fin >> nextSymbol)
	{
		if (nextSymbol != ';')  // <--- Added the if else.
		{
			fout.put(nextSymbol);
			std::cout << nextSymbol;
			count++;
		}
		else
		{
			count = 8;  // <--- If shorter than 8 letters.
			check = 1;  // <--- Usd for the next while loop if less than 8.
		}

		if (count == limit)
		{
			std::cout << "*";  // <--- Do not see any use for this, but it works.
			//fout.put(semiColon);  <--- Puts two semicolons at the end of each Id.
			count = 0;

			while (!check)
			{
				fin >> nextSymbol;
				if (nextSymbol == ';' || fin.eof()) break;
			}

			if (nextSymbol == semiColon)
			{
				check = 1;  // <--- Not used.
				fout.put(nextSymbol);
				//fout << '\n';  // <--- Added for testing.
				std::cout << nextSymbol << std::endl;
				//std::cout << " " << std::setw(2) << ln << ". ";  // <--- Added for testing.
				//fout << " " << std::setw(2) << ln++ << ". ";  // <--- Added for testing.
				//count++;  // <--- Makes the 2nd ID on only have 7 letters.
				check = 0;  // <--- Setting back to zero OK here.
			}
			else
			{
				check = 0;
				count = 0;;  // <--- Setting back to zero OK here/
			}
		}
	}

	fin.close();
	fout.close();


Have fun,

Andy
Last edited on
Topic archived. No new replies allowed.