CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 6 of 6
  1. #1
    Join Date
    May 2009
    Location
    Boston
    Posts
    364

    parsing of char array won't finish

    I have some cpp code that is looping through an array of char looking for a delimiter. The code saves the chars in a string until it finds the delimiter, then it adds the string to a vector of string and continues processing.

    The input char array is,
    Cl.N1C=CC=N1.HCl
    the delimiter is '.', so the parsed strings should be,
    Cl
    N1C=CC=N1
    HCl

    The code seems to work find for the first two strings, but then it seems to stop and not find the third string.

    This is the code,
    Code:
    #include <iostream>
    #include <vector>
    #include <string>
    
    extern "C" { int parse_string_test_( char *INP_PASS, int *LENGTH); }
    
    int parse_string_test_( char *INP_PASS, int *LENGTH ) {
    
       vector<string> found_fragments;
       string temp_read;
       int i, passed_length;
    
       // number of occupied positions in passed char array
       passed_length = *LENGTH;
    
       // print initial values
       cout << "char array" << endl;
       cout << "LENGTH " << passed_length << endl;
       for(i=0; i<passed_length; i++) { cout << INP_PASS[i]; }
       cout << endl;
       cout << endl;
    
       // parse char array into strings using . as delimiter
       for(i=0; i<passed_length; i++) {
    
          // add characters to temp_read until delimiter is found
          if(INP_PASS[i] != '.') {
             temp_read.push_back(INP_PASS[i]);
          }
    
          // when delimiter is found
          else if(INP_PASS[i] == '.') {
    
             // add temp read string to vector of string
             found_fragments.push_back(temp_read);
    
             cout << "temp_read " << found_fragments.size() << endl;
             cout << temp_read << endl;
    
             // clear temp read structure to continue looking for next string
             temp_read.clear();
          }
       }
    
    return 0;
    }
    The output from he above is,
    char array
    LENGTH 16
    Cl.N1C=CC=N1.HCl

    temp_read 1
    Cl
    temp_read 2
    N1C=CC=N1

    ...then nothing. The function returns to the calling code, but may not have returned normally, it is hard to tell.

    This appears to work up to a point, but does not find the last string HCl. The size of the char array that is passed to the functions prints as correct (16), so the for loop should process all 16 characters in the array. I don't see here why it stops.

    This was compiled using g++-3. Some of the unusual syntax results from this being a cpp function that is called from fortran. The char array that is passed to the cpp prints as correct and has the correct size, so I don't think that is part of the problem.

    Any suggestions,

    Thanks,

    LMHmedchem
    Last edited by LMHmedchem; May 6th, 2013 at 12:58 PM.

  2. #2
    Join Date
    May 2009
    Location
    Boston
    Posts
    364

    Re: parsing of char array won't finish

    Once again, now that I have written the whole thing up, I see the problem. I swear that writing up a post is the best debugging exercise. The third string isn't found because there is no trailing delimiter to let the code know that it has found a third string. I guess I need to add an else for where the loop gets to the end of the char array.

    LMHmedchem

  3. #3
    GCDEF is offline Elite Member Power Poster
    Join Date
    Nov 2003
    Location
    Florida
    Posts
    12,635

    Re: parsing of char array won't finish

    Running the program in the debugger is the best debugging exercise.

  4. #4
    Join Date
    May 2009
    Location
    Boston
    Posts
    364

    Re: parsing of char array won't finish

    Quote Originally Posted by GCDEF View Post
    Running the program in the debugger is the best debugging exercise.
    Unfortunately, I have had great trouble getting gdb to play nicely with g77. If anyone has a good writeup on how to do that, I would appreciate a link.

    I add a second conditional in the for loop.

    Code:
         #include <iostream>
    #include <vector>
    #include <string>
    
    extern "C" { int parse_string_test_( char *INP_PASS, int *LENGTH); }
    
    int parse_string_test_( char *INP_PASS, int *LENGTH ) {
    
       vector<string> found_fragments;
       string temp_read;
       int i, passed_length;
    
       // number of occupied positions in passed char array
       passed_length = *LENGTH;
    
       // print initial values
       cout << "char array" << endl;
       cout << "LENGTH " << passed_length << endl;
       for(i=0; i<passed_length; i++) { cout << INP_PASS[i]; }
       cout << endl;
       cout << endl;
    
       // parse char array into strings using . as delimiter
       for(i=0; i<passed_length; i++) {
    
          // add characters to temp_read until delimiter is found
          if(INP_PASS[i] != '.') {
             temp_read.push_back(INP_PASS[i]);
          }
    
          // when delimiter is found
          else if(INP_PASS[i] == '.') {
    
             // add temp read string to vector of string
             found_fragments.push_back(temp_read);
    
             cout << "temp_read " << found_fragments.size() << endl;
             cout << temp_read << endl;
    
             // clear temp read structure to continue looking for next string
             temp_read.clear();
          }
    
          // look for end of char array, if found, add final string to string vec 
          if(i == passed_length-1) {
             // add temp read string to vector of string
             found_fragments.push_back(temp_read);
    
             cout << "temp_read " << found_fragments.size() << endl;
             cout << temp_read << endl;
          }
    
       }
    
    return 0;
    }
    Now the print out is correct,
    char array
    LENGTH 16
    Cl.N1C=CC=N1.HCl
    temp_read 1
    Cl
    temp_read 2
    N1C=CC=N1
    temp_read 3
    HCl

    This appears to be a reasonable way to accomplish the task, but it's not exactly a fine example of oo code. Are there any suggestions on better ways to do this? At the end of the day, I am looking for the longest fragment string to pass back to the calling function. In this example, N1C=CC=N1 would be passed back and the other two strings discarded.

    LMHmedchem

  5. #5
    Join Date
    Apr 1999
    Posts
    27,449

    Re: parsing of char array won't finish

    Code:
    extern "C" { int parse_string_test_( char *INP_PASS, int *LENGTH); }
    The INP_PASS is not changed. You should change the prototype to this:
    Code:
    extern "C" { int parse_string_test_( const char *INP_PASS, int *LENGTH); }
    Otherwise, it gives the impression that your function can change the contents of the buffer that INP_PASS points to.
    This appears to be a reasonable way to accomplish the task, but it's not exactly a fine example of oo code. Are there any suggestions on better ways to do this?
    Write or get a generic parser/tokenizer that tokenizes a string based on a delimiter (boost has one).

    Regards,

    Paul McKenzie

  6. #6
    2kaud's Avatar
    2kaud is offline Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,822

    Re: parsing of char array won't finish

    Not elegant, but try this. It returns the longest fragment string.

    Code:
    #include <iostream>
    #include <string>
    using namespace std;
    
    const char DELIM = '.';
    
    string parse_string_test_(const char *const INP_PASS, const int *const LENGTH)
    {
    string	temp_read,
    	longest;
    
    	//parse char array into strings using . as delimiter
    	for (int i = 0; i < *LENGTH; i++) {
    
    		// add characters to temp_read until delimiter is found
    		if ((INP_PASS[i] != DELIM) && (i != *LENGTH - 1))
    			temp_read += INP_PASS[i];
    		else {
    			//If end of input and last char not a '.' add last char to string
    			if ((i == *LENGTH - 1) && (INP_PASS[i] != DELIM))
    				temp_read += INP_PASS[i];
    
    			//Save temp string if size greater than previous largest string
    			if (temp_read.size() > longest.size())
    				longest = temp_read;
    
    			// clear temp read structure to continue looking for next string
    			temp_read = "";
    		}
    	}
    	return longest;
    }
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++23 Compiler: Microsoft VS2022 (17.6.5)

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured