Thread: Need help with probably a very simple char sting issue

  1. #1
    Registered User
    Join Date
    Jan 2007
    Posts
    7

    Need help with probably a very simple char sting issue

    Today I got back to a little programming after a long time.


    Ok, the thing I am trying to do is read a DNA-like code from a text file. It consists out of A, B, C and D's This all works.

    Because every three letters of the code together have a meaning I need to read the first three letters from the file, look which combination it is and do something. I try to use an if statement.


    Code:
    char triplet[3];
    
    [...]
    
    if ( strncmp ( triplet, "ABC", 3 ) == 0 )[/quote] { [...] }
    This has the problem that "ABC" isn't a constant. So I change it to

    Code:
    char strABC[] = { "ABC"};
    if ( strncmp ( triplet, strabc, 3 ) == 0 )[/quote] { [...] }

    There is no difference between strcmp and strncmp, it seems.

    This doesn't seem to work though the program clearly says that triplet[1] is A, triplet[2] is B and triplet[3] is C.

    Strangely enough if I give the command cout<<triplet I get strange symbols on stopts 0 4 5 and 6.

    Ok, I am being stupid here, I guess. What am I doing wrong?

  2. #2
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    >> This has the problem that "ABC" isn't a constant
    "ABC" is a constant. Were you getting an error, what was the exact text of the error?

    >> There is no difference between strcmp and strncmp, it seems.
    There is. strncmp will only compare as many characters as you tell it, while strcmp will compare until it finds a null (or a difference). This is a problem since your triplet array does not leave space for the null character (which is also why it outputs the strange characters).

    If you are trying to use C++, consider using C++ strings instead of C style strings. They will make your job much easier.

  3. #3
    The larch
    Join Date
    May 2006
    Posts
    3,573
    This doesn't seem to work though the program clearly says that triplet[1] is A, triplet[2] is B and triplet[3] is C.
    Array indices start at 0 in C and C++. So the first character would be at triplet[0] and last at triplet[2].

  4. #4
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    And for a string to be used with strcmp the null character would be at triplet[3] if that had been allocated properly, but in this case triplet[3] is past the bounds of the array.

  5. #5
    Registered User
    Join Date
    Jan 2007
    Posts
    7
    I will post the exact error concerning invalid conversion of char and const char later. I am on a different computer right now.


    Using C++ style, you mean using std::string? I will if it's recommended.

    So I will also need other functions for std::string?



    As for the possible solution given. Thanks. I will try that later. Yes, I now remember I used to forget strings start at 0 years ago as well.


    But, I think that the actual first character somehow was in 1 and not in 0. Hmm. I'll figure that out later.

  6. #6
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    >> Using C++ style, you mean using std::string? I will if it's recommended.
    Yes, I'd definitely recommend it for C++ programming.

    I'm not sure how you are reading in your strings right now. If there is no whitespace between each three letter combination, then you would probably want to read in a character at a time and append it to the string (using +=). To compare your string variable with "ABC" you would just use == like comparing integers.

  7. #7
    Registered User
    Join Date
    Apr 2003
    Posts
    2,663
    This has the problem that "ABC" isn't a constant
    Yes it is. Whenever C++ sees something between double quotes, it slaps a \0 onto the end of it and stores it in memory somewhere, like this:

    ABC\0

    C++ also makes the string a constant, so you cannot change it.

    There is no difference between strcmp and strncmp, it seems.
    Run this code to see the difference:
    Code:
    //declare char array and initialize it with a "string literal":
    char triplet[] = "ABCD";
    
    
    //strncmp:
    if ( strncmp ( triplet, "ABC", 3 ) == 0 )
    {
    	cout<<"strncmp: they are the same"<<endl;
    }
    else
    {
    	cout<<"strncmp: they are different"<<endl;
    }
    
    //strcmp:
    if ( strcmp ( triplet, "ABC") == 0 )
    {
    	cout<<"strcmp: they are the same"<<endl;
    }
    else
    {
    	cout<<"strcmp: they are different"<<endl;
    }
    When you do this:

    cout<<triplet;

    that says to keep outputting the characters in the triplet array until a \0 character is encountered. If there is no \0 character in the array, C++ will overrun the end of the array, and print out any junk characters it encounters.

    With the code example I posted, you can get the correct output like this:

    cout<<triplet

    But, why doesn't C++ overrun the end of the array and print out the junk characters in that code? After all there's no \0 in the assignment statement:

    char triplet[] = "ABCD";

    Also, you can do this with triplet:

    triplet[0] = 'X';
    cout<<triplet; //outputs: XBCD

    yet I said that C++ slaps a \0 onto the end of "ABCD" forming the string "ABCD\0" and makes the result a constant.

    The answer to both those questions is that when you do the assignment:

    char triplet[] = "ABCD";

    C++ first slaps a \0 on the end of the string "ABCD" and stores "ABCD\0" in memory as a constant. Then C++ creates an array called triplet that is 5 characters long to match the number of characters in the constant string stored in memory. Then C++ copies the first character of "ABCD\0" into the triplet array at triplet[0], and then it copies the second character into triplet[1], etc., and then it copies the last character, which is the \0 into triplet[4]. Therefore, the triplet array just contains a bunch of single characters copied from elsewhere, and you are free to change the characters stored in the triplet array. Changing the characters in the triplet array has no effect on the constant string "ABCD\0" that is stored in memory because the characters are copies.
    Last edited by 7stud; 01-10-2007 at 07:24 PM.

  8. #8
    Registered User
    Join Date
    Jan 2007
    Posts
    7
    Ok it seems I can slowly fix the bugs.

    But I have one major problem of a slightly different nature.

    I have a function that checks the ABC-combinations and then writes to a file.

    But I have to do the ofstream file ( "file.txt" ) inside the function. Otherwise it is undefined. But then every time the function is called it creates a new version of the file.

    But if I try to create the ofstream file ( "file.txt" ) and then try to pass it through to the function this doesn't work.
    Another way would to return the char string data I want to put in a text file by returning this. But I can't have a function that returns an array of char's it seems.

    How do I do this?
    Last edited by Prometheus; 01-10-2007 at 07:17 PM.

  9. #9
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    >> if I try to create the ofstream file ( "file.txt" ) and then try to pass it through to the function this doesn't work.
    When something doesn't work it is best to explain how it doesn't work and post the error messages you are getting. In this case, your problem might be that you need to pass the ofstream variable by reference to the function. You could also use std::ios::app to always append to the file if you open it again each time in the function, but that wouldn't be as good of a solution as just passing it in by reference.

    >> But I can't have a function that returns an array of char's it seems.
    You really should switch to C++ strings. Returning a C++ string is easy to do (you return a string like you would return an int). Otherwise, if you stick with C style strings, it would be best to pass in the array as an argument and then fill it in the function. This leads to all kinds of memory maintenance issues, though, which is another reason to use C++ strings.

  10. #10
    Registered User
    Join Date
    Jan 2007
    Posts
    7
    I meant that if I try this:

    Defining the function
    Code:
    void check(char triplet[2], ofstream file);
    Then creating the ofstream and then calling the function:
    Code:
    ofstream file ( "file.txt" );
    check(triplet, ofstream file);


    I get this error:
    Code:
    expected primary-expression before "file" 
    In function `void check(char*, std::ofstream)':
    I'll try to switch to strings tomorrow.

  11. #11
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    That's what I figured it was. You have to pass the ofstream by reference.

  12. #12
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Ireland
    Posts
    8,446
    > check(triplet, ofstream file);

    You don't specify the arguments type when calling the function. check(triplet, file);
    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

  13. #13
    Registered User
    Join Date
    Apr 2003
    Posts
    2,663
    If you are just getting back into programming, I would avoid passing anything but simple types to functions. You have forgotten that when things get passed to functions, they get copied, so the function uses the copy, and the original remains unchanged.

  14. #14
    Registered User
    Join Date
    Apr 2003
    Posts
    2,663
    expected primary-expression before "file"
    unexpected primary-expression before "file"?

    When you have a problem you also need to identify the line in your code that the error states is the problem. Here is an example:

    I am getting the error:
    line 30: blah, blah, blah
    in the code:
    Code:
    if ( strncmp ( triplet, "ABC", 3 ) == 0 )
    {
    	cout<<"strncmp: they are the same"<<endl;  //***ERROR***
    }
    else
    {
    	cout<<"strncmp: they are different"<<endl;
    }
    Last edited by 7stud; 01-10-2007 at 07:55 PM.

  15. #15
    Registered User
    Join Date
    Jan 2007
    Posts
    7
    I just looked up what a reference is in one of my old books. Yes, I didn't remember.

    After some fiddeling it seems that everything is now actually working.

    Now I can sleep peacefully. Thanks.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. seg fault at vectornew
    By tytelizgal in forum C Programming
    Replies: 2
    Last Post: 10-25-2008, 01:22 PM
  2. Replies: 16
    Last Post: 10-29-2006, 05:04 AM
  3. comparing fields in a text file
    By darfader in forum C Programming
    Replies: 9
    Last Post: 08-22-2003, 08:21 AM
  4. I'm having a problem with data files.
    By OmniMirror in forum C Programming
    Replies: 4
    Last Post: 05-14-2003, 09:40 PM
  5. simulate Grep command in Unix using C
    By laxmi in forum C Programming
    Replies: 6
    Last Post: 05-10-2002, 04:10 PM