locked
FLTK GUI Question: How to load array data from and to an Fl_Input widget? RRS feed

  • Question

  • How can array data be loaded from and to an Fl_Input widget?

    I have tried the code bellow, but in the last line a compiler error is created due data type incompatibility. So, either I need to be able to change the int data type of the array into the const char data type of the Fl_Input when loading to the Fl_Input widget OR I need to change the data type of the Fl_Input widget to use int in the first place. But I do not know how to do either. I am using VC10 and FLTK 1.3.

    int array[10]; Fl_Input *input = new Fl_Input(100,100,20); array[0] = ((int)input->value()) - See more at: http://www.gidforums.com/t-29117.html#sthash.uYYgAoLp.dpuf
    int array[10]; Fl_Input *input = new Fl_Input(100,100,20); array[0] = ((int)input->value()) - See more at: http://www.gidforums.com/t-29117.html#sthash.uYYgAoLp.dpuf
    int arrayNum[10] = {{0},{0},{0},{0},{0},{0},{0},{0},{0},{0}} //Create integer array
    Fl_Input *input = new Fl_Input(100,100,50,20);               //Create Fl_Input widget
    arrayNum[0] = input->((int)value());                         //Load Fl_Input value to array as integer
    input->value((char)arrayNum[0]);                             //Load data back, but "char to const char" error

    Is there a way to cast the array data type back into a format that is acceptable to the Fl_Input widget OR could the following be used to change the Fl_Input data type from const char to int in the first place? If so, how? The FLTK documentation is written in a style that is too obscure for me as a person who is relatively new to programming.

    input->input_type();
    Monday, July 21, 2014 7:47 AM

Answers

  • Explanation aside, here is the working code:

    void cb_save(Fl_Widget*o, void*)
    {
    Fl_Int_Input *g1 = (Fl_Int_Input*)o->parent()->child(20);
    Fl_Int_Input *g2 = (Fl_Int_Input*)o->parent()->child(21);
    const char *ptr1 = g1->value();
    char gR[3] = {{'a'},{'b'},{'c'}};
    for(size_t i=0; i<strlen(ptr1); i++)
    { gR[i] = ptr1[i]; }
    ptr1 = &gR[0];
    int gval = atoi(ptr1);
    gval *= 2;
    char gS[3] = {{'a'},{'b'},{'c'}};
    itoa(gval, gS, 10);
    ptr1 = &gS[0];
    g2->value((LPCSTR)ptr1);
    }





    • Marked as answer by MHostetter Wednesday, July 23, 2014 12:55 PM
    • Edited by MHostetter Wednesday, July 23, 2014 1:42 PM
    • Unmarked as answer by MHostetter Wednesday, July 23, 2014 1:43 PM
    • Marked as answer by MHostetter Wednesday, July 23, 2014 1:43 PM
    Wednesday, July 23, 2014 12:32 PM
  • Above explanation aside, here is the actual code:

    void cb_save(Fl_Widget*o, void*)
    {
    Fl_Int_Input *g1 = (Fl_Int_Input*)o->parent()->child(20);
    Fl_Int_Input *g2 = (Fl_Int_Input*)o->parent()->child(21);
    const char *ptr1 = g1->value();
    char gR[3] = {{'a'},{'b'},{'c'}};
    for(size_t i=0; i<strlen(ptr1); i++)
    { gR[i] = ptr1[i]; }
    ptr1 = &gR[0];
    int gval = atoi(ptr1);
    gval *= 2;
    char gS[3] = {{'a'},{'b'},{'c'}};
    Itoa(gval, gS, 10);
    ptr1 = &gS[0];
    g2->value((LPCSTR)ptr1);
    }

    There is no int array in this code. Rather the code assumes that the widget data is a string representation of an integer (which it may be). It then attempts to convert this value to an integer, double it, convert it back to a string, and insert it in a different widget.

    There are several things seriously wrong with your code

    1. The array gR may not be big enough, and is not nul-terminated.

    2. It's itoa, not Itoa.

    3. The array gS may not be long enough for the conversion.

    In addition

    1. There is no need to copy the value obtained from widget g1.

    2. itoa() is not a good way to convert an integer to a string. Not thread-safe, and serious potential for buffer overrun. It is not even a standard C or C++ function.

    3. The LPCSTR cast is unnecessary because LPCSTR is the same as const char*.

    4. What is the purpose of the initialization of gR and gS? These values are immediately over-written.

    Here is an improved version of your code:

    void cb_save(Fl_Widget*o, void*)
    {
      Fl_Int_Input *g1 = (Fl_Int_Input*)o->parent()->child(20);
      Fl_Int_Input *g2 = (Fl_Int_Input*)o->parent()->child(21);
      const char *ptr1 = g1->value();
      int gval = atoi(ptr1);
      gval *= 2;
      std::ostringstream os;
      os << gval;
      g2->value(os.str().c_str());
    }

    Much shorter, and no possibility of buffer overrun.

    Please do not keep marking your own post as answer.


    David Wilkinson | Visual C++ MVP

    • Marked as answer by MHostetter Wednesday, July 23, 2014 2:11 PM
    Wednesday, July 23, 2014 1:43 PM
  • Thanks for the header. Bellow is a simple example of the widget i/o for processing.
    ...
    Copy this code to a VC10 IDE and it should compile into a working program.
    This marks the first full program written from my cellphone.

    This code will certainly not compile as written, for at least two reasons. Typing code directly on the forum is never a good idea. Always copy and paste your actual code.

    You do not appear to have taken note of any of the suggestions in my previous post. In particular the lines like

    char vR[4]={{'a'}{'b'}{'c'}{'d'}};

    This line does not compile for me. Perhaps you mean

    char vR[4]={'a', 'b', 'c', 'd'};

    Even so, I do not see the purpose of this line. Note also that the array is not nul-terminated. Then when you do

    for (size_t i = 0; i < strlen(ptr1); i++)
    {
       vR[i] = ptr1[i];
    }

    vR is still not nul-terminated, so I do not see how the subsequent call to atoi() can work. Also, what do you think happens if strlen(ptr1) is greater than 4? Perhaps you are sure this will not be the case, but this is very dangerous code. In any case, as I told you before, it is not necessary to copy the contents of ptr1 before calling atoi().

    Here is a simplified version of your code (untested):

    #include <string.h>
    #include <sstream>
    
    int vHo[2] = {0, 0}; 
    
    void cb_calculate(Fl_Widget *o, void*)
    {
    	Fl_Int_Input *v1 = (Fl_Int_Input*)o->parent()->child(0);
    	Fl_Int_Input *v2 = (Fl_Int_Input*)o->parent()->child(1);
    	Fl_Output *v3 = (Fl_Output*)o->parent()->child(2);
    
    	const char *ptr1;
    
    	ptr1 = v1->value();
    	vHo[0] = atoi(ptr1);
    
    	ptr1 = v2->value();
    	vHo[1] = atoi(ptr1);
    
    	int avgval = (vHo[0] + vHo[1])/2;
    
    	//LOAD to Fl_Output
    	std::ostringstream os;
    	os << avgval;
    	v3->value(os.str().c_str());
    }



    David Wilkinson | Visual C++ MVP


    • Edited by davewilk Thursday, July 24, 2014 12:25 PM typo
    • Marked as answer by MHostetter Thursday, July 24, 2014 2:30 PM
    Thursday, July 24, 2014 12:22 PM

All replies

  • I would advise you to learn C++ before trying to use it with some third party GUI API.

    Also, when you get compiler errors, you should post the exact error (including error number), not some paraphrase of it.

    For someone who does not know anything about FLTK, the missing piece of information is the documentation for Fl_Input. This may be found at

    http://www.fltk.org/documentation.php/doc-1.1/Fl_Input.html

    It seems that Fl_Input can hold a position (four integers) and a label (const char*). The documentation gives the members

    const char *Fl_Input::value() const
    int Fl_Input::value(const char*)

    which are used to get or set the label text.

    In this context what are you trying to do exactly?


    David Wilkinson | Visual C++ MVP

    Monday, July 21, 2014 11:13 AM
  • Thank you for the response and pointers on learning process and accurately posting errors. It is true that I am jumping in the middle a bit here by picking up FLTK so soon and trying to bridge only the necessary connections between it and what I have learned of C++ so far. The GUI of the program that I am building seems so simple. Transferring data from an input box to an array and then back seemed like the last thing that would give the project a hang up. But there it was. In relation to the point of difficulty with the code in this case, the good news is that a solution came to my attention while continuing to surf the net. And the solution is to cast the int data type to a const char by using (LPCSTR) from #include <cstring>. The relevant and essential lines of code are shown bellow:

    #include <cstring>
    arrayNum[0] = ((int)input->value());
    input->value((LPCSTR)arrayNum[0]);



    • Marked as answer by MHostetter Monday, July 21, 2014 3:22 PM
    • Edited by MHostetter Monday, July 21, 2014 3:35 PM
    • Unmarked as answer by MHostetter Wednesday, July 23, 2014 12:03 PM
    Monday, July 21, 2014 3:21 PM
  • That looks awful because I posted from my phone which shows no code box option.
    Monday, July 21, 2014 3:24 PM
  • Thank you for the response and pointers on learning process and accurately posting errors. It is true that I am jumping in the middle a bit here by picking up FLTK so soon and trying to bridge only the necessary connections between it and what I have learned of C++ so far. The GUI of the program that I am building seems so simple. Transferring data from an input box to an array and then back seemed like the last thing that would give the project a hang up. But there it was. In relation to the point of difficulty with the code in this case, the good news is that a solution came to my attention while continuing to surf the net. And the solution is to cast the int data type to a const char by using (LPCSTR) from #include <cstring>. The working piece of code is shown bellow: [code] #include <cstring> //... grades[0] = ((int)g1->value()); g2->value((LPCSTR)grades[0]); //... [/code]

    This code is not formatted in a readable way, but I think you mean

    #include <cstring>
    //...
    grades[0] = (int)g1->value();
    g2->value((LPCSTR)grades[0]);

    I'm really not sure what you think this does. What do you mean by 'working'? I have to say that your approach to C++ seems to be to keep typing till the code compiles, without any real understanding.

    LPCSTR is equivalent to const char* (not to const char). What is the purpose of casting to an int and back again? If this is all you are doing with grades[0] then the code may work, but why not just do

    g2->value(g1->value());

    Any code that has a cast in it is generally suspect.

    Also, <cstring> is not really the header for the LPCSTR typedef (though maybe it will work). The Microsoft documentation says to use <WinNT.h>. Note that <cstring> is a standard C++ header, while LPCSTR and WinNT.h are Microsoft-specific.


    David Wilkinson | Visual C++ MVP

    Monday, July 21, 2014 4:31 PM
  • Yes, it seems that FLTK Fl_Input widgets store all their data as const char, but, since I need to send their data to an array as int for processing, there is the necessity for the casts. But the lines of code that I wrote are not trying to send one widget's data to another so much as confirm the ability to send data to an int array and to confirm the ability to send the data back to an Fl_Input widget. If the purpose were to only send data from one widget directly to another, then the line of code that you wrote would work much better. I will actually use lines like that to replicate redundant pieces of information across the GUI so that the user must only type it in once. On the other hand, the lines of code that I have got functioning correctly now will be used separately in various parts of the program to do things like send data to an array for mathematical processing, returning the results to a text widget, saving data to a file and loading the data back from the saved file to widgets. So then I am still not sure why (LPCSTR) achieves the data cast that I intended even though you explained it a bit, but I will probably learn and come to appreciate the hidden details of that as I continue to learn more about the C++ language. For now, pressing the relatively abstract code pedals gets me from point A to point B without knowing exactly what is going on in the engine. Thanks again for getting me thinking more about these things.
    Tuesday, July 22, 2014 3:17 AM
  • Yes, it seems that FLTK Fl_Input widgets store all their data as const char, but, since I need to send their data to an array as int for processing, there is the necessity for the casts. But the lines of code that I wrote are not trying to send one widget's data to another so much as confirm the ability to send data to an int array and to confirm the ability to send the data back to an Fl_Input widget. If the purpose were to only send data from one widget directly to another, then the line of code that you wrote would work much better. I will actually use lines like that to replicate redundant pieces of information across the GUI so that the user must only type it in once. On the other hand, the lines of code that I have got functioning correctly now will be used separately in various parts of the program to do things like send data to an array for mathematical processing, returning the results to a text widget, saving data to a file and loading the data back from the saved file to widgets. So then I am still not sure why (LPCSTR) achieves the data cast that I intended even though you explained it a bit, but I will probably learn and come to appreciate the hidden details of that as I continue to learn more about the C++ language. For now, pressing the relatively abstract code pedals gets me from point A to point B without knowing exactly what is going on in the engine. Thanks again for getting me thinking more about these things.

    But you are not sending that data to an array of int - you are converting the const char* pointer to a single int, and storing it in grades[0]. You cannot use this value for anything other than casting it back to const char*.

    Why do you want to convert the data to an array of int? Why not use it as an array of char (which is what it is)?

    This code may be more what you really want:

    const char* str = g1->value();
    for (size_t i = 0; i < strlen(str); i++)
    {
      int val = str[i]; // now you have an integer
      // ...
    }


    David Wilkinson | Visual C++ MVP

    Tuesday, July 22, 2014 12:11 PM
  • Thank you for the loop code. The size_t and strlen() usage were very interesting and useful. So much of the complication in coding seems to be related to data types and their differing byte size. The code that I wrote was compiling, but not giving me the expected output in the program. It seemed that only the first char value from the Fl_Input widget's value was being loaded to the char array. So I used the loop that you provided, but with a char array instead of the int val, and it worked. After getting the char values from the widget into a char array, I tried using atoi() to feed the char array values to an int variable which also worked. All that gave me the Fl_Input widget's char values in an int variable for storing to an int array and then processing. But I would still need to be able to load the int value back to the Fl_Input widget as a char value. That proved to be its own adventure of searching and testing. As it turns out, I surfed the net and found itoa() which is in the <cstdlib> and used it to convert and assign the integer value back into a character array. Then a char pointer was set to the char array, and that pointer was then sent to the Fl_Input widget's value, though the char pointer also had to be cast into a const char pointer at the time with (LPCSTR) which is found in <cstring>. I will try to post the code bellow in this post or more probably the next post since I am typing from my cellphone again and will probably take a break from the hunt-and-peck of typing this post.
    • Marked as answer by MHostetter Wednesday, July 23, 2014 12:02 PM
    • Unmarked as answer by MHostetter Wednesday, July 23, 2014 12:03 PM
    • Edited by MHostetter Wednesday, July 23, 2014 12:59 PM
    Wednesday, July 23, 2014 11:56 AM
  • Thank you for the loop code. The size_t and strlen() usage were very interesting and useful. So much of the complication in coding seems to be related to data types and their differing byte size. The code that I wrote was compiling, but not giving me the expected output in the program. It seemed that only the first char value from the Fl_Input widget's value was being loaded to the char array. So I used the loop that you provided, but with a char array instead of the int val, and it worked. After getting the char values from the widget into a char array, I tried using atoi() to feed the char array values to an int variable which also worked. All that gave me the Fl_Input widget's char values in an int variable for storing to an int array and then processing. But I would still need to be able to load the int value back to the Fl_Input widget as a char value. That proved to be its own adventure of searching and testing. As it turns out, I surfed the net and found itoa() which is in the <cstdlib> and used it to convert and assign the integer value back into a character array. Then a char pointer was set to the char array, and that pointer was then sent to the Fl_Input widget's value, though the char pointer also had to be cast into a const char pointer at the time with (LPCSTR) which is found in <cstring>. I will try to post the code bellow in this post or more probably the next post since I am typing from my cellphone again.

    Forgive me, but your post does not really make any sense. You are trying to program in C++ without taking the time to learn the language. In particular, you do not seem to understand the relationship (or difference) between variables, pointers and arrays. Using casts can obscure these distinctions, but can lead to incorrect code unless you really know what you are doing. I would seriously advise you to avoid all casts in your code.

    You still have not explained why you want to convert the widget data to an int array. I suspect that really you do not. What processing do you really want to perform on the widget data?


    David Wilkinson | Visual C++ MVP

    Wednesday, July 23, 2014 12:19 PM
  • Explanation aside, here is the working code:

    void cb_save(Fl_Widget*o, void*)
    {
    Fl_Int_Input *g1 = (Fl_Int_Input*)o->parent()->child(20);
    Fl_Int_Input *g2 = (Fl_Int_Input*)o->parent()->child(21);
    const char *ptr1 = g1->value();
    char gR[3] = {{'a'},{'b'},{'c'}};
    for(size_t i=0; i<strlen(ptr1); i++)
    { gR[i] = ptr1[i]; }
    ptr1 = &gR[0];
    int gval = atoi(ptr1);
    gval *= 2;
    char gS[3] = {{'a'},{'b'},{'c'}};
    itoa(gval, gS, 10);
    ptr1 = &gS[0];
    g2->value((LPCSTR)ptr1);
    }





    • Marked as answer by MHostetter Wednesday, July 23, 2014 12:55 PM
    • Edited by MHostetter Wednesday, July 23, 2014 1:42 PM
    • Unmarked as answer by MHostetter Wednesday, July 23, 2014 1:43 PM
    • Marked as answer by MHostetter Wednesday, July 23, 2014 1:43 PM
    Wednesday, July 23, 2014 12:32 PM
  • Well, now that values can be saved from and loaded to the various input widgets, one can apply all sorts of processing too. You seem to point out that I do not know what I am doing, which is true to an extent, and that I do not really want to process the values, which is not true, all in order to get me to reveal more in an explanation or demonstration especially in regard to the processing that is intended. Your approach to eliciting information in a conversation reminds me of fairly well-known individual who wrote an insightful book wherein he noted using the same approach to getting information that was otherwise not being said. It is a respectably insightful and amusingly clever approach, but since I know better of it and since the subject of processing is outside the intended scope of this post, I will kindly decline at this time. Besides, the processing is nothing too special or sophisticated. More importantly, anyone who reads this post can more easily get values in and out if the FLTK library and process their values in anyway that benefits their own project. Thanks for your help. I am sure many others will be thankful too since I might post the answer to the other forums where I asked for the same help, and might send Erco the code so that he can use it to publish a tutorial on the subject.
    Wednesday, July 23, 2014 1:40 PM
  • Above explanation aside, here is the actual code:

    void cb_save(Fl_Widget*o, void*)
    {
    Fl_Int_Input *g1 = (Fl_Int_Input*)o->parent()->child(20);
    Fl_Int_Input *g2 = (Fl_Int_Input*)o->parent()->child(21);
    const char *ptr1 = g1->value();
    char gR[3] = {{'a'},{'b'},{'c'}};
    for(size_t i=0; i<strlen(ptr1); i++)
    { gR[i] = ptr1[i]; }
    ptr1 = &gR[0];
    int gval = atoi(ptr1);
    gval *= 2;
    char gS[3] = {{'a'},{'b'},{'c'}};
    Itoa(gval, gS, 10);
    ptr1 = &gS[0];
    g2->value((LPCSTR)ptr1);
    }

    There is no int array in this code. Rather the code assumes that the widget data is a string representation of an integer (which it may be). It then attempts to convert this value to an integer, double it, convert it back to a string, and insert it in a different widget.

    There are several things seriously wrong with your code

    1. The array gR may not be big enough, and is not nul-terminated.

    2. It's itoa, not Itoa.

    3. The array gS may not be long enough for the conversion.

    In addition

    1. There is no need to copy the value obtained from widget g1.

    2. itoa() is not a good way to convert an integer to a string. Not thread-safe, and serious potential for buffer overrun. It is not even a standard C or C++ function.

    3. The LPCSTR cast is unnecessary because LPCSTR is the same as const char*.

    4. What is the purpose of the initialization of gR and gS? These values are immediately over-written.

    Here is an improved version of your code:

    void cb_save(Fl_Widget*o, void*)
    {
      Fl_Int_Input *g1 = (Fl_Int_Input*)o->parent()->child(20);
      Fl_Int_Input *g2 = (Fl_Int_Input*)o->parent()->child(21);
      const char *ptr1 = g1->value();
      int gval = atoi(ptr1);
      gval *= 2;
      std::ostringstream os;
      os << gval;
      g2->value(os.str().c_str());
    }

    Much shorter, and no possibility of buffer overrun.

    Please do not keep marking your own post as answer.


    David Wilkinson | Visual C++ MVP

    • Marked as answer by MHostetter Wednesday, July 23, 2014 2:11 PM
    Wednesday, July 23, 2014 1:43 PM
  • Well, now that values can be saved from and loaded to the various input widgets, one can apply all sorts of processing too. You seem to point out that I do not know what I am doing, which is true to an extent, and that I do not really want to process the values, which is not true, all in order to get me to reveal more in an explanation or demonstration especially in regard to the processing that is intended. Your approach to eliciting information in a conversation reminds me of fairly well-known individual who wrote an insightful book wherein he noted using the same approach to getting information that was otherwise not being said. It is a respectably insightful and amusingly clever approach, but since I know better of it and since the subject of processing is outside the intended scope of this post, I will kindly decline at this time. Besides, the processing is nothing too special or sophisticated. More importantly, anyone who reads this post can more easily get values in and out if the FLTK library and process their values in anyway that benefits their own project. Thanks for your help. I am sure many others will be thankful too since I might post the answer to the other forums where I asked for the same help, and might send Erco the code so that he can use it to publish a tutorial on the subject.

    The reason I asked you about the processing was because you seem (or seemed) to think that you need an integer array to do it, and I doubted that this was really the case.

    David Wilkinson | Visual C++ MVP

    Wednesday, July 23, 2014 2:07 PM
  • Your code was inserted in to the function with my own code marked out. But at compile time, the compiler complained about the "os::ostringstream os;" line of code and then all of the subsequently related expressions. The exact error code is: C2079. It is probably just a difference in my IDE's particular configuration, which is VC10 in its default configuration, but with the FLTK GUI libraries installed. Or it is the lack of a declaration in the #include statements of my program. I have marked your post as the answer too since you are a C++ MVP.

    • Edited by MHostetter Wednesday, July 23, 2014 2:27 PM
    Wednesday, July 23, 2014 2:23 PM
  • Your code was inserted in to the function with my own code marked out. But at compile time, the compiler complained about the "os::ostringstream os;" portion of the code and then all of the subsequently related expressions. It gives the error code: C2079. It is probably just a difference in my IDE's particular configuration, which is VC10 in its default configuration, but with the FLTK GUI libraries installed. So I have marked your post as the answer too since you are a C++ MVP.

    If you look up the documentation for std::ostringstream, here for example

    http://en.cppreference.com/w/cpp/io/basic_ostringstream

    you will find that it requires the <sstream> header.


    David Wilkinson | Visual C++ MVP

    Wednesday, July 23, 2014 2:28 PM
  • Thanks for the header. Bellow is a simple example of the widget i/o for processing.

    #include <cstdlib>
    #include <cstring>
    #include <FL/Fl.H>
    #include <FL/Fl_Window.H>
    #include <FL/Fl_Int_Input.H>
    #include <FL/Fl_Output.H>
    #include <FL/Fl_Button.H>
    using namespace std;

    int vHo[2]={{0},{0}};

    void reset(char *a)
    {
    char reset[4]={{'a'}{'b'}{'c'}{'d'}};
    for(int i=0; i<4; i++)
    {
    a[i]=reset[i];
    }
    }

    void cb_calculate(Fl_Widget *o, void*)
    {
    Fl_Int_Input *v1 = (Fl_Int_Input*)o->parent()->child(0);
    Fl_Int_Input *v2 = (Fl_Int_Input*)o->parent()->child(1);
    Fl_Output *v3 = (Fl_Output*)o->parent()->child(2);

    const char *ptr1;
    int *ptr2;
    char vR[4]={{'a'}{'b'}{'c'}{'d'}};
    char vS[4]={{'a'}{'b'}{'c'}{'d'}};
    int avgval = 0;

    //LOAD to ARRAY first Fl_Int_Input
    ptr1 = v1->value();
    for (size_t i = 0; i < strlen(ptr1); i++)
    {
    vR[i] = ptr1[i];
    }
    ptr1 = &vR[0];
    avgval = atoi(ptr1);
    vHo[0] = avgval;
    reset(vR);
    avgval = 0;

    //LOAD to ARRAY second Fl_Int_Input
    ptr1 = v2->value();
    for (size_t i = 0; i < strlen(ptr1); i++)
    {
    vR[i] = ptr1[i];
    }
    ptr1 = &vR[0];
    a gval = atoi(ptr1);
    vHo[1] = avgval;
    reset(vR);
    avgval = 0;

    //PROCESS ARRAY VALUES
    ptr2 = &vHo[0];
    int pv1 = *ptr2;
    ptr2 = &vHo[1];
    int pv2 = *ptr2;
    avgval = ((pv1+pv2)/2);

    //LOAD to Fl_Output
    itoa(avgval, vS, 10);
    ptr1 = &vS[0];
    v3->value(ptr1);
    }

    int main()
    {
    Fl_Window *win = new Fl_Window(200,200, "I/O");
    Fl_Int_Input *v1 = new Fl_Int_Input(90,10,35,20,"Value 1:");
    v1->maximum_size(3);
    Fl_Int_Input *v2 = new Fl_Int_Input(90,40,35,20,"Value 2:");
    v2->maximum_size(3);
    Fl_Output *v3 = new Fl_Output(90,70,35,20,"Avg:");
    Fl_Button *b1 = new Fl_Button(90,120,35,20,"Calc."); b1->callback(cb_calculate);
    win->end();
    win->show();
    return (Fl::run());
    }

    Copy this code to a VC10 IDE and it should compile into a working program.
    This marks the first full program written from my cellphone.
    • Edited by MHostetter Thursday, July 24, 2014 10:49 AM
    Thursday, July 24, 2014 10:48 AM
  • Thanks for the header. Bellow is a simple example of the widget i/o for processing.
    ...
    Copy this code to a VC10 IDE and it should compile into a working program.
    This marks the first full program written from my cellphone.

    This code will certainly not compile as written, for at least two reasons. Typing code directly on the forum is never a good idea. Always copy and paste your actual code.

    You do not appear to have taken note of any of the suggestions in my previous post. In particular the lines like

    char vR[4]={{'a'}{'b'}{'c'}{'d'}};

    This line does not compile for me. Perhaps you mean

    char vR[4]={'a', 'b', 'c', 'd'};

    Even so, I do not see the purpose of this line. Note also that the array is not nul-terminated. Then when you do

    for (size_t i = 0; i < strlen(ptr1); i++)
    {
       vR[i] = ptr1[i];
    }

    vR is still not nul-terminated, so I do not see how the subsequent call to atoi() can work. Also, what do you think happens if strlen(ptr1) is greater than 4? Perhaps you are sure this will not be the case, but this is very dangerous code. In any case, as I told you before, it is not necessary to copy the contents of ptr1 before calling atoi().

    Here is a simplified version of your code (untested):

    #include <string.h>
    #include <sstream>
    
    int vHo[2] = {0, 0}; 
    
    void cb_calculate(Fl_Widget *o, void*)
    {
    	Fl_Int_Input *v1 = (Fl_Int_Input*)o->parent()->child(0);
    	Fl_Int_Input *v2 = (Fl_Int_Input*)o->parent()->child(1);
    	Fl_Output *v3 = (Fl_Output*)o->parent()->child(2);
    
    	const char *ptr1;
    
    	ptr1 = v1->value();
    	vHo[0] = atoi(ptr1);
    
    	ptr1 = v2->value();
    	vHo[1] = atoi(ptr1);
    
    	int avgval = (vHo[0] + vHo[1])/2;
    
    	//LOAD to Fl_Output
    	std::ostringstream os;
    	os << avgval;
    	v3->value(os.str().c_str());
    }



    David Wilkinson | Visual C++ MVP


    • Edited by davewilk Thursday, July 24, 2014 12:25 PM typo
    • Marked as answer by MHostetter Thursday, July 24, 2014 2:30 PM
    Thursday, July 24, 2014 12:22 PM
  • The code that you provided compiles quite fine. Even if modern processors can run quickly through large sections of code, it is quite nice that the efficiently written code cleans up the visuals while coding in the IDE. I am still using itoa() as part of the process of sending values back to the widget though, even though it entails one or two lines more of code compared to the version that you have presented. Seeing atoi()/ itoa() in the written code has a nice sense of symmetry to it.
    • Edited by MHostetter Thursday, July 24, 2014 2:34 PM
    Thursday, July 24, 2014 2:30 PM
  • Well, the difference in code length does not have to do with itoa() versus std::ostringstream. It has to do with the fact that you have a lot of unnecessary (and confusing) copying.

    In addition, as I said before, I do not see how your code can work (due to lack of nul-termination). You do understand about nul-terminated strings, don't you? C and C++ can be very dangerous if you do not.

    As to symmetry between atoi() and itoa(), you should realize that atoi() is relatively safe, while itoa() is very dangerous (and is not present in current standard C or C++).

    If you want to have symmetry, you can use std::istringstream for reading.

    int vHo[2] = {0, 0};
    const char* ptr1 = v1->value();
    std::istringstream is(ptr1);
    is >> vHo[0];


    David Wilkinson | Visual C++ MVP

    Thursday, July 24, 2014 2:47 PM
  • Yes, my initial code had what I suppose now were redundancies with the workings of the functions that were also being used. Now that the code is both functioning and cleaner, I tried adding fstream functionality for saving the values to a text file, but there is a new unexpected problem with this. The compiler complains with the following error: main.obj: error LNK 2019: unresolved external symbol __imp__CrtDbgReportW referenced in function "public: char const & __thiscall std::_String_const_iterator<char,struct std::char_traits<char>,class std::allocator<char>>::operator*(void)const " (...

    I enabled function-level linking and used /FORCE to create the program image and found that the program gets as far as creating a blank file without the .txt ending and then crashes its window.

    I also tried the fstream code in a separate console program's function, but received another LNK error. /FORCE was used to compile the exe and it worked fine in the console program. But for the larger window program, the error crashes the program. So it seems the LNK error has to be resolved. I would have posted the error in a separate thread, but posting a new thread has not been working on my phone recently. Sample code can be found bellow:

    int vHo[2] = {{'a'},{'b'},{'c'}};
    char vS[4] = {{'a'},{'b'},{'c'}};
    int avgval = 0;
    const char *ptr1;

    void cb_calculate(Fl_Widget *o, void*)
    {
    //...
    ptr1 = v1->value();
    vHo[0] = atoi(*ptr1);
    ptr1 = v2->value();
    vHo[1] = atoi(*ptr1);

    avgval = (vHo[0]+vHo[1])/2;vHo[0] = atoi(*ptr1);

    itoa(avgval,vS,10);
    ptr1 = &vS[0];
    v3->value(ptr1);

    ofstream file("DataFile", ios::out | ios::trunc);
    file << vHo[0] << vHo[1];
    file.close();
    }

    With more success, I wrote the fstream code into the following type of function in a smaller console program:

    int save()
    {
    //fstream code
    return 0;
    }





    Can an example of fstream being used in a function be given?
    • Edited by MHostetter Sunday, July 27, 2014 12:22 PM
    Sunday, July 27, 2014 11:37 AM
  • Yes, my initial code had what I suppose now were redundancies with the workings of the functions that were also being used. Now that the code is both functioning and cleaner, I tried adding fstream functionality for saving the values to a text file, but there is a new unexpected problem with this. The compiler complains with the following error: main.obj: error LNK 2019: unresolved external symbol __imp__CrtDbgReportW referenced in function "public: char const & __thiscall std::_String_const_iterator<char,struct std::char_traits<char>,class std::allocator<char>>::operator*(void)const " (...

    I enabled function-level linking and used /FORCE to create the program image and found that the program gets as far as creating a blank file without the .txt ending and then crashes its window.

    I also tried the fstream code in a separate console program's function, but received another LNK error. /FORCE was used to compile the exe and it worked fine in the console program. But for the larger window program, the error crashes the program. So it seems the LNK error has to be resolved. I would have posted the error in a separate thread, but posting a new thread has not been working on my phone recently. Sample code can be found bellow:

    int vHo[2] = {{'a'},{'b'},{'c'}};
    char vS[4] = {{'a'},{'b'},{'c'}};
    int avgval = 0;
    const char *ptr1;

    void cb_calculate(Fl_Widget *o, void*)
    {
    //...
    ptr1 = v1->value();
    vHo[0] = atoi(*ptr1);
    ptr1 = v2->value();
    vHo[1] = atoi(*ptr1);

    avgval = (vHo[0]+vHo[1])/2;vHo[0] = atoi(*ptr1);

    itoa(avgval,vS,10);
    ptr1 = &vS[0];
    v3->value(ptr1);

    ofstream file("DataFile", ios::out | ios::trunc);
    file << vHo[0] << vHo[1];
    file.close();
    }

    With more success, I wrote the fstream code into the following type of function in a smaller console program:

    int save()
    {
    //fstream code
    return 0;
    }

    Can an example of fstream being used in a function be given?

    This code cannot possibly work. It should be

    ptr1 = v1->value();
    vHo[0] = atoi(ptr1);
    ptr1 = v2->value();
    vHo[1] = atoi(ptr1);

    Also, the initialization of the vHo array is incorrect (and as I told you before, there is no purpose to these initializations you are doing -- they are just distracting). If you wish, you can do zero initialization of the arrays by

    int vHo[2] = {0};
    char vS[4] = {0};

    I would really advise you to stop trying to post code from your phone. Post from your computer, when you can copy your actual code from Visual Studio.

    Also, you do not need

    itoa(avgval,vS,10);
    ptr1 = &vS[0];
    v3->value(ptr1);

    You can just do

    itoa(avgval,vS,10);
    v3->value(vS);

    Also, as I told you before, itoa() is a very dangerous function, and not thread safe.

    As to your LNK problem, of course fstream can be used in a function. In you console program, main() is a function.

    Does this link help you

    http://stackoverflow.com/questions/6003368/unresolved-externals-in-c-when-using-vectors-and-find

    ? The suggestion is that your problem has to do with invalid debug/release settings in your program.


    David Wilkinson | Visual C++ MVP

    Sunday, July 27, 2014 2:33 PM
  • I read your answer and thought no. Tried it out and saw it was a yes. NDEBUG allowed for the compiling process to finish without errors. And the program runs fine with out crashing either. I would not have been able to experiment with the settings for the preprocessor because it has no drop down list. So thank you very much for the pointer.
    Sunday, July 27, 2014 3:23 PM