0

I am trying to convert a C/C++ class into a Java equivalent. It's going ok so far but I've got to this bit of code and Java is complaining.

// Isolate each byte in turn
cRecByte = lpszRec[ lRecByteCount++ ] & 0x00FF;

cRecByte is a char

lpszRec is a LPCSTR

lRecByteCount is a long

This works in the C++ code but won't work in Java.

In my Java code I have exactly the same line with the following differences

cRecByte is a char

lpszRec is a String

lRecByteCount is a long

The errors I get (as I'd expect) are

 Type mismatch: cannot convert from int to char
 Type mismatch: cannot convert from long to int

For some context I'm trying to re-write/emulate a Hash Totaling function that was written in the 1980's that is still used by our legacy systems today. Replacing them with something new would cost a fortune in dev/test costs so I have to continue along this path.

The piece of code I've put up is designed to separate out each character from a given record (line of text).

Any help would greatly appreciated.

Some code as requested - This is from the C++ file. I've only gone as far as where I've got to as the actual class is quite large.

void CHashTotalFile::CalcRecHashTotal( /*[in]*/     LPCSTR lpszRec,
                                       /*[in]*/     DWORD dwRecLen, 
                                       /*[in]*/     long lIteration, 
                                       /*[in,out]*/ UINT64& u64HashTotal,
                                                    SYSTYPE stType ) throw()
{
    char    cRecByte;
    LPCSTR  szNullReplacer = "CALCULATE HASH TOTAL";

    const static int  nLenNullReplacer = lstrlenA( szNullReplacer );
    const static char szRandomMap[] = { 17,
                                        5,
                                        37,
                                        31,
                                        53,
                                        19,
                                        41,
                                        7,
                                        11,
                                        2,
                                        23,
                                        3,
                                        29,
                                        47,
                                        43,
                                        13 };

    // 64bit unsigned integer data types:
    UINT64  u64ByteValue;
    UINT64  u64Carry;

    // long data types:
    long    lByteWord;      // Used in u64ByteValue & offset to random map
    long    lRecByteCount;  // Byte count within (actual) record  - used as subscript to data
    long    lRecByteIndex;  // Byte count within (logical) record - used in hashing calculations

    // int data types:
    int     nAttempts;
    int     nByteDistance;  // 'random' distance which rotates (right) the hash total
    int     nHashDistance;  // 'random distance which rotates (left) the hash total
    int     nWordValue;     // From data - offset to random map for hash distance
    bool    bGenerated = false;

    // No exception calls or error logging here as efficiency is the name of the game!
    // (or not so much inefficiency!)

    // If text & this is a blank line (i.e. \n) set to record length to zero
    if( m_fText && lpszRec[0] == NEWLINE_CHARACTER  )
        dwRecLen = 0;

    // use dummy string where no data
    if( dwRecLen == 0 )
    {
        lpszRec = szNullReplacer;
        dwRecLen = nLenNullReplacer;
    }

    for( nAttempts = 0; (nAttempts <= MAX_HASH_ATTEMPTS) && !bGenerated; nAttempts++ )
    {
        // Loop around every byte in the record
        for( lRecByteCount = lRecByteIndex = 0L; lRecByteCount < dwRecLen; lRecByteIndex++ )
        {
            // Isolate each byte in turn
            cRecByte = lpszRec[ lRecByteCount++ ] & 0x00FF;

            if( m_fText )   // If text
thonnor
  • 1,206
  • 2
  • 14
  • 28
  • 3
    Could you post a [mcve] so we don't have to piece one together from your clues? – khelwood Oct 06 '16 at 16:09
  • 2
    Try casting from `long` to `int`? – erip Oct 06 '16 at 16:09
  • 5
    `lpszRec[...]` won't work with a string, try `lpszRec.charAt(...)` or `lpszRec.toCharArray()[...]` instead (and with an `int` index ofc). Yet better you might want to use `lpszRec.getBytes("whatever encoding you need")[...]`. – Thomas Oct 06 '16 at 16:11
  • Some code added for further context – thonnor Oct 06 '16 at 16:15
  • Maybe it shouldn't even be a `String` at all, just a `byte` array (or `Vector`)? – mindriot Oct 06 '16 at 16:17
  • 1
    @Thomas - would the lpszRec.getBytes() mean that I wouldn't require the bitwise bit that is causing the problem? – thonnor Oct 06 '16 at 16:18
  • Try to split the expression into multiple lines - that will make it more obvious where your problems are. (and show us the java code - we can only guess what you really tried at the moment). – Hulk Oct 06 '16 at 16:21
  • probably related: [Why can I assign an integer literal to a short type variable but not to a short type method parameter?](http://stackoverflow.com/q/39886332/2513200) and [Primitive type 'short' - casting in Java](http://stackoverflow.com/a/477769/2513200) – Hulk Oct 06 '16 at 16:27
  • 1
    @thonnor what bytes you'd get would depend on the encoding but you'd not have to isolate them then so it _might_ solve your problem. – Thomas Oct 07 '16 at 08:26

1 Answers1

1

I see multiple separate problems here:

  1. Array indices are always int

    long l = 0;
    int[] i = new int[] { 1, 2, 3 };
    int res1 = i[l]; //Error: Type mismatch: cannot convert from long to int
    int res2 = i[(int)l]; //works
    
  2. Strings can not be directly accessed as arrays - you need to either convert it to an array first or use an accessor:

    String testString = "TESTSTRING";
    char c1 = testString[0]; //Error: The type of the expression must be an array type but it resolved to String  
    char c2 = testString.charAt(0); //works
    
  3. The result of an operation between a char and an int is an int - you need to cast explicitly if you want to store it as a char:

    char c = 'h';
    char var1 = c & 0x00FF; //Error: Type mismatch: cannot convert from int to char
    char var2 = (char) (c & 0x00FF); //works
    
Hulk
  • 6,399
  • 1
  • 30
  • 52
  • Thank you. Good answer. Why will the error in No 3 work in C though? This is my confusion. I don't know the ramifications of leaving the &0x00FF out all together. – thonnor Oct 06 '16 at 16:53
  • Because C++ is a different language with different rules. – Hulk Oct 06 '16 at 17:14
  • Yeah I get that. But because so much of the code I'm "porting to Java" is so similar I was hoping this bit I'm stuck on would be the same. Thanks for your help, you've given me some good advice which I'll try at work tomorrow. – thonnor Oct 06 '16 at 17:24
  • More specifically - the bitwise operator `&` is defined as `T T::operator&(const T2 &b) const;` in C++. – Hulk Oct 06 '16 at 17:25