Need beginner help with C (LabWindows/CVI)!

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • lgerhardx@hotmail.com

    #1

    Need beginner help with C (LabWindows/CVI)!

    First of all, please forgive my newness to the language. I have had
    much experience programming...b ut not in C! :)

    I am modifying a program designed in LabWindows/CVI, which as far as I
    can tell is a version of ANSI C. The program needs to communicate
    with my AS/400 via sql/odbc to retrieve some information about a
    barcode scanned part.

    This works. Once. After that, it blows up on the SQLPrepare
    command. I have no idea why, and I really don't understand where I've
    failed. Any guidance would be greatly appreciated as I try to learn
    this language in a matter of days to complete this project... >_<

    Below you will find the procedures that I have added for the AS400
    connection, per research I did online. In the opening process of the
    program it calls DBopen. Then, I am simulating a barcode scan by
    calling a procedure TestAS400. It asks for a barcode label and then
    uses that in a dynamic sql statement. As I said, this works the first
    time. The first time I get the following output:
    --------------------------
    [data]
    DONE,BYE
    --------------------------
    The second time I get the last 15 characters of the sql statement
    followed by 'Error or SQLPrepare!!', then "error!', then "DONE,BYE".

    I just don't get it! Is my connection not being closed properly? How
    do I fix this? Any ideas are very much appreciated.

    Oh, and even though I only wanted one field returned from my sql
    statement, I had to make the statement ask for two or my variable
    would be corrupted?! I really am being tossed in to this. Sorry if
    these are newbie errors.

    Procedures:
    --------------------------
    int DBopen(void)
    {
    int res=0;
    RETCODE retcode;

    printf("DBopen Start\n");

    /*allocate the environment handle*/
    if(SQLAllocEnv( &henv)==SQL_SUC CESS)
    {
    /*allocate the connection handle*/
    if(SQLAllocConn ect(henv, &hdbc)==SQL_SUC CESS)
    {
    /* Set login timeout to 5 seconds. */
    //SQLSetConnectOp tion(hdbc, SQL_LOGIN_TIMEO UT, 5);
    //SQLSetConnectOp tion(hdbc, SQL_CURSOR_TYPE ,
    SQL_CURSOR_STAT IC);
    /* Connect to data source */
    retcode = SQLConnect(hdbc , "iSeries", SQL_NTS, "USER",
    SQL_NTS, "PWD", SQL_NTS);

    if (retcode == SQL_SUCCESS || retcode ==
    SQL_SUCCESS_WIT H_INFO)
    {
    res=1;
    }
    }
    else
    {
    SQLFreeConnect( hdbc);
    }
    }
    else
    {
    SQLFreeEnv(henv );

    }
    dbopen=res;
    return res;
    }

    void DBclose(void)
    {
    if(dbopen)
    {
    SQLDisconnect(h dbc);
    SQLFreeConnect( hdbc);
    SQLFreeEnv(henv );
    }
    dbopen=0;
    }
    int DBexecute(char *sql,HSTMT *hstmt)
    {
    int res=0;
    RETCODE retcode;

    if(SQLAllocStmt (hdbc, hstmt)== SQL_SUCCESS)
    {
    retcode=SQLPrep are(*hstmt,sql, strlen(sql));
    if(retcode==SQL _SUCCESS)
    {
    retcode=SQLExec ute(*hstmt);
    if(retcode==SQL _SUCCESS)
    {
    res=1;
    }
    else
    {
    printf("Error on SQLExecute!!\n" );
    }
    }
    else
    {
    printf(sql);
    printf("Error on SQLPrepare!!\n" );
    }
    }
    else
    {
    printf("Error on SQLAllocStmt!!\ n");
    }
    return res;
    }

    void DBcloseCursor(H STMT hstmt)
    {
    SQLFreeStmt(hst mt, SQL_DROP);
    }

    void TestAS400()
    {
    char sql[160];
    char *sql2;
    HSTMT fstmt;
    long lens;
    RETCODE retcode;
    char name[2 + 1];
    char szBarcode[13 + 1];

    scanf("%s", szBarcode );

    sql2 = strcat("SELECT field1,field2 FROM library.file where field3 =
    (select field4 from library.file where field5 ='",szBarcode );
    sql2 = strcat(sql2,"') \n");

    if(DBexecute(sq l2,&fstmt))
    {
    SQLBindCol(fstm t,1,SQL_C_CHAR, name,sizeof(nam e),&lens);

    retcode = SQLFetch(fstmt) ;
    while(retcode == SQL_SUCCESS || retcode ==
    SQL_SUCCESS_WIT H_INFO)
    {
    printf("%s\n",n ame);
    retcode = SQLFetch(fstmt) ;
    }
    DBcloseCursor(f stmt);
    }
    else
    {
    printf("error!\ n");
    }
    printf("DONE,BY E\n");
    //DBclose();

    }
  • Antoninus Twink

    #2
    Re: Need beginner help with C (LabWindows/CVI)!

    On 10 Oct 2008 at 20:08, lgerhardx@hotma il.com wrote:
    void TestAS400()
    {
    char sql[160];
    char *sql2;
    HSTMT fstmt;
    long lens;
    RETCODE retcode;
    char name[2 + 1];
    char szBarcode[13 + 1];
    >
    scanf("%s", szBarcode );
    >
    sql2 = strcat("SELECT field1,field2 FROM library.file where field3 =
    (select field4 from library.file where field5 ='",szBarcode );
    sql2 = strcat(sql2,"') \n");
    This is very bad news. Firstly, sql2 could be pointing anywhere - you
    need to allocate memory before you can write to it. Secondly, strcat()
    doesn't behave the way you think it does.

    Try:

    sql2 = malloc(snprintf (NULL, 0,
    "SELECT field1,field2 FROM library.file where field3 = "
    "(select field4 from library.file where field5 ='%s')\n", szBarcode)+1);
    if(sql2)
    sprintf(sql2,
    "SELECT field1,field2 FROM library.file where field3 = "
    "(select field4 from library.file where field5 ='%s')\n", szBarcode);
    else
    /* handle error */



    Then remember to free(sql2); when you're done with it.

    Comment

    • Keith Thompson

      #3
      Re: Need beginner help with C (LabWindows/CVI)!

      lgerhardx@hotma il.com writes:
      [...]
      void TestAS400()
      {
      char sql[160];
      char *sql2;
      HSTMT fstmt;
      long lens;
      RETCODE retcode;
      char name[2 + 1];
      char szBarcode[13 + 1];
      >
      scanf("%s", szBarcode );
      This reads one whitespace-delimited "word" from stdin and stores it in
      szBarcode. You normally have no control over what appears on stdin.
      What if the word you read is bigger than what szBarcode can hold? Use
      a length specifier rather than a bare "%s" format to avoid this.
      Better, read input a line at a time and then process it.
      sql2 = strcat("SELECT field1,field2 FROM library.file where field3 =
      (select field4 from library.file where field5 ='",szBarcode );
      sql2 = strcat(sql2,"') \n");
      [...]

      Your strcat() calls are certainly a problem. Whether they explain the
      symptoms you're seeing is another matter.

      strcat() takes two char* arguments, both of which must point to
      strings. A copy of the contents of the string pointed to by the
      second argument is appended to the end of the string pointed to by the
      first argument.

      This means that (a) the first string needs to be writable, and (b)
      there must be enough room to store the result.

      A string literal may or may not be writable, depending on your
      implementation, but in any case attempting to write to it invokes
      undefined behavior. (Note that this *might* mean that it behaves as
      you expect it to.) Either way, a string literal does not allocate any
      additional space beyond what's needed for the string itself (including
      the terminating '\0'), so you're also attempting to write over memory
      that you haven't allocated.

      Here's how I might do it:

      char *sql2;
      const char command[] = "SELECT field1,...";
      ...
      sql2 = malloc(sizeof command + strlen(szBarcod e) + 1);
      /* Check whether sql2==NULL */
      strcpy(sql2, command);
      strcat(sql2, szBarcode);

      You'll need to check whether malloc succeeded before attempting to use
      the result, which means you'll need to decide what to do if it fails;
      aborting the program with an error message is probably better than
      ignoring the error.

      I haven't gone over your code thoroughly, so there may be other
      errors; this one just jumped out at me.

      --
      Keith Thompson (The_Other_Keit h) kst-u@mib.org <http://www.ghoti.net/~kst>
      Nokia
      "We must do something. This is something. Therefore, we must do this."
      -- Antony Jay and Jonathan Lynn, "Yes Minister"

      Comment

      • David Given

        #4
        Re: Need beginner help with C (LabWindows/CVI)!

        Antoninus Twink wrote:
        [...]
        sql2 = malloc(snprintf (NULL, 0,
        "SELECT field1,field2 FROM library.file where field3 = "
        "(select field4 from library.file where field5 ='%s')\n", szBarcode)+1);
        if(sql2)
        sprintf(sql2,
        "SELECT field1,field2 FROM library.file where field3 = "
        "(select field4 from library.file where field5 ='%s')\n", szBarcode);
        else
        /* handle error */
        Just as an addendum to what Antoninus posted, if you don't care about
        portability (and it looks like you're a Windows programmer), look to see
        if your platform has an aprintf() function (sometimes called
        asprintf()). Most libcs have an extension that does this. What it is is
        an sprintf() that will return you a newly allocated block of the right
        size, which means you avoid having to allocate it yourself (and
        therefore avoid getting it wrong). While it's not terribly efficient, it
        can make string handling code much, much easier to get right.

        If you *don't* have one, or you do care about portability, you may want
        to consider writing your own.
        Then remember to free(sql2); when you're done with it.
        You still need to do this with aprintf(), though.

        --
        ┌─── dg@cowla rk.co m ───── http://www.cowlark.com ─────
        │ "...it's not that well-designed GUI's are rare, it's just that the
        │ three-armed users GUI's are designed for are rare." --- Mike Uhl on
        │ a.f.c

        Comment

        • lgerhardx@hotmail.com

          #5
          Re: Need beginner help with C (LabWindows/CVI)!

          Great! Thanks everyone for the awesome help! I'll put these newly-
          learned points to use today.

          I do have one more quick dummy question though about what I've seen
          here. Sometimes I notice ints and chars defined with an asterisk. I
          have not had much success searching online for information on what
          that means exactly. Is there either 1) any quick and dirty reference
          that you could point me to that would explain such simple things to
          me, or 2) just explain in 7,204^2 words or less what exactly the
          significance of the * is? <G>

          Thanks! I really appreciate your kind assistance!!

          Comment

          • Richard Heathfield

            #6
            Re: Need beginner help with C (LabWindows/CVI)!

            lgerhardx@hotma il.com said:
            Great! Thanks everyone for the awesome help! I'll put these newly-
            learned points to use today.
            >
            I do have one more quick dummy question though about what I've seen
            here. Sometimes I notice ints and chars defined with an asterisk. I
            have not had much success searching online for information on what
            that means exactly. Is there either 1) any quick and dirty reference
            that you could point me to that would explain such simple things to
            me, or 2) just explain in 7,204^2 words or less what exactly the
            significance of the * is? <G>
            In a definition (or declaration), * means "pointer to". Thus:

            int i = 42; /* i is an int */
            int j = 0;
            int *p; /* p is a pointer to int; *p is an int */

            p = &i; /* p now points to i */
            j = *p; /* j now has the value 42, i.e. the value of the thing
            to which p points */
            *p = 6; /* i's value has now been changed to 6 */

            For further information on pointers, consult your C reference.

            --
            Richard Heathfield <http://www.cpax.org.uk >
            Email: -http://www. +rjh@
            Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
            "Usenet is a strange place" - dmr 29 July 1999

            Comment

            • lgerhardx@hotmail.com

              #7
              Re: Need beginner help with C (LabWindows/CVI)!

              Thanks for the quick notes, and thanks everyone for your comments and
              help! I know a lot more now because of such assistance, and now I
              think I can hit the ground running!

              I made the some of the changes that were offered and have been having
              perfect success retrieving the data I wanted! THANK YOU!

              Comment

              Working...