Posted By: BenZillaTheSecond | Aug 22nd, 2007 @ 6:22 PM
page 1 of 1
Comments: 9 | Views: 5246
Hallo guys and gals long time no speak Smiley

As teh title suggests I'm having problems with strcmp in C, basically when I use it I crash the program and I'm trying to work out how to fix it.

I am working on a file loader which has the basic skinny of.

    char c;

Yadda yadda file opening stuff all works good.

  c = fgetc(file);

yaddda yadda

strcmp( c, ","  );

bam it crashes, I hve no idea why, because if I send it something like strcmp( ",", ","  ); it works.

Any help would be appreciated.
CannotResolveSymbol
CannotResolveSymbol
{insert caption here}
Strcmp takes char*, not char, because char is just a single character.  String literals in C are treated like char*, so strcmp("blah", "blah"); works fine.

And C will quite happily let you do it, too...  fun!  (Visual C++ in C mode will give you a warning, though.  How nice of it.)
CannotResolveSymbol
CannotResolveSymbol
{insert caption here}
BenZillaTheSecond wrote:
Ok Smiley But I only want to compare a single char, it's a CSV reader so I'm trying to find the ',' in the file.

Basically this is what I'm doing and I can't work out why it's crashing :z

        // need to keep looping
        while (1) {
            // current character in teh file is stored
            c = fgetc(file);
            // not at the end of the file
            if (c != EOF) {

                if( c ) {

                    // check for terminator and check whats in the cell
                    if (strcmp( c, ","  )) {
                        //char *tempchar = c++;
                        printf("hi");
                    }
                }

Ergh!


If you're just comparing a single char, why are you using strcmp and not == ?

So, just do:

if(c == ','){
  printf("hi");
}

Strcmp compares two strings, not two characters (despite what the signature may suggest).  Ah, the joy of overcomplicating things Tongue Out

Let me know if I'm completely missing something here.
BlueFirehawk02
BlueFirehawk02
I Code, Therefore, I Am

BenZillaTheSecond wrote:
Ok Smiley But I only want to compare a single char

// streamlined further
while((c = fgetc(file)) != EOF)
{
  // check for terminator and check whats in the cell
  if(c == ',')
     print("hi");
}

Matthew van Eerde
Matthew van Eerde
AKA Maurits
If you want to use strcmp with a single character you could build your own string:

char string[2] = { '\0', '\0' };
string[0] = fgetc(file);

... strcmp(string, ...) ...
Or, if you just need a function to break up the CSV file by a delimiter (in this case, a comma), you could also use strtok.
evildictaitor
evildictaitor
How could you use the adjective "indescribable" truthfully?
thumbtacks2 wrote:
Or, if you just need a function to break up the CSV file by a delimiter (in this case, a comma), you could also use strtok.


strtok isn't threadsafe btw.
evildictaitor wrote:

thumbtacks2 wrote:Or, if you just need a function to break up the CSV file by a delimiter (in this case, a comma), you could also use strtok.


strtok isn't threadsafe btw.


Nor is it wise as it probably won't catch "this is the first, item","this is the second".  That problem aside Microsoft may (dunno) supply the re-entrant version of strtok called strtok_r
Matthew van Eerde
Matthew van Eerde
AKA Maurits
CSV parsing in general is harder than it looks.  Here's an off-the-cuff algorithm...

row = 0;
column = 0;

bool parse_file() {
    // read a line at a time
    while (true) {
        // an empty file is perfectly valid
        if (EOF) return true;
        column = 0;
        if (!parse_line()) { return false; }
        row++;
    }
}

bool parse_line() {
    string value;

    // read a value at a time
    while (true)
        // the last character must be a newline character
        // (if you like you can count EOF as a newline)
        // an empty line is perfectly valid
        if (\n) { eat it; return true; }

        // a comma signals an empty value
        if (,) {
            eat it;
            val = (empty);
        } else if (!parse_value(&val)) {
            return false;
        }
        column++;
        add(row, column, val); // stick the data somewhere

        // values must be followed by a comma or end-of-line
        if (,) {
            eat it;
        } else if (\n) { // or EOF, perhaps
            // fine, continue
        } else {
            return false;
        }
}

bool parse_value(string &val) {
    if (") {
        return parse_quoted_value(&val);
    } else {
        return parse_unquoted_value(&val);
    }
}

bool parse_unquoted_value(string &val) {
    val = "";
    // quotes are errors
    // commas, newlines (and EOF?) signal the end
    while (true) {
        if (") { return false; }
        if (, or \n (or EOF?)) { return true; } // don't eat it
        val += the char;
        eat it;
    }
}

bool parse_quoted_value(string &val) {
    val = (empty);
    if (!") { return false; }
    eat it; // the quote
    while (true) {
        // EOF in the middle is an error
        if (EOF) { return false; }

        if (") {
            eat it;
            // quote followed by comma, newline, or EOF is the end
            if (, or \n or EOF) {
                return true; // don't eat it
            // quote followed by another quote is a literal quote
            } else if (") {
                eat it;
                val += ";
            // quote followed by anything else is an error
            // you might be liberal and allow whitespace after closing quotes
            // but eventually there should be a comma or \n or EOF
            } else {
                return false;
            }
        } else {
            eat it;
            val += the char;
        }
    }
}