-
May 6th, 2013, 12:54 PM
#1
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.
-
May 6th, 2013, 01:00 PM
#2
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
-
May 6th, 2013, 01:08 PM
#3
Re: parsing of char array won't finish
Running the program in the debugger is the best debugging exercise.
-
May 6th, 2013, 01:16 PM
#4
Re: parsing of char array won't finish
Originally Posted by GCDEF
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
-
May 6th, 2013, 03:12 PM
#5
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
-
May 6th, 2013, 03:31 PM
#6
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
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|