#1
  1. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Sep 2013
    Posts
    10
    Rep Power
    0

    Smile Problem with functions


    Hello :)
    I'm a beginner in programming and I need some ideas for this problem:
    I have an integer i and an arbitrary collection of functions
    (f1,..., fn) that accept an integer argument and also return an integer.
    I have to write a program that returns a collection of integers representing the results of the application of those functions on the value of input, i.
    Example:
    4 and [add_one, multiply_by_five] => output will be [5, 20]. Another example of input: 7 and [subtract_three, add_two, multiply_by_three] => output will be [4, 9, 21].

    Thank you, any help would be greatly appreciated! :)
  2. #2
  3. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,253
    Rep Power
    2222
    Here's a hint: we do not do anybody's homework for them. You need to make an honest effort to do your own work. If you encounter problems, then describe the specific problem and we will help you. We do want you to learn and will do what we can to help you to learn. Doing your work for you will not help you learn.

    One proven way to approach a problem is to work it out by hand, describing in English (or whatever your native language is) in a step-by-step manner. From that natural language procedure you will see how to design your program.
  4. #3
  5. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Sep 2013
    Posts
    10
    Rep Power
    0
    Yes, I know, you are right, but my first problem is that I don't know how to convert strings into numbers and operators.
    thanks
  6. #4
  7. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,253
    Rep Power
    2222
    That's relatively low-level, down in the details of the code. First, you need to design the overall program as I had described. Besides, there was nothing in your statement of the problem that said anything about converting strings into numbers and operators.

    Read your textbook about console I/O, which is about reading input from the keyboard and displaying output on the monitor screen. The input functions that your textbook will describe to you will tell you how to convert the keyboard input, which is in string form, to whatever internal datatypes you need.

    We work for a living in a profession that does not afford us much free time. We are using what little free time we have to help others. In order to make the best use of our time, we respond best to specific questions about specific problems. We cannot use that time to teach others everything about C programming; that is what your programming class and textbook are for. If you don't know something, then read up on it. If you don't know what it's called, then we can tell you that. If you then don't understand something, then you can ask use specific questions.

    A few details about you may help us. "Beginner" is too nebulous. More exactly how far have you gotten in your class? What do you know how to do already? That you understand the need to convert strings to numbers indicates that you do know something already. Also, the operating system and compiler that you are using can be valuable information.

    But first you need to work on a procedure for your problem.
  8. #5
  9. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Sep 2013
    Posts
    10
    Rep Power
    0
    Hello!

    I'm back with the code I've been working at so far:


    Code:
    #include<iostream>
    #include<vector>
    #include <map>
    #include <set>
    #include <string>
    #include <sstream>
    #include <algorithm>
    #include <cctype>
    using namespace std;
    typedef unsigned long long accum_type;
    typedef std::map<std::string, accum_type> token_map;
    typedef std::set<std::string> token_set;
    char only_upper(char c) {
    	return (isalpha(c) ? toupper(c) : ' ');
    }
    
    class probl
    {     public: int n; public: int inp;
    public: vector <string> functions;
    public:
    	void get_functions()
    	{
    
    		for(int i=0;i<n;i++)
    		{cout<<"dati functiile:";      
    		cin>>functions[i];}
    	}
    
    public: int convert (string line) { 
    
    	token_map add, multiply;
    	token_set special;
    
    			// Additive tokens
    			add["ZERO"]     = 0;
    			add["ONE"]      = 1;  add["TWO"]      = 2;  add["THREE"]     = 3;
    			add["FOUR"]     = 4;  add["FIVE"]     = 5;  add["SIX"]       = 6;
    			add["SIX"]      = 6;  add["SEVEN"]    = 7;  add["EIGHT"]     = 8;
    			add["NINE"]     = 9;  add["TEN"]      = 10; add["ELEVEN"]    = 11;
    			add["TWELVE"]   = 12; add["THIRTEEN"] = 13; add["FOURTEEN"]  = 14;
    			add["FIFTEEN"]  = 15; add["SIXTEEN"]  = 16; add["SEVENTEEN"] = 17;
    			add["EIGHTEEN"] = 18; add["NINETEEN"] = 19; add["TWENTY"]    = 20;
    			add["THIRTY"]   = 30; add["FORTY"]    = 40; add["FIFTY"]     = 50;
    			add["SIXTY"]    = 60; add["SEVENTY"]  = 70; add["EIGHTY"]    = 80;
    			add["NINETY"]   = 90;
    
    			// Multiplicative tokens
    			multiply["HUNDRED"] = 100; multiply["THOUSAND"] = 1000;
    			multiply["MILLION"] = 1000000; multiply["BILLION"] = 1000000000;
    			// etc., if you really need to
    
    			// "Special" tokens are multipliers that do not need to be moved
    			// into the real accumulator immediately.
    			special.insert("HUNDRED");
    
    
    			if(!line.empty()) {
    
    
    
    				std::istringstream tokens(line);
    				std::string token;
    
    				// Accumulator for this "component"
    				accum_type sub_accum = 0;
    
    				// Accumulator for entire string
    				accum_type accum = 0;
    
    				// Move sub_accum to accum?
    				bool move_to_accum = false;
    
    				while (tokens >> token) {
    					if (add[token]) {
    						if (move_to_accum) {
    							accum += sub_accum;
    							sub_accum = 0;
    							move_to_accum = false;
    						}
    
    						sub_accum += add[token];
    					} else if (multiply[token]) {
    						// Handle a bare multiplier properly
    						if (sub_accum)
    							sub_accum *= multiply[token];
    						else
    							sub_accum = multiply[token];
    
    						// We will move to accum only if the token wasn't "special"
    						move_to_accum = (special.find(token) == special.end());
    					}
    				}
    
    				accum += sub_accum;
    				cout<< accum;
    				system("pause");
    			}
    
    		}   
    
    
    public: void split()
    		{  vector <string> s1;  vector <string> s2;
    		int v[5000], final[5000];
    
    		for(int i=0;i<n;i++)
    		{
    			string str=functions[i];
    			int found = str.find_last_of("_");  
    			s1[i]=str.substr(0,found);   //s1=functia
    			s2[i]=str.substr(found+1);   //s2=argumentul
    
    			v[i]=convert(s2[i]);   //in v retin numerele convertite
    			if( s1[i]=="add_")
    				final[i]= inp+v[i];
    			if(s1[i] == "substract_")
    				final[i]=inp-v[i];
    			if(s1[i]== "multiply_by_")
    				final[i]= inp*v[i];
    		}
      for (int i=0; i<n;i++)
       cout<<final[i]<<", ";
    		} 
    
    
    };  
    
    int main()
    {probl b; int inp, n;
    cout<<"dati input-ul"; cin>>inp; cout<<"dati n"; cin>>n;
    b.get_functions();
    b.split();
    system("pause");
    return 0;
    
    }
    I didn't know how to use the console I/O for converting written numbers to numbers, but I've used a function.
    Now I have some errors and I can't figure out how to solve the situation...
    108 `str' undeclared (first use this function)
    `final' undeclared (first use this function) etc
    How (and where) should I declare the variables from the functions in order to be seen from the main function, too?
    I tried to declare them as static, but I still get errors.



    LATER EDIT: I don't have errors anymore, but when I try to run it, the program crashes after reading the first function as a string. :(

    thank you so much!
  10. #6
  11. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,253
    Rep Power
    2222
    Lei italiano? While all programming is in English, native languages can come through in the comments, variable names, and prompts. One of the more interesting code listings I've seen was a BASIC program written by a Russian. It had a mixture of Latin alphabet for the code and Cyrillics for the comments. BTW, I've only learned a little Italian.

    For using some non-trivial techniques, your errors are surprisingly basic and your inability to correct them is surprising. Here is what I get when I try to compile using MinGW g++ on WinXP:
    C:TEST>g++ -Wall ely01.cpp
    ely01.cpp: In method `void probl::split()':
    ely01.cpp:123: `str' undeclared (first use this function)
    ely01.cpp:123: (Each undeclared identifier is reported only once
    ely01.cpp:123: for each function it appears in.)
    ely01.cpp: In function `int main()':
    ely01.cpp:151: `final' undeclared (first use this function)

    C:TEST>
    One of the most basic concepts in C/C++ is that you must declare a variable before you use it. That first error tells you that str is not declared in probl::split(). That means that you need to declare it in order to correct that error. Extremely basic.

    Similarly, the array, final, is not declared in main(). But in that case you are wanting to print out the final array that you created in probl::split(). The basic problem there is that final is a local variable in split() and a local variable only exists inside the function that it's declared in. That means at least two things:
    1. That local variable is not known anywhere else outside its function.
    2. As soon as you exit a function, all of its local variables cease to exist.

    I would recommend that you move final out of split and make it a property of the probl class. Then you should create another method for outputting it or else make it a public property and access it in main() as b.final[i].

    Those two changes would eliminate your compiler errors.

    Also, that system("pause") in main() doesn't do anything, because you will have returned before you execute it.

    Originally Posted by ely_en
    I didn't know how to use the console I/O for converting written numbers to numbers, but I've used a function.
    Since you hadn't told us what language you were using, I had assumed it to be C. The console I/O function I was thinking of was scanf, but since you are using C++ that would be cin>> . In C (and in C++ if you don't use iostream which I don't) you can use sscanf to find and convert numbers in a string (that would be a C-style string). I wasn't sure about the same thing using iostream, but I suspected a solution and you confirmed it for me with your (tokens >> token), that showed me that you can output from a stringstream object just as you can input into one to create a string (same as using sprintf in C). So I would think that something like this should work:
    Code:
        int n;
        std::istringstream tokens(line);
        
        tokens >> n;  // assuming that the next characters in tokens are for a number
    Though I'm not sure how to check for errors.

    Otherwise, there are C functions such as atoi or strtol, but they require a C-style string which you can get from a string class with the c_str() method.

    Or you could do it character by character starting with the first character. Initialize the int accumulator to zero and then perform the loop until you encounter a non-digit character:
    1. multiply the accumulator by 10. The first time, the accumulator is zero so nothing happens, but this is important for each digit that follows.
    2. Read the next character from the string, which should be a digit, and convert it to its numeric value (char ch = str[i]; int num = ch -'0';).
    3. Add the digit's numeric value to the accumulator.
    4. Goto Step 1. Of course, you would use a loop structure and not an actual goto.

    That will convert a string representing a decimal integer into a numeric value. While you are scanning that string, you can also test for and detect the characters for operators.
  12. #7
  13. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jan 2013
    Posts
    159
    Rep Power
    19
    In your get_functions() function you are accessing your vector out of bounds. Your vector contains zero elements so you can't try to access any elements. You need to use push_back() to insert an element into your vector.

    Jim
  14. #8
  15. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Sep 2013
    Posts
    10
    Rep Power
    0
    Thank you so much, I'll try to understand what you have explained to me. :D
    Sorry for those funny errors, I had made a later edit in my previous post as soon as I got rid of them, but I don't know why it's crashing at runtime.

    Oh, and I'm not italian, I'm romanian. :D
    thank you!
    :)
  16. #9
  17. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,253
    Rep Power
    2222
    Well, Romanian is also a Romance language, derived from Latin. I was mainly going by the plural endings -i and -e which are also used in Italian, though I should have paid more attention to the words "functia" and "argumentul". I had started college as a foreign language major (German) so language always piques my interest. My first programming language class was FORTRAN, which I treated as just another language. With that attitude towards programs, I would and still do read the program for what it says, which has always helped me immensely when debugging.

    What kind of runtime error message do you get? More importantly, do you have a debugger? If so, then compile a debug version of your program and run it in the debugger. When the program crashes the debugger will be at the location where it crashed and you will be able to see what values are in the variables.

    PS

    Good eye, Jim. I also only just now saw your message.
  18. #10
  19. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Sep 2013
    Posts
    10
    Rep Power
    0
    :) Very nice.

    thank you, Jim! I've modified into this:
    i=0;
    while(i<n)
    {cout<<"give functions:"; cin>>stri;
    functions.push_back(stri); i++;}

    But now I see that the n that I give in main doesn't keep its value when it goes into get_functions. For example, if I give n=2 in main, in get_functions n will be a very big number and that "for" doesn't stop.

    No, I don't have a debugger. What would you recommend?
    I could use the debug function from dev c++, right?
  20. #11
  21. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jan 2013
    Posts
    159
    Rep Power
    19
    That's because 'n' in main is not the same 'n' that is contained in your class. If you want your class variables to have values you must initialize them when you construct your class or assign a value to them before you try to use them.

    Jim
  22. #12
  23. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,253
    Rep Power
    2222
    Originally Posted by ely_en
    But now I see that the n that I give in main doesn't keep its value when it goes into get_functions. For example, if I give n=2 in main, in get_functions n will be a very big number and that "for" doesn't stop.
    Remember: a local variable is only known inside its own function. The n you declare in main is completely different and separate from the n that you declare in the probl class. The n in main does indeed keep its value perfectly well, but you never initialize the n in probl and so it contains garbage, whatever just happens to have last been written to that memory location. In your case, it's a large value, though it just as easily could be a negative value.

    If you want the value of the n in the probl object to be the same as the value of the other n in main, then you need to set it to that value.

    This seems to be a common misconception among beginners, since we've seen others do the same thing. Understand that the variables that you declare inside a function are local to that function and their very existence is not known outside that function. So if you to set a local variable in one function, you cannot use it in another function. That is why you have function parameters so that you can pass values into a function and that is why functions have return values so that you can pass a value from a function to the function that had called it.

    Scope is the property of a variable that determines where it is visible and how long it exists. Scope is a very important concept that you must keep in mind all the time. Learn to look at a variable and see what its scope is.


    I had given up on Bloodshed's Dev-C++ several years ago, but I kept its MinGW gcc compiler and continue to use that from the command line. I never tried its debugger, nor have I tried the Orwell Dev-C++ IDE. I have used the debugger in Microsoft Visual Studio 2008. You can download a free version of Visual C++ which has a fully functional debugger. Though you may want to try the debugger in Dev-C++ first.
  24. #13
  25. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Sep 2013
    Posts
    10
    Rep Power
    0
    Thank you so much, I'm done with it.
    ;)

    I'll try to keep in mind all your advices. They are very useful to me.

IMN logo majestic logo threadwatch logo seochat tools logo