# C++ Character Processing Algorithm

1. Feb 22, 2014

### ActionPotential

1. The problem statement, all variables and given/known data

Hey guys! Thanks for taking the time to help me out, I really appreciate it. I am in my second semester of college, taking my first C++ course, and I had never programmed before this class so I am kind of stuck on a problem. I have almost the entire assignment figured out and I am confident I can get this to work with a bit of guidance so any hints would be wonderful!

The basic idea is that the program will read in data from a text file using fstream and store it as a char. As each character is read in, an isdigit acid test determines if it is a digit from 0-9 and then proceeds to this assignment (if not, then we ignore it):

sum = (10*sum)+ch

Ex.

Code (Text):

char ch;
int sum;
sum= 0;

ch = 3;
sum = 10*0+3 == 3;

ch = 9;
sum = 10*3 + 9 == 39;

ch = 7;
sum = 10*39+7 == 397;

If we read in a '#' we want to print the sum to the data file, and proceed to processing the next string of characters.

For example, in my data file:

@2,89#3,*67
$187,3#%34,72#123# *3*7*1#2,3,8 The algorithm would process each individual character, assigning its value to sum, then move to the next one until it hits a '\n' or a '#'. The ouput after full processing would look like this: 289 367 1873 3472 123 371 238 Now, I can think of a variety of ways that I could make this work, however, our teacher requires this algorithm to be based on his sample algorithm as well as using the idea of summing the characters together to produce the desired number. 2. Relevant equations We are required to use an EOF Loop, process each character individually and use a sum formula to properly output the numbers separated by '#'. 3. The attempt at a solution Code (Text): /* CS 201 - Computer Science 1 Program 1 - Version D - Character Filtration February 15, 2014 */ #include <iostream> #include <fstream> #include <cctype> using namespace std; int main () { /* Variable/Data Type Declarations */ char ch; int sum; ifstream data; ofstream out; /* Input/Output of File Stream Data */ data.open ("numbers.txt"); if(not data){ cout << "Failure to open numbers.txt" << endl; system ("pause"); return 1;} out.open ("out.txt"); if(not out){ cout << "failure to open out.txt" << endl; system ("pause"); return 1;} sum = 0; // Initialization of Sum data.get(ch); // Priming Read for End-of-File Loop /* External EOF Loop */ while(data){ /* Internal Control Structure and Processing */ while((ch !='\n') and data) { if(isdigit(ch)){ // All Processing Here sum = 10*sum+ch; // Character Sum Assignment data.get(ch); // Update for Inner Loop } if(ch == '#'){ //Decision to Print Sum to File out << "The Sum is: " << sum; //Prints Sum to out.txt sum = 0; //Resets the Sum data.get(ch); //Retrieves next char in istream } } // Inner Loop } // Outer Loop cout << "Your data has been processed and is available for use. \n " << endl; system("pause"); data.close(); out.close(); // Close Data Files return 0; } // main I have tried A LOT of different things and I just feel I am missing something really simple. This isn't a difficult problem to program but I think because of the specific conditions we have to apply to the loops per the teacher, it is making it more writing myself out of a corner. Thanks for any and all input. Last edited: Feb 22, 2014 2. Feb 22, 2014 ### lewando What is your output? Examining that can provide some clues. 3. Feb 22, 2014 ### ActionPotential Thanks for your reply and assistance. Well, I have tried various methods and received different outputs each time. This current code doesn't produce any output (but the codes that produced an output either didn't use sum, or the sum seems to include the characters acsii values and doesn't do the proper conversions). I added a cout statement at the end to let me know that it at least ran through the loops, however, its currently not running through the loops (blank dos window as opposed to cout statement). Ideally: it opens the data files sets sum = 0 then the priming read would grab the first character go into the End of File loop while(data) if that's good, it goes to the "Sentinel" or event-based loop, while((ch !='\n') and data) if it's good then it goes into the first test if(isdigit(ch)) Then it adds the 0-9 digit to my sum formula sum = (10*sum)+ch; grabs the next digit, etc. until it hits if(ch == '#') Then it writes the sum to the output file Resets the sum Exits back to the top of inner while loop to make sure ch !='\n' Then, when it encounters '\n', it exits the inner loop, and the End-of-File loop checks to make sure we still have data to process. I could easily use getline and convert the string of characters into the data I need, however, our teacher wants us to use this specific method, so I am a bit hamstrung. 4. Feb 22, 2014 ### lewando Okay, getting no output is a big clue! Your first character is a '@'. How is your code processing that? 5. Feb 22, 2014 ### ActionPotential Great question. Gave me a few ideas. 1) First idea, removed the '@' leaving a leading 2. This didn't change anything that I could tell. 2) I saved my original input file as a copy. The new "numbers.txt" contained only numbers. The program ran successfully (gave me my cout statement) but produced no output. So that tells me that even though I have a problem processing nondigits, I also have a problem producing an output file. I made some changes to the code, but no luck. I am going to try a couple of things and see if anything changes (in simply processing digits). 6. Feb 22, 2014 ### ActionPotential I see a couple of problems now. Going to rewrite some things and let you know if I run into another issue or if I am able to resolve it on my own. 7. Feb 22, 2014 ### lewando You need to also process the newline '\n' inside your loop. Encountering one is significant. I think you'll get it--good luck! 8. Feb 22, 2014 ### ActionPotential So, I came back to it a few minutes ago after taking a break to work on other things and now I am simply getting an output of this: Code (Text): The Sum is: 0 The Sum is: 0 So, as I have it written now, it's simply printing the sum's initial value, twice. I thought I understood these loops pretty well, however, things are not occurring in the proper order. I tried a couple of other ideas but this seemed to have the "best output". I took the comments away temporarily because it was easier to manipulate the code. Code (Text): #include <fstream> #include <iostream> #include <cctype> using namespace std; int main() { char ch; int sum; ifstream data; ofstream out; data.open("numbers.txt"); if(not data){ cout <<"Failure to open numbers.txt" << endl; system("pause"); return 1;} out.open("out.txt"); if(not out){ cout << "Failure to open out.txt" << endl; system("pause"); return 1;} sum = 0; data.get(ch); while(data) { while((ch!='\n') and data){ data.get(ch); } if(isdigit(ch)){ sum = (10*0)+ch; data.get(ch); } if(ch == '#' or ch =='\n' ){ out << "The Sum is: " << sum << endl; data.get(ch); } } cout << "Processed..." << endl; system("pause"); data.close();out.close(); return 0; } 9. Feb 22, 2014 ### lewando When you state what the output is, make sure you state what the input is. And vice versa. This loop: Code (Text): while((ch!='\n') and data){} seems redundant and superfluous [EDIT: and hazardous] (you are already looping on data and '\n' is being handled inside). You need to process all characters that you will encounter. I still don't see how you are handling non-digits other than '#' or '\n'. Try this kind of construct inside the loop: if () {} else if () {} else if () {} else {} That should enable you to handle all character cases and do only one {} with each pass of the loop. You should be reading only one new character with each pass of the loop. Last edited: Feb 22, 2014 10. Feb 23, 2014 ### Mark44 ### Staff: Mentor Where is this "not" defined? Code (Text): if([B]not[/B] data){ cout <<"Failure to open numbers.txt" << endl; system("pause"); return 1;} I get what it's doing, but I haven't seen it before. I searched on cplusplus.com and didn't find it listed as an operator. 11. Feb 23, 2014 ### ActionPotential Hey Mark! The "not" is a boolean value for "!". Another way to write it would have been !data. However, most of this code is straight from my teacher's algorithm that are strictly required to adhere to. If I was allowed to write my own code, I would be done by now. However, I scrapped the original project and re-entered his algorithm and trying to implement the loops again. We aren't allowed to change any test conditions or add anything else other than the necessary if statements to satisfy the conditions of the loop. 12. Feb 24, 2014 ### ActionPotential Lewando, that solution makes perfect sense, however, I am required to use my teacher's algorithm. The Code (Text): while((ch !='\n') and data) is his piece of code and I am not allowed to change any of the test conditions. I reread the chapter on loops and nested if-else statements but I guess I am still not quite understanding how it works. I have rewritten my program, however, I am still getting incorrect output. Input: Code (Text): @2,89#3,*67$187,3#%34,72#123#
*3*7*1#2,3,8
Output:
Code (Text):
#
8
Here is my new code:

Code (Text):

/* Character Filtration Algorithm */

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

int main()
{
ifstream data;
ofstream out;
char ch;
int n, sum;

data.open("numbers.txt"); // Open Input Data File
if (not data){
cout << "Can't open numbers.txt" << endl;
system ("pause");
return 1;}

out.open("out.txt"); // Generate Output Data File
if (not out){
cout << "Can't open out.txt" << endl;
system ("pause");
return 1;}

data.get(ch); // Priming Read for End-of-File Loop
while (data){ // End-of-File Loop
sum = 0;

while((ch != '\n') && data){

if(isdigit(ch)){ // Test for digit
sum = sum * 10+ch; // Sum Assignment
}

if((ch == '#') && data){ // Test for '#'
out.put(ch);
}

data.get(ch); // Next Character

} // Inner Loop

if (sum > 0){ // Test for Sum
out.put(ch);
}

data.get(ch); // Next Character
} // End-of-File Loop

cout << "Program Successful " << endl;

system ("pause");
data.close(); out.close(); // Close Data Files
return 0;
}

13. Feb 24, 2014

### Staff: Mentor

Right, I get that. My question was where is this defined? I haven't seen it before. It wasn't part of C++ a while back, and I wonder if they changed the language to include "not" and "and" and so forth. As I said before, I looked on the cplusplus.com site and didn't find any mention of these operators.

14. Feb 24, 2014

### AlephZero

http://en.cppreference.com/w/cpp/keyword

15. Feb 24, 2014

### lewando

If you are constrained, then I suggest adding some "loop exit code" when you break out of the loop (as a result of a '\n' or !data). You are already using "loop entry code" (the initial priming of ch), so give it a try.

16. Feb 24, 2014

### ActionPotential

Yo, Lewando! Thanks for your all of your help. I figured out my issue. I wasn't using an ACSII character conversion formula
Code (Text):
(ch-'0')
.

It is working properly now. Here is the final code in case anyone is curious (I need to tidy the style up a bit):

Code (Text):

/* Character Filtration Algorithm */

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

int main()
{
ifstream data;
ofstream out;
char ch;
int sum;

data.open("numbers.txt"); // Open Input Data File
if (not data){
cout << "Can't open numbers.txt" << endl;
system ("pause");
return 1;}

out.open("out.txt"); // Generate Output Data File
if (not out){
cout << "Can't open out.txt" << endl;
system ("pause");
return 1;}

data.get(ch); // Priming Read for End-of-File Loop
while (data){ // End-of-File Loop
sum = 0;

while((ch != '\n') and data){

if(isdigit(ch)){ // Test for digit
sum = (10*sum)+(ch-'0'); // Sum Assignment
}

if((ch == '#')){ // Test for '#'
out << sum << endl;
sum = 0;
}

data.get(ch); // Next Character
} // Inner Loop

if (sum > 0){ // Test for Sum
out << sum << endl;
}

data.get(ch);
} // End-of-File Loop

cout << "Program Successful " << endl;

system ("pause");
data.close(); out.close(); // Close Data Files
return 0;
}

Last edited: Feb 24, 2014