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.
I have been given following assignment
Write a simple telephone directory program; contain two dimensional arrays in which you have hard code names and telephone number. Then declare a simple character array. You have to prompt user to enter any name, which you want to search. This name should be store in this character array, then search this name from the two dimensional array. If number is found against entered name then program should display the number against this name, and if not found then program should display the message that name is not registered.
Here is my code but i could not get the number when i search for the name. I am new to coding so i am having trouble making this code work. Help is appreciated.
#include <iostream>
#include <conio.h>
using namespace std;
int getPhone(int p[5][10],int row, int col, char key[10],char n[5][10]);
int main() {
int i,j;
char search[10];
const int r = 5;
const int c = 10;
int element;
int phone[r][c] =
{
42-5429874,
42-5333156,
42-9824617,
42-9927562,
42-6238175
};
char name[r][c] = {"shazia","zara","sana","ahmad","maha"};
cout<<"\nEnter name to find in directory : ";
cin>>search[r];
element = getPhone(phone,r,c,search,name);
cin.get();
return 0;
}
int getPhone(int p[5][10],int row,int col,char key[10], char n[5][10]) {
int i, j;
for(i=0;i<row;i++)
for(j=0;j<col;j++)
p[5][10] = p[i][j];
if(key[j] = n[5][10])
cout<<"The desired number is: "<<p[i][j]<<endl;
else if(key[j]!=n[5][10])
cout<<"Sorry! This name is not registered.";
return p[i][j];
}
Your code contains several mistakes. Let's examine them.
for(i=0;i<row;i++)
for(j=0;j<col;j++)
p[5][10] = p[i][j];
Here, you make no change on your array, because just the value of p[5][10] is changed. Furthermore, you access an invalid memory zone, because array indexes go from 0 to size - 1 in C++. So last index is p[4][9].
if(key[j] = n[5][10])
In C++, comparing two values needs two =, because only one is an affectation that results the if to be always true. A tip to remember: two values to compare need two =.
else if(key[j]!=n[5][10])
The same than before, you access invalid memory zone. And are you sure that j is valid, e.g less than 10 ? If not, you do double invalid access.
cin>>search[r];
As search is an array of char, you do an input of only a single char there, which I think is not what you want and that can leads to segfault.
int phone[r][c] =
{
42-5429874,
42-5333156,
42-9824617,
42-9927562,
42-6238175
};
Your array is not good, a simple 1-dimension array is enough, not 2-dimensions. Furthermore, 42-54.. does a subtraction, and I think is not what you want.
There are others mistakes. But why not using C++ abstractions, like std::vector, or std::string? Your life would get so much easier. But I guess you have an old teacher that never took time to learn C++ news, or that is not a good teacher.
As a beginner, I suggest you to read C++ Primer and Programming: Principles and Practice Using C++ to introduce you both programming and modern C++.
It is wanted of me to implement the following function:
void calc ( double* a, double* b, int r, int c, double (*f) (double) )
Parameters a, r, c and f are input and b is output. “a” and “b” are two-dimensional matrices with “r” rows and “c”
columns. “f” is a function pointer which can point to any function of the following type:
double function‐name ( double x ) {
…
}
Function calc converts every element in matrix a, i.e., aij, to bij=f(aij) in matrix b.
I implement the calc function as follows, and put it in a program to test it:
#include <stdlib.h>
#include <iostream>
using namespace std;
double f1(double x){
return x * 1.7;
}
void calc (double* a, double* b, int r, int c, double (*f) (double))
{
double input;
double output;
for(int i=0; i<r*c; i++)
{
input = a[i];
output = (*f)(input);
b[i] = output;
}
}
int main()
{
// Input array:
int r=3;
int c=4;
double* a = new double[r*c];
double* b = new double[r*c];
// Fill "a" with test data
//...
for (int i=0; i<r*c; i++)
{
a[i] = i;
}
// Transform a to b
calc(a, b, r, c, f1);
// Print to test if the results are OK
//...
for (int i=0; i<r*c; i++)
{
b[i] = i;
}
return 0;
}
The problem is, I can't compile it. This is the output of DevC++ when I click on Compile and Execute button:
What's wrong?
I appreciate any comment to make the implementation more efficient.
As mentioned in a previous reply, this generally comes when compiling copy pasted code. If you have a Bash shell, the following command generally works:
iconv -f utf-8 -t ascii//translit input.c > output.c
It appears you have illegal characters in your source. I cannot figure out what character \240 should be but apparently it is around the start of line 10
In the code you posted, the issue does not exist: Live On Coliru
The /240 error is due to illegal spaces before every code of line.
eg.
Do
printf("Anything");
instead of
printf("Anything");
This error is common when you copied and pasted the code in the IDE.
Your program has invalid/invisible characters in it.
You most likely would have picked up these invisible characters when you copy and paste code from another website or sometimes a document. Copying the code from the site into another text document and then copying and pasting into your code editor may work, but depending on how long your code is you should just go with typing it out word for word.
I got the same error when I just copied the complete line but when I rewrite the code again i.e. instead of copy-paste, writing it completely then the error was no longer present.
Conclusion: There might be some unacceptable words to the language got copied giving rise to this error.
Solution: Delete that line of code (if you copied it from another source document) and type it yourself.
Error: stray '\240' in program is simply a character encoding error message.
From my experience, it is just a matter of character encoding. For example, if you copy a piece of code from a web page or you first write it in a text editor before copying and pasting in an IDE, it can come with the character encoding of the source document or editor.
I faced the same problem due to illegal spaces in my entire code.
I fixed it by selecting one of these spaces and use find and replace to replace all matches with regular spaces.
i did the following to solve the issue:
Paste the corrupted code into a txt file.
Open the code file with some hexadecimal editor.
Replace every occurrence of "C2A0" hexadecimal chain that you find in the document with an empty string.
Save it.
Now you should be able to copy the text code without any issue.
I've Googled, asked my classmates, and finally asked my professor about this particular problem, but I haven't achieved a solution yet. I'm hoping someone here can help me out.
Basically, I need to make an array of structs that will contain 4 pieces of information per struct: country name, country population, country area, and country density. This information will be written to the structs in the array from a .txt document. This info will then be written onto the console from said array.
Unfortunately, in attempting to write anything to the structs in the array, I get 2 errors. "Cannot convert from 'const char[8]' to 'char [30]'" and "no operator '[]' matches these operands, operand types are: CountryStats [int]". These errors both refer to the line:
countries[0].countryName = "A";
Keep in mind that I have only started to use structs and this is the first time I've used them in an array. Also, I must use an array, as opposed to a vector.
Here's my code:
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
struct CountryStats;
void initArray(CountryStats *countries);
const int MAXRECORDS = 100;
const int MAXNAMELENGTH = 30;
struct CountryStats
{
char countryName[MAXNAMELENGTH];
int population;
int area;
double density;
};
// All code beneath this line has been giving me trouble. I need to easily edit the
// struct variables and then read them.
int main(void)
{
CountryStats countries[MAXRECORDS];
initArray(*countries);
}
void initArray(CountryStats countries)
{
countries[0].countryName = "A";
}
As of now I am just attempting to figure out how to write information to a struct within the array and then read the information off of it onto the console. Everything else should fall into place after I find the solution to this.
Oh, and one final note: I have not quite learned the function of pointers (*) yet. I am still relatively new to C++ as my past programming education has been primarily in Java. Any and all inclusions of pointers in this code have been influenced by my classmates and professor in the pursuit of solving this problem.
Thanks in advance!
Two problems
void initArray(CountryStats countries)
must be:
void initArray(CountryStats *countries)
And you must use strcpy to copy c style string. (but i suggest to use c++ string instead of char[])
strcpy(countries[0].countryName,"A");
But I say again, use c++ features like vector<> and string.
You are not defining a definition for:
void initArray(CountryStats *countries);
but for:
void initArray(CountryStats countries);
in which countries is not an array. Since no operator[] is defined for CountryStats, the expression countries[0] fails to compile.
Since you cannot use std::vector (for some weird reasons), I'd suggest you to use an std::array:
template<std::size_t N>
void initArray(std::array<CountryStats, N>& ref) {
for (std::size_t i = 0; i < N; i++)
// initialize ref[i]
}
Of course, if you feel masochist, you can also use a C-style array:
void initArray(CountryStats* arr, int size) {
for (int i = 0; i < size; i++)
// initialize arr[i]
}
But you'll, probably, need to provide the dimension of the array as a second parameter.
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.