I want to generate some variables using for command. look at code below:
for (char ch='a'; ch<='z'; ch++)
int ch=0;
It just an example, after running code above, I want to have int a, int b, int c ...
another example:
for (int i=0; i<10; i++)
int NewiEnd=0;
For example after running code above, we will have int New1End, int New2End etc.
Hope I'm clear enough, How can I do such thing in C++??
No, not possible, not exactly. However, this is possible:
std::map<char,int> vars;
for (char ch='a'; ch<='z'; ch++)
vars[ch] = 0;
std::cout << vars['a'] << vars['b'] << vars['c'];
You can also have std::map<std::string, int>.
std::map<std::string,int> vars;
for (int i=0; i<10; i++)
vars["New" + std::to_string(i) + "End"] = 0;
std::cout << vars["New5End"];
What you're trying to do isn't possible in C or C++.
What you seem to want is a map of the type:
std::map<std::string, int> ints;
This will let you call "variables" by name:
ints["a"] = 0;
ints["myVariable"] = 10;
Or as given in your example:
std::map<char, int> ints;
for (char ch='a'; ch<='z'; ch++)
ints[ch] = 0;
If you are just about to use 'a' - 'z' you could use an array of ints:
int ints['z' + 1];
ints['a'] = 0;
ints['z'] = 0;
But this allocates unnecessary space for the ascii characters below 'a'.
In C/C++ the variable names have "gone away" by the time the code has been compiled and run. You can't print out the name of an existing variable at run time via "reflection"...much less make new named variables. People looking for this feature find out that the only generalized way you can do it falls down to using the preprocessor:
generic way to print out variable name in c++
The preprocessor could theoretically be applied to your problem as well, with certain constraints:
Writing a while loop in the C preprocessor
But anyone reading your code would probably drive a stake through your heart, and be justified in doing so. Both Sunday-morning laziness and a strong belief that it's not what you (should) want leads me to not try and write a working example. :-)
(For the curious, the preprocessor is not Turing-Complete, although there are some "interesting" experiments)
The nature of C/C++ is to have you build up named tables on an as-needed basis. The languages that offer this feature by default make you pay for the runtime tracking of names whether you wind up using reflection or not, and that's not in the spirit of this particular compiled language. Others have given you answers that are more on the right track.
Related
I am trying to write a lexer, when I try to copy isdigit buffer value in an array of char, I get this core dumped error although I have done the same thing with identifier without getting error.
#include<fstream>
#include<iostream>
#include<cctype>
#include <cstring>
#include<typeinfo>
using namespace std;
int isKeyword(char buffer[]){
char keywords[22][10] = {"break","case","char","const","continue","default", "switch",
"do","double","else","float","for","if","int","long","return","short",
"sizeof","struct","void","while","main"};
int i, flag = 0;
for(i = 0; i < 22; ++i){
if(strcmp(keywords[i], buffer) == 0)
{
flag = 1;
break;
}
}
return flag;
}
int isSymbol_Punct(char word)
{
int flag = 0;
char symbols_punct[] = {'<','>','!','+','-','*','/','%','=',';','(',')','{', '}','.'};
for(int x= 0; x< 15; ++x)
{
if(word==symbols_punct[x])
{
flag = 1;
break;
}
}
return flag;
}
int main()
{
char buffer[15],buffer1[15];
char identifier[30][10];
char number[30][10];
memset(&identifier[0], '\0', sizeof(identifier));
memset(&number[0], '\0', sizeof(number));
char word;
ifstream fin("program.txt");
if(!fin.is_open())
{
cout<<"Error while opening the file"<<endl;
}
int i,k,j,l=0;
while (!fin.eof())
{
word = fin.get();
if(isSymbol_Punct(word)==1)
{
cout<<"<"<<word<<", Symbol/Punctuation>"<<endl;
}
if(isalpha(word))
{
buffer[j++] = word;
// cout<<"buffer: "<<buffer<<endl;
}
else if((word == ' ' || word == '\n' || isSymbol_Punct(word)==1) && (j != 0))
{
buffer[j] = '\0';
j = 0;
if(isKeyword(buffer) == 1)
cout<<"<"<<buffer<<", keyword>"<<endl;
else
{
cout<<"<"<<buffer<<", identifier>"<<endl;
strcpy(identifier[i],buffer);
i++;
}
}
else if(isdigit(word))
{
buffer1[l++] = word;
cout<<"buffer: "<<buffer1<<endl;
}
else if((word == ' ' || word == '\n' || isSymbol_Punct(word)==1) && (l != 0))
{
buffer1[l] = '\0';
l = 0;
cout<<"<"<<buffer1<<", number>"<<endl;
// cout << "Type is: "<<typeid(buffer1).name() << endl;
strcpy(number[k],buffer1);
k++;
}
}
cout<<"Identifier Table"<<endl;
int z=0;
while(strcmp(identifier[z],"\0")!=0)
{
cout <<z<<"\t\t"<< identifier[z]<<endl;
z++;
}
// cout<<"Number Table"<<endl;
// int y=0;
// while(strcmp(number[y],"\0")!=0)
// {
// cout <<y<<"\t\t"<< number[y]<<endl;
// y++;
// }
}
I am getting this error when I copy buffer1 in number[k] using strcpy. I do not understand why it is not being copied. When i printed the type of buffer1 to see if strcpy is not generating error, I got A_15, I searched for it, but did not find any relevant information.
The reason is here (line 56):
int i,k,j,l=0;
You might think that this initializes i, j, k, and l to 0, but in fact it only initializes l to 0. i, j, and k are declared here, but not initialized to anything. As a result, they contain random garbage, so if you use them as array indices you are likely to end up overshooting the bounds of the array in question.
At that point, anything could happen—in other words, this is undefined behavior. One likely outcome, which is probably happening to you, is that your program tries to access memory that hasn't been assigned to it by the operating system, at which point it crashes (a segmentation fault).
To give a concrete demonstration of what I mean, consider the following program:
#include <iostream>
void print_var(std::string name, int v)
{
std::cout << name << ": " << v << "\n";
}
int main(void)
{
int i, j, k, l = 0;
print_var("i", i);
print_var("j", j);
print_var("k", k);
print_var("l", l);
return 0;
}
When I ran this, I got the following:
i: 32765
j: -113535829
k: 21934
l: 0
As you can see, i, j, and k all came out such that using them as indices into any of the arrays you declared would exceed their bounds. Unless you are very lucky, this will happen to you, too.
You can fix this by initializing each variable separately:
int i = 0;
int j = 0;
int k = 0;
int l = 0;
Initializing each on its own line makes the initializations easier to see, helping to prevent mistakes.
A few side notes:
I was able to spot this issue immediately because I have my development environment configured to flag lines that provoke compiler warnings. Using a variable before it's being initialized should provoke such a warning if you're using a reasonable compiler, so you can fix problems like this as you run into them. Your development environment may support the same feature (and if it doesn't, you might consider switching to something that does). If nothing else, you can turn on warnings during compilation (by passing -Wall -Wextra to your compiler or the like—check its documentation for the specifics).
Since you declared your indices as int, they are signed integers, which means they can hold negative values (as j did in my demonstration). If you try to index into an array using a negative index, you will end up dereferencing a pointer to a location "behind" the start of the array in memory, so you will be in trouble even with an index of -1 (remember that a C-style array is basically just a pointer to the start of the array). Also, int probably has only 32 bits in your environment, so if you're writing 64-bit code then it's possible to define arrays too large for an int to fully cover, even if you were to index into the array from the middle. For these sorts of reasons, it's generally a good idea to type raw array indices as std::size_t, which is always capable of representing the size of the largest possible array in your target environment, and also is unsigned.
You describe this as C++ code, but I don't see much C++ here aside from the I/O streams. C++ has a lot of amenities that can help you guard against bugs compared to C-style code (which has to be written with great care). For example, you could replace your C-style arrays here with instances of std::array, which has a member function at() that does subscripting with bounds checking; that would have thrown a helpful exception in this case instead of having your program segfault. Also, it doesn't seem like you have a particular need for fixed-size arrays in this case, so you may better off using std::vector; this will automatically grow to accommodate new elements, helping you avoid writing outside the vector's bounds. Both support range-based for loops, which save you from needing to deal with indices by hand at all. You might enjoy Bjarne's A Tour of C++, which gives a nice overview of idiomatic C++ and will make all the wooly reference material easier to parse. (And if you want to pick up some nice C habits, both K&R and Kernighan and Pike's The Practice of Programming can save you much pain and tears).
Some general hints that might help you to avoid your cause of crash totally by design:
As this is C++, you should really refer to established C++ data types and schemes here as far as possible. I know, that distinct stuff in terms of parser/lexer writing can become quite low-level but at least for the things you want to achieve here, you should really appreciate that. Avoid plain arrays as far as possible. Use std::vector of uint8_t and/or std::string for instance.
Similar to point 1 and a consequence: Always use checked bounds iterations! You don't need to try to be better than the optimizer of your compiler, at least not here! In general, one should always avoid to duplicate container size information. With the stated C++ containers, this information is always provided on data source side already. If not possible for very rare cases (?), use constants for that, directly declared at/within data source definition/initialization.
Give your variables meaningful names, declare them as local to their used places as possible.
isXXX-methods - at least your ones, should return boolean values. You never return something else than 0 or 1.
A personal recommendation that is a bit controversional to be a general rule: Use early returns and abort criteria! Even after the check for file reading issues, you proceed further.
Try to keep your functions smart and non-boilerplate! Use sub-routines for distinct sub-tasks!
Try to avoid using namespace that globally! Even without exotic building schemes like UnityBuilds, this can become error-prone as hell for huger projects at latest.
the arrays keywords and symbols_punct should be at least static const ones. The optimizer will easily be able to recognize that but it's rather a help for you for fast code understanding at least. Try to use classes here to compound the things that belong together in a readable, adaptive, easy modifiable and reusable way. Always keep in mind, that you might want to understand your own code some months later still, maybe even other developers.
Is this efficient way to convert int to string?
int(int input) {
int myNumber = input;
string myString = "";
while (myNumber > 0) {
myString += char(myNumber % 10 + 48);
myNumber /= 10;
}
//reverse
string result = "";
for (int i = myString.size() - 1; i >= 0; i--) {
result += myString[i];
}
return result;
}
If not, is there some more efficient way to do this without using any additional libraries?
C++ for a long time has a function within a standard library that can do that. It is to_string.
For example you can do something along the lines of:
int a;
std::cin >> a;
std::string aStr = std::to_string(a);
You should always try to use existing functions, if at all possible. There are many reasons for that:
Efficiency. It is likely that there exist methods more efficient than those used in the implementation of the standard library. However, often you will find that by optimising one part of the code you actually lose efficiency in another aspect. Developers of STL try to balance all the aspects.
Error-proneness. You are pretty much guaranteed to have more bugs in your code, then exist in the implementation of STL.
Interoperability with other code. Very rarely we write something to be used all by itself these days. Most of the time we want the code, that can actually function with another part of the system. And writing your own implementation of standard functions can easily break the system as the whole.
Future improvement. As the standards mature, your code will start working better if you use standard functions. But if you use your own... then who knows what will happen.
I'm trying to define macros to read and print matrices in C++, but I'm trying something different, and it's not working:
#define rm(A, m, n, type)
for(int i = 0; i < m; i++)
for(int j = 0; j < n; j++)
scanf("%##type##", &A[i][j]);
A is the matrix (int or char)
I want to write d or c to read int or char, but this code isn't working and I don't even know why, I just tried to use the concat ## symbol to create the string that scanf receive as argument, but it bugs.
My questions are:
1 - why is it wrong?
2 - how can I make this macro work fine?
(if necessary, the solution may contain 1 or 2 macro declarations, but short ones, otherwise I wouldn't ask and I could just create a macro for int and other for char.
PS: this macro is written one line, the algorithm above is just to show what it does.
Thanks
If you really must make a macro for this - which, as others have pointed out, is a Really Bad Idea and Not The Right Way To Do This - the issue that you're encountering is that macros are interpreted by the preprocessor, which treats line breaks as as the end of a macro replacement. To fix this, you'll need to introduce some escape sequences at the ends of the lines:
#define rm(A, m, n, type) \
for(int i = 0; i < m; i++) \
for(int j = 0; j < n; j++) \
scanf("%" #type, &A[i][j]);
Notice that I've factored out your use of the token-pasting operator from the inside of the string, since the preprocessor doesn't fill in string literals for you, and instead opted to use the stringizing operator # to convert the type to a string literal. Since the compiler automatically concatenates adjacent string literals together, there's no need to paste anything. I should repeat that this is a really bad idea in that it hurts code readability and doesn't offer anything you can't already do with a regular C++ function.
You've tagged this question as C++, though, so I should point out that scanf has all sorts of type safety issues that can come up, so it's almost certainly safer to use the iostream library, which for all its faults does catch a ton of possible errors at compile-time.
Fundamentally, though, you shouldn't use macros for this. Just write a regular old function. Here's one way to do this, which has the added benefit that it automatically infers the sizes of arrays:
template <typename T, size_t m, size_t n>
void readArray(T (&array)[m][n], std::istream& source = std::cin) {
for (size_t i = 0; i < m; i++) {
for (size_t j = 0; j < n; j++) {
source >> array[i][j];
}
}
}
Now, you can say something like this:
double arr[137][42];
readArray(arr);
to read an array of doubles from cin, or
int arr[5][5];
ifstream input("my-file.txt");
readArray(arr, input);
to read an array of ints from an external file. This is type-safe and will raise a compiler error if you try reading in a case where the array size isn't defined or where the type can't be read. This prevents all sorts of possible problems. Compare this with your macro, where I could do something like this:
int arr[5][5];
rm(arr, 6, 6, f);
Oops - I just used the wrong array size and the wrong scanf specifier. Any time you can offload work to the compiler that saves you from having to make code changes across lots of places, it's worth considering!
I have seen code like,
Approach 1
for(int i = 0; i < 200; ++i) {
do_some_stuff(i);
}
Approach 2
const int max_limit = 200;
for(int i = 0; i < max_limit; ++i) {
do_some_stuff(i);
}
Is there any advantage for Approach 2 over Approach 1?
It's generally good practice to replace an integer constant by something with a meaningful name, so I'd say that's the main advantage of the second one. However, if the code is really simple than the extra line may just make it one more line to parse.
That said, if you are replacing something like this:
for(int i = 0; i < something.size(); ++i) {
do_some_stuff(i);
}
with
const int something_sz = something.size();
for(int i = 0; i < something_sz; ++i) {
do_some_stuff(i);
}
then there is the added benefit that it makes it obvious to the reader, as well as the compiler, that something.size() isn't changed by the call to do_some_stuff(i).
Use of magic numbers, such as 200 in your example, anywhere in your code is cause for concern. It makes the code harder to understand and maintain.
Approach 2 is better if the variable is appropriately named. max_limit has no more meaning than 200. However, if you use max_number_of_books, it is a lot more meaningful than 200.
For me, approach 2 is better, when you define a const like const int max_num_of_students it looks more meaningful and someone reading to that code, can easily understand what is going on.
Another advantage of using such const in loops is that if you are printing names of students more than one time, you don't need to change the condition in your loop every time the count of students gets increased. Go to your variable and change it to new student count.
We should avoid to using the magic number anytime when wrote codes. Because if you use the number 200 only, maybe others cannot understand your codes' intention well. But when you use const int max_limit = 200;, we can understand the number 200's meanings. Especially when your codes was very complex, you must write it with the second way.
2nd Approach is better as by this you can also get the value from the user:
cin>>max_limit;
Approach 2 is better as per my opinion.
Readability is enhanced.
For example:
int currentPortNo=getPortNo();
const int inputPort=80;
if(currentPortNo == inputPort){
//Get input from port
}
when compared to:
int currentPortNo=getPortNo();
if(currentPortNo == 80){
//Get input from port
}
Maintainability is enhanced since if we want inputPort should be initialized(changed) with 81 instead of 80 due to new requirements/limitations we can simply use:
const int inputPort=81;
instead of changing all the occasion wherever the value 80 is used in entire program.
Also, if you need to pass a pointer around the program.
Can have the scoping and typing properties
In java you can do something like:
Scanner sc = new Scanner(System.in);
int total = 0;
for(int i = 0; i<something;i++){
total+=sc.nextInt(); // <<< Doesn't require an extra variable
}
And my question is: can you do something similar in C or C++ ? and if there is, is it better?
This is what I currently do:
int total;
int aux; // <<< Need an extra variable to read input
for(int i = 0; i<something;i++){
scanf("%d",&aux);
total+=aux; // <<< and add the read value here
}
The obvious way to do it in C++ would be something like this:
int total = std::accumulate(std::istream_iterator<int>(std::cin),
std::istream_iterator<int>(),
0);
As it stands, this reads all the ints it can from the input file rather than requiring a separate specification of the number of input values. You could specify an N if you wanted to badly enough, but at least in my experience, you're not very likely to want that.
If you really want to specify N directly, the cleanest way to handle the situation would probably be to define an accumulate_n that works about like std::accumulate:
template <class InIt, class T>
T accumulate_n(InIt in, size_t n, T init) {
for (size_t i=0; i<n; i++)
init += *in++;
return init;
}
You'd use this about like the previous version, but (obviously enough) specifying the number of values to read:
int total = accumulate_n(std::istream_iterator<int>(std::cin),
something,
0);
I suppose I should add that (especially for production code) you'd probably want to add some constraints on the template parameters in the accumulate_n definition above. I also haven't tried to do anything about the possibility of bad input, such as containing something other than a number, or simply containing fewer items than specified. These can be dealt with, but offhand I don't remember how Java deals with them; I'd probably have to do some thinking/research to find/figure out exactly what reaction to such problems would be most appropriate.
Reading a number of variables from an input stream in c++ usually looks like follows (regarding your sample):
int total = 0;
int aux;
while(std::cin >> aux) {
// break on 'something' condition
total += aux;
}
So, I don't see a way how to do it without an auxiliary variable, that actually receives the value read from the std::istream, unless you provide a wrapper class yourself, that just provides that java like behavior.
"can you do something similar in C or C++ ? and if there is, is it better?"
I doubt it's worth to write such wrapper class for std::istream in c++ (You can just consider to use the std::accumulate() algorithm as mentioned in #JerryCoffin's answer).
For c language, there's no alternate choice, I actually can see/know about.