1. Limited time only! Sign up for a free 30min personal tutor trial with Chegg Tutors
    Dismiss Notice
Dismiss Notice
Join Physics Forums Today!
The friendliest, high quality science and math community on the planet! Everyone who loves science is here!

C++ Character Processing Algorithm

  1. Feb 22, 2014 #1
    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. jcsd
  3. Feb 22, 2014 #2

    lewando

    User Avatar
    Gold Member

    What is your output? Examining that can provide some clues.
     
  4. Feb 22, 2014 #3
    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.
     
  5. Feb 22, 2014 #4

    lewando

    User Avatar
    Gold Member

    Okay, getting no output is a big clue! Your first character is a '@'. How is your code processing that?
     
  6. Feb 22, 2014 #5
    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).
     
  7. Feb 22, 2014 #6
    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.
     
  8. Feb 22, 2014 #7

    lewando

    User Avatar
    Gold Member

    You need to also process the newline '\n' inside your loop. Encountering one is significant. I think you'll get it--good luck!
     
  9. Feb 22, 2014 #8
    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;
    }        
     
     
  10. Feb 22, 2014 #9

    lewando

    User Avatar
    Gold Member

    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
  11. Feb 23, 2014 #10

    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.
     
  12. Feb 23, 2014 #11
    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.
     
  13. Feb 24, 2014 #12
    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;
    }
     
     
  14. Feb 24, 2014 #13

    Mark44

    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.
     
  15. Feb 24, 2014 #14

    AlephZero

    User Avatar
    Science Advisor
    Homework Helper

    http://en.cppreference.com/w/cpp/keyword
     
  16. Feb 24, 2014 #15

    lewando

    User Avatar
    Gold Member

    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.
     
  17. Feb 24, 2014 #16
    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
Know someone interested in this topic? Share this thread via Reddit, Google+, Twitter, or Facebook

Have something to add?
Draft saved Draft deleted