4

Doing my best to be brief; I am trying to program an LCD to print out an integer variable (of more than 1 digit). I'm trying to do this using the itoa function as the LCD takes ASCII characters. The below code compiles and prints "Set Temp: " when I want it to, the problem is that it doesn't print out the chars (digits) stored in the numberString array like I want it to. The writeString function is working fine but I cant figure out why it's just not printing the value of int setTemp after "Set Temp: ". All that's outputted is: "Set Temp: " with the cursor just hanging.

Probably worth mentioning that the cursor is hanging ON the position where the value should be printed on the LCD, indicating that it isn't just printing an empty value, it just isn't printing anything at all or waiting for something.

Apologies for any incorrect formatting of question, I'm new.

void writeChar(unsigned char ch)
{
  lcd = ch;
  RS = 1;
  RW =0;
  E = 1;
  lcdDelay();
  E=0;
}

void writeString(char *stringToLcd)
{
  while(*stringToLcd > 0)
  {
    writeChar(*stringToLcd++);
  }
}



int changeTriggTemp(void)
{
  char numberString[4]; //buffer, -99 -> 99
  int setTemp = 50;

  clearDisplay();
  writeString("Set Temp: ");

  itoa(setTemp,numberString,10);
  lcdDelay();

  writeString(numberString);

  while(1); //placeholder before I return the int I want

}
Eric
  • 1,689
  • 15
  • 12
James
  • 356
  • 2
  • 13
  • pleas reduce this to a (much) smaller example. If your problem is with `itoa` write a small function that demonstrates the problem you are having with `itoa`. Don't paste an entire program. – Ryan Haining Dec 08 '15 at 18:23
  • "it doesn't print out the chars (digits) stored in the numberString array like I want it to." What _does_ it print (if anything)? – chux - Reinstate Monica Dec 08 '15 at 18:23
  • 1
    Why not "sprintf( str, "Set Temp: %d", setTemp)"; – Clarus Dec 08 '15 at 18:29
  • Reduced the code size (thanks Ryan), and added further clarification to what the output is currently. I'm not convinced I can use sprintf in this case due to the fact that I need to use the writeChar and writeString functions to interface with the LCD. I'm not sure what using sprintf would achieve. – James Dec 08 '15 at 18:51
  • what happens if you skip `writeString("Set Temp: ");` all together ? – Eric Dec 08 '15 at 18:54
  • Presents an empty display with the cursor on position 1 – James Dec 08 '15 at 18:58
  • 1
    and what if you write the number, and then write the `writeString("Set Temp: ");` ? – Eric Dec 08 '15 at 19:05
  • Just writes "Set Temp: " as per usual, from position 1. – James Dec 08 '15 at 19:07
  • 1
    `itoa` is actually not standard, can you try with this implementation instead ? (nb: you'll need to modify it for negative numbers/non decimal output/writing '0' correctly) ` void alt_itoa(int number, char *dest) { int cursor = 0; while (number > 0) { dest[cursor++] = '0' + (number % 10); number /= 10; } dest[cursor] = '\0'; } ` – Eric Dec 08 '15 at 19:08
  • Who implemented `itoa`? – Weather Vane Dec 08 '15 at 19:09
  • What happens if you try to pass non-terminated string to `writeString()`? Does it print garbage or does it hang? Can you test it by putting 4 digits in `numberString` so it will not be null terminated? – alvits Dec 08 '15 at 19:15
  • @alvits it doesn't hang because reversing the print sequence worked, but still no number. – Weather Vane Dec 08 '15 at 19:16
  • @Eric , you seem to be on to something there. Using that implementation it prints out the integers (or chars, I should say), however they are in reverse. I.e. if setTemp = 123, the output I get is "321". I did originally add include in order to be able to use itoa, but I'm curious as to how your function differs. – James Dec 08 '15 at 19:20
  • I really don't know about your environment so its impossible to say, but `itoa` is a fun and easy challenge to get right. Best of luck =) – Eric Dec 08 '15 at 19:22
  • @Nick are you saying you no longer `#include `? You must. – Weather Vane Dec 08 '15 at 19:24
  • (though i suspect your buffer is simply too small) – Eric Dec 08 '15 at 19:25
  • @Eric I was going to say that but noticed `int setTemp = 50;` – Weather Vane Dec 08 '15 at 19:25
  • @WeatherVane True - but who know what itoa expects in that impl. Any overflow would have unpredictable consequences (besides allocating enough for -max_int is trivial) – Eric Dec 08 '15 at 19:27
  • 1
    @Nick what is the function prototype for `itoa` in your compiler's `stdlib.h`? – Weather Vane Dec 08 '15 at 19:28
  • @WeatherVane sorry for the confusion! yes I am continuing to include it. I'm not sure where to find the functions implemented in the header files in the MPLAB IDE I'm using. I'm looking now. – James Dec 08 '15 at 19:36
  • @Nick look in the header file, that's where the function prototype is. – Weather Vane Dec 08 '15 at 19:36
  • @WeatherVane Beginning to feel like a real beginner here, because it seems that my header file is empty, whereas you're hinting heavily that it shouldn't be. I was under the impression that by including it removed the necessity for the programmer (i.e. me) to add the header files himself and they would work by default. – James Dec 08 '15 at 19:43
  • I am sure you have `#include ` at the top of your .c file. Is it time to prepare a [Minimal, Complete, and Verifiable example](http://stackoverflow.com/help/mcve) that tests your LCD writing? I am equally sure that `stdlib.h` cannot be an empty file in your embedded compiler toolchain. – Weather Vane Dec 08 '15 at 19:53
  • @WeatherVane I believe I've found what I'm looking for: char * itoa (int val, char *s, int radix) – James Dec 08 '15 at 20:03
  • `#include "something"` just means "Remove this line (#inclu...) and replace it with the contents of that file (and so on if that file also has includes). Feeling like a beginner is very healthy for programming, as you've just seen, most comes from questioning everything. – Eric Dec 08 '15 at 20:05
  • @Nick the standard implementation is `char *itoa(int value, char *str, int radix);` I wonder what your embedded compiler does passing `int` to `long`. What happens with `long setTemp = 50;` and is `long` the same size as `int` anyway? EDIT you changed your comment from `long val` to `int val`. – Weather Vane Dec 08 '15 at 20:09
  • @WeatherVane I hoped I had edited it before you saw it, but yes it is supposed to be int. For what its worth it seems that it allows me to pass a variable of type long into Erics alternative itoa, despite the argument being of type int. Though I would assume that is just a feature in C when passing variables of similar types. – James Dec 08 '15 at 20:17
  • @Nick if `sprintf()` is available, as suggested earlier, can you use that? It's not the quickest way of converting `int` to `char[]` but it would prove the point that `itoa` might be faulty. `sprintf(numberString, "%d", setTemp );` – Weather Vane Dec 08 '15 at 20:21
  • Argh! I'm so stupid!!! I've had a little feeling that I've been looking in the wrong place for the header files. Just chased it up and discovered that indeed, the prototype for itoa is: itoa(char * buf, int val, int base); and that I was looking in the wrong place! The function now works correctly and program as a whole is running fine. Many many thanks for setting me on the right path to both WeatherVane and Eric. And sorry for the wasted time! – James Dec 08 '15 at 20:25
  • the function `atoi()` returns an integer (on a 32 bit system, a 4 bytes integer) not a ascii string. The parameter to `atoi()` was the ascii string, and that is what should be being printed on the LCD. – user3629249 Dec 09 '15 at 05:27
  • I do not know where you got that syntax for the `atoi()` function, when looking at the man page the syntax is: `int atoi(const char *nptr);` As I already stated, the original ascii string is what needs to be passed to the LCD, not some integer – user3629249 Dec 09 '15 at 05:31
  • @WeatherVane You should post the header fix as an answer, you deserve credit. – Eric Dec 09 '15 at 15:40
  • 1
    @Eric thanks for the praise, your comments paved the way. – Weather Vane Dec 09 '15 at 16:02

1 Answers1

1

If you don't define a function prototype, the compiler can make incorrect assumptions about it, and code its use wrongly. Having drawn your attention to that I asked what the definition is, because the usual definition (at least in MSVC) is

char *itoa(int value, char *str, int radix);

This agreed with your own usage of the function,

itoa(setTemp, numberString, 10);

however on closer inspection of your library header file, you stated that it defines

itoa(char * buf, int val, int base);

In other words, the first two arguments are switched. Since itoa() is not a standard function, this is allowed, but you have to call it accordingly:

itoa(numberString, setTemp, 10);

(Thanks to @Eric whose suggestions revealed that it could well be itoa at fault).

Weather Vane
  • 33,872
  • 7
  • 36
  • 56