tags:

views:

142

answers:

2

I am converting code from C to C++. I am currently using the C function, isspace, what is the C++ equivalent when using an ifstream? Specifically while (!isspace(lineBuffer[l]))

id is the first the number (2515, 1676, 279) and name is the set of letters after the first "space" (ABC, XYZ, FOO).

Example NewList.Txt

2515    ABC 23.5    32  -99 1875.7  1  
1676    XYZ 12.5    31  -97 530.82  2  
279  FOO 45.5    31  -96  530.8  3  

C Code

void converter::updateNewList(){
    FILE* NewList;
    char lineBuffer[100];
    char* id = 0;
    char* name = 0;

    int l = 0;
    int n;

    NewList = fopen("NewList.txt","r");
    if (NewList == NULL){
        std::cerr << "Error in reading NewList.txt\n";
        exit(EXIT_FAILURE);
    } 

    while(!feof(NewList)){
        fgets (lineBuffer , 100 , NewList); // Read line    
        l = 0;
        while (!isspace(lineBuffer[l])){
            l = l + 1;
        }

        id = new char[l];
        switch (l){
            case 1: 
                n = sprintf (id, "%c", lineBuffer[0]);
                break;
            case 2:
                n = sprintf (id, "%c%c", lineBuffer[0], lineBuffer[1]);
                break;
            case 3:
                n = sprintf (id, "%c%c%c", lineBuffer[0], lineBuffer[1], lineBuffer[2]);        
                break;
            case 4:
                n = sprintf (id, "%c%c%c%c", lineBuffer[0], lineBuffer[1], lineBuffer[2],lineBuffer[3]);
                break;
            default:
                n = -1;
                break;
        }
        if (n < 0){
            std::cerr << "Error in processing ids from NewList.txt\n";
            exit(EXIT_FAILURE);
        }

        l = l + 1;
        int s = l;
        while (!isspace(lineBuffer[l])){
            l = l + 1;
        }
        name = new char[l-s];
        switch (l-s){
            case 2:
                n = sprintf (name, "%c%c", lineBuffer[s+0], lineBuffer[s+1]);
                break;
            case 3:
                n = sprintf (name, "%c%c%c", lineBuffer[s+0], lineBuffer[s+1], lineBuffer[s+2]);
                break;
            case 4:
                n = sprintf (name, "%c%c%c%c", lineBuffer[s+0], lineBuffer[s+1], lineBuffer[s+2],lineBuffer[s+3]);
                break;
            default:
                n = -1;
                break;
        }
        if (n < 0){
            std::cerr << "Error in processing short name from NewList.txt\n";
            exit(EXIT_FAILURE);
        }


        ids_.push_back ( std::string(id) );
        names_.push_back(std::string(name));
    }

    bool isFound = false;
    for (unsigned int i = 0; i < siteNames_.size(); i ++) {
        isFound = false;
        for (unsigned int j = 0; j < names_.size(); j ++) {
            if (siteNames_[i].compare(names_[j]) == 0){
                isFound = true;
            }
        }
    }

    fclose(NewList);
    delete [] id;
    delete [] name;
}

C++ CODE

void converter::updateNewList(){
    int l = 0;
    char c;

    std::ifstream radesNewList ("NewList.txt",std::ios::in|std::ios::ate);
    NewList.seekg(std::ios_base::beg);

    std::string line;
    while(!NewList.eof()){
        l = 0;
        getline(radesNewList,line);

        for (size_t i=0; i<line.length(); ++i){
            c=line[i];
            bool isWhiteSpace = std::isspace(c, std::locale("C")); 
            if (isWhiteSpace){
                l = i+1;
                break;
            }       
        }

        ids_.push_back (line.substr(0,l));

        int s = l;
        for (size_t i=l; i<line.length(); ++i){
            c=line[i];
            bool isWhiteSpace = std::isspace(c, std::locale("C")); 
            if (isWhiteSpace){
                l = i+1;
                break;
            }       
        }
        names_.push_back(line.substr(s,l-s));
        line.clear();
    }

    NewList.close();
}
+8  A: 

std::isspace(). (Or, more fully qualified, template <typename T> bool std::isspace(T c, const std::locale& loc). Exact declaration may vary between compilers.)

Jonathan Grynspan
Can you please provide an example?
Elpezmuerto
Jonathan Grynspan
@Jonathan: not exactly the way you use C's `isspace`. For the C function, if the value you want to test is a `char` you need to cast it to an unsigned type. For the C++ template, you can just pass in a `char` and it's valid for that value to be negative.
Steve Jessop
Do I need to create a `locale` variable then? I never used `locale` before and still little confused looking at the documentation for it.
Elpezmuerto
How is the declaration allowed to vary between compilers?
Charles Bailey
@Steve: I know, I know. @Elpezmuerto: Depends how you're using it. Again, what are you trying to accomplish? @Charles: Compilers can provide specializations (e.g. for `char`), or can decorate declarations with something like `__attribute__((__pure__))` (a GCCism.) Or they might just name parameters differently.
Jonathan Grynspan
I am trying to find the whitespace between characters. The C++ code I show does this, but according to David Thornley this is different than `isspace`
Elpezmuerto
An explicit specialization doesn't affect the declaration of the template; any decoration can't have a visible (to a conforming program) effect on the type and a change of parameter names has not effect on the type or template name. I guess you're using 'exact' in a stricter sense than I would.
Charles Bailey
@Charles: I meant exact as in "character for character, your header file may differ from this." That's all.
Jonathan Grynspan
@Elpezmuerto: It's different because the definition of "whitespace" can vary. (Now, in practice, it ain't gonna, but folks on SO are usually aiming for strict correctness.) The question I asked before still stands: *Whose* whitespace? Are you parsing files created by Bolivians? By Americans? Are you parsing files that are intended for use with a C compiler? What? Answer that and then we can very quickly show you what you should do.
Jonathan Grynspan
Sample input is posted
Elpezmuerto
So it's machine-readable/machine-generated input? In that case, you'll presumably be expecting the input to be well-formed--it won't have any strange Bolivian whitespace unknown to the average C++ programmer. You'll probably want the "C" locale, which avoids any actual localization: `bool isWhiteSpace = std::isspace(theCharacter, std::locale("C"));` This example can of course be optimized further, but doing so is an exercise left up to the reader. ;) Note that the "C" locale would be appropriate for whitespace, but probably not for letters, digits, etc.
Jonathan Grynspan
@Jonathan, that does it! I am very glad SO aims for strict correctness.
Elpezmuerto
+2  A: 

I'm not aware of anything from the C89 standard lib that isn't available for C++. (It's different for C99, which was released after the current C++ standard and contains a few things-like complex-that can never make it into the C++ standard.)

Generally, just include the C header replacing the .h suffix with a c prefix (<ctype.h> becomes <cctype> and <string.h> becomes <cstring>) and remember that most of the identifiers (with the exclusion of macros) needs a std:: prefix.

Particularly, include <cctype> and std::isspace(ch) works in C++ as it works in C.

sbi