I am using the latest version of Code::Blocks. I have a function that passes in a string and a vector. The function compiles with no errors. However, when I run the debugger, it immediately leads me to line 118 (which I have noted) and gives me trouble. The error that comes up says "Cannot find bounds of current function".
Here is the function, which takes in a line of code of a variable declaration (like "var c=0"), and gets the variable of it and adds its value to the vector, v, a struct with an int value and string name:
char get_variable_declaration(string line, vector<variable> &v)
{
string b;
variable t;
char d[0];
int counter = 0;
int a;
for (int i = 0; i<line.size(); i++) {
if (line[i] == 'r' && counter != 1) {
b[0] = line [i+2];
counter ++;
}
if (line[i] == '=') {
b[1]=line[i+1];
}
}
t.name = b[0];
d[0] = b[1];
a = atoi (d);
t.value = a;
v.push_back (t);
return b[0];
//This function will take in a line of code
//that is confirmed to have a variable declaration
//it will add the variable to the list of
//vectors
}
Here is when it is called:
bool read_code(string file_name, vector<funct> &my_functions, vector<variable> & v)
{
vector<string> code;
string s;
std::size_t found;
bool flag;
funct new_function;
ifstream in;
in.open(file_name.c_str());
if(in.is_open())
{
//read in file line by line and put it into a vector called code
while(in.peek()!=EOF)
{
getline(in,s);
code.push_back(s);
}
in.clear();
in.close();
//read through each line of the code, determine if it's a variable or function (definition or call)
//here it makes reference to functions (listed following this one) which will actually decompose the line
//for information
for(int i=0;i<code.size();i++)
{
//check if it's a variable declaration
found = code[i].find("var");
if(found!=std::string::npos) //its a variable declaration
get_variable_declaration(code[i], v); //ERROR CANNOT FIND..
//check if it's a function. it'll go in the list of functions
found = code[i].find("funct");
if (found!=std::string::npos) //that means it's a function
{
new_function.funct_name=get_function_name(code[i]);
new_function.commands.clear();
i+=2; //skip over the open curly brace
flag=false;
while(!flag)
{
found = code[i].find("}");
if(found==std::string::npos)
{
new_function.commands.push_back(code[i]);
i++;
}
else
{
my_functions.push_back(new_function);
flag=true;
}
}
}
}
return true;
}
else
{
cout << "Cannot locate this file" << endl;
return false;
}
}
Disclaimer: Yes, this is a homework assignment. No, I am not looking for anyone to finish this assignment for me. But, I am still mostly a novice at coding, in need of some assistance, so I ask if you know what is going on, please help me address this issue. Thanks!
Edit: I have gotten this to work on another compiler w/o the text file I am reading from. Not sure if this is a universal issue, or one that the other compiler just didn't pick up on.
Multiple problems with this section of code:
string b;
for (int i = 0; i<line.size(); i++) {
if (line[i] == 'r' && counter != 1) {
b[0] = line [i+2];
counter ++;
}
if (line[i] == '=') {
b[1]=line[i+1];
}
}
Problems:
If the last character in line is 'r', undefined behavior can occur.
If the next to last character in line is 'r', undefined behavior can occur.
If the last character in line is '=', undefined behavior occurs.
Both assignments to b[0] and b[1] is undefined behavior. The b string is empty.
There are also other instances of undefined behavior that have been noted in the comments, which I won't duplicate.
I found the problem. To correctly use atoi, you cannot use a specific character from a string or character array. If you declare a char a[3], and you want to use atoi, you must use it like int value = atoi(a) and not value = atoi(a[2]). If you do not do it this way, it will cause a runtime error.
Related
I have a homework assignment in which I have to return the number of words in a string based on the number of blank spaces. Here is my code, I am not sure what is wrong with it but I keep getting error messages when I try to compile it.
string getWordCount(string sentence){
int count = 1;
for(int i = 1; i < sentence.length(); i++){
if (s[i]==' '){
count++;
}
}
return count;
}
The error messages are:
error: ‘s’ was not declared in this scope
if (s[i]==' '){
^
error: could not convert ‘count’ from ‘int’ to ‘std::__cxx11::string {aka std::__cxx11::basic_string<char>}’
return count;
^~~~~
To compile your code, you must ensure that return type (count is an int) is compatible with the declared return type of the function (you said it would return string). So instead of:
string getWordCount(string sentence)
declare your function as :
int getWordCount(string sentence)
Note also that you use s[i], but s is not declared. You probably mean sentence[i].
Consider also solving the different algorithmic errors mentionned in the comments (i.e. wrong result for an empty string, for a string with only blank, and depending on the exercise narative, for a string where several consecutive spaces are used between two words) to finish your homework and improve your skills.
You are passing in a variable named sentence but parsing on a variable named s. Also, count is an int but your return type is string. Try this:
int getWordCount (string sentence)
{
int count = 1;
for (int i = 0; i < sentence.length (); i++)
{
if (sentence[i] == ' ')
count++;
}
return count;
}
What they said.
Plus ...Avoid indexing with square brackets. Use range-based for loops. Be careful about trivial input (no words, or even an empty string, in this case). Do not assume that white space is only spaces, or that it only comprises one character. Input parameters that a function does not modify can be declared const-reference, to avoid making an un-needed copy. Use #include <algorithm> for common tasks.
SPOILER ALERT. Read no more until you after you have finished the assignment.
#include <cctype>
#include <string>
int get_word_count(const std::string &sentence)
{
int count = 0;
bool scanning_a_word = false;
for (auto ch : sentence) {
if (!std::isspace(ch)) {
if (!scanning_a_word) {
count += 1;
scanning_a_word = true;
}
} else {
scanning_a_word = false;
}
}
return count;
}
Bonus (and better) solution. The following does not use a state-variable (scanning_a_word). I call that kind of code "bread crumb programming". You leave bread crumbs along the trail to show where you've been. Sometimes birds eat the bread crumbs. Look Ma, no crumbs!
#include <algorithm>
int get_word_count(const std::string &sentence)
{
int count = 0;
auto next = sentence.begin();
const auto done = sentence.end();
while(done != next) {
next = std::find_if_not(next, done, std::isspace);
if (done != next) {
count += 1;
next = std::find_if(next, done, std::isspace);
}
};
return count;
}
Generally, when a variable is not declared within a scope you defined it inside something locally and it does not exist after that block of code (i.e. for loop) has finished executing. Or, you have not declared the variable at all.
error: ‘s’ was not declared in this scope
if (s[i]==' '){
^
Assuming you were trying to iterate through the parameter you passed in, which is a string called sentence, I either change the variable name to s of the parameter, copy the string into another string called s, or change s to sentence in the loop. The different variations are shown below:
// change parameter name to s
string getWordCount(string s)
{
int count = 1;
for(int i = 1; i < sentence.length(); i++)
{
if (s[i]==' ')
count++;
}
return count;
}
// change s to sentence inside the loop
string getWordCount(string sentence)
{
int count = 1;
for(int i = 1; i < sentence.length(); i++)
{
if (sentence[i]==' ')
count++;
}
return count;
}
// create a string s, and copy sentence into string s
string getWordCount(string sentence)
{
int count = 1;
string s = strcpy(s, sentence);
for(int i = 1; i < sentence.length(); i++)
{
if (s[i]==' ')
count++;
}
return count;
}
For your second error, generally this error occurs when there is an issue with casting a variable type to another type. In your case, the below error occurs because you are declaring a function will return a string, however, you are trying to return an int.
error: could not convert ‘count’ from ‘int’ to ‘std::__cxx11::string {aka std::__cxx11::basic_string<char>}’
return count;
^~~~~
To fix this error, simply change the return type to int. However, if you really want to return the count as a string for some reason, convert the integer to a string before returning. Both variations are shown below.
// Change return type to int to match count's type
int getWordCount(string sentence)
{
int count = 1;
...
...
return count;
}
// If you really need to send count back as a string for some reason, convert the int to string
string getWordCount(string sentence)
{
int count = 1;
...
...
return itoa (count);
}
Please note: this is only describing why your compilation errors are occurring and how to fix them so that you can continue on with your homework assignment. This is not describing what is wrong, logically, with your code.
I keep getting the following error:
Unhandled exception at 0x74BDD8A8 in FileName.exe: Microsoft C++ exception: std::out_of_range at memory location 0x004FA55C.
I've done some searching but I was not able to solve this problem. I did narrow it down to the fact that the out of range error is coming from my string fdata variable. Here is my code where error/exception occurs:
void MyClass::MyMethod10()
{
string fdata;
char num[100];
int i = 0,k=0;
unsigned int m,j=0;
inputFile.open("sec1.txt", ios::in);
inputFile >> fdata;
while (j<fdata.length())
{
while (fdata.at(j) != '+')
{
if (fdata.at(j) != '*' && j<fdata.length())
{
num[k] = fdata.at(j);
k++;
}
else
{
num[k] = '\0';
m = atoi(num);
//cout << m << endl;
MyMethod22(m);
k = 0;
}
j++;
}
MyMethod22(43);
j++;
}
inputFile.close();
outputFile.open("sec2.txt", ios::out);
while (i<index)
{
outputFile << (char)data[i];
i++;
}
outputFile.close();
CleanBuffer();
}
The sec1.txt file contains the following data
25750*23084*57475*15982*+57475*15982*+13364*15982*26260*+48840*32397*13364*15982*57475*11371*21876*+25197*
In the while() loop section my program is able to read the data correctly from the file. The problem/error/exception occurs at the point where my program takes in the last number from the file. I am guessing the problem is in the while() loop, but I am not able to figure out what's wrong. All I was able to do was to narrow down the error to string fdata being out of range after it reads the last number from the file. I was wondering if anyone can help me to solve this or suggest something which I might have missed?
The actual problem you have is here:
while (fdata.at(j) != '+')
{
...
j++;
}
Note that you increment j, and try to read j-th character before you check if j is in range. To fix it, change it like this:
while (j < fdata.size() && fdata.at(j) != '+')
{
...
j++;
}
I saw that a part of my code did not work as expected. It does not go into the if statement and give an error while it should. I tried to examine the code and found something very odd. When I add cout << i in the for loop to check, it starts to work well. Can anyone explain what is the problem with it? Note: airports is a vector of Airport objects. Airport::getName() returns its name as string.
string name = "smth";
//this is the loop with unexpected behaviour
for (int i = 0; i < airports.size(); i++)
{
//when the following line is taken outside the comment, it works well:
//cout << i;
if (isEqualNoCaseSense(name, airports[i].getName()))
{
cout << "Could not create airport " << name << ". It already exists." << endl;
return;
}
}
The function I used to compare strings without case sensitivity:
bool isEqualNoCaseSense(string str1, string str2)
{
if (str1.size() != str2.size())
return false;
char *lowerStr1 = new char[str1.size()];
char *lowerStr2 = new char[str2.size()];
for (int i = 0; i < str1.size(); i++)
{
lowerStr1[i] = tolower(str1[i]);
lowerStr2[i] = tolower(str2[i]);
}
if (strcmp(lowerStr1, lowerStr2) == 0)
{
delete[] lowerStr1;
delete[] lowerStr2;
return true;
}
else
{
delete[] lowerStr1;
delete[] lowerStr2;
return false;
}
}
EDIT: Correcting the compare function fixes it, but I still wonder why cout << i fixed it
The problem is that you haven't terminated your strings, but if you just write a sensible function it will work correctly:
bool isEqualNoCaseSense(const string& str1, const string& str2)
{
if (str1.size() != str2.size())
return false;
for (int i = 0; i < str1.size(); ++i)
if (tolower((unsigned char)str1[i]) != tolower((unsigned char)str2[i]))
return false;
return true;
}
No unnecessary allocation, and only loops through the strings up to the first mismatch.
EDIT: Correcting the compare function fixes it, but I still wonder why cout << i fixed it
Because the program had undefined behaviour, so anything can happen. Adding random, unrelated code might change the memory allocation patterns of the code, or cause the compiler to optimise it slightly differently. You'll go mad trying to reason about some kinds of undefined behaviour. Just avoid it.
strcmp expects NULL terminated strings. So you needed to reserve one more character for the lowerStr1, lowerStr2 arrays and set the last character of each array to NULL. Failing to do so, created undefined bahaviour to your program.
But you could bypass all these issues if you use strncmp function passing str1.size() as the third argument, since you already check if the two strings have equal size:
if (strncmp(lowerStr1, lowerStr2, str1.size()) == 0)
I'm really not sure as to why I am receiving this error. I've tried to google it but I haven't had the best of results... If somebody could just tell me as to why I'm getting this error:
No viable conversion from 'vector<Country>' to 'int'
int main()
{
vector<Country> readCountryInfo(const string& filename);
// Creating empty vector
vector<Country> myVector;
// Opening file
ifstream in;
in.open("worldpop.txt");
if (in.fail()) {
throw invalid_argument("invalid file name");
}
while (in) {
char buffer; // Character buffer
int num; // Integer to hold population
string countryName; // Add character buffer to create name
while (in.get(buffer)) {
// Check if buffer is a digit
if (isdigit(buffer)) {
in.unget();
in >> num;
}
// Check if buffer is an alphabetical character
else if (isalpha(buffer) || (buffer == ' ' && isalpha(in.peek()))) {
countryName += buffer;
}
// Checking for punctuation to print
else if (ispunct(buffer)) {
countryName += buffer;
}
// Check for new line or end of file
else if (buffer == '\n' || in.eof()) {
// Break so it doesn't grab next char from inFile when running loop
break;
}
}
Country newCountry = {countryName, num};
myVector.push_back(newCountry);
}
return myVector;
}
It says here
int main()
that main returns an int — as it should, because The Standard requires it to.
Then, at the end, you say
return myVector;
and myVector is a vector<Country>, which can't be converted to an int.
Hence the error message.
I suspect, based on the declaration
vector<Country> readCountryInfo(const string& filename);
of a function that does return a vector<Country>, that you intended to write your code in a function called "readCountryInfo", but somehow happened to write it in the wrong place.
Your int main() should return an int, not myVector (last line of your code).
In c++, main returns an int, normally zero.
I'm writing a program for an exercise that will read data from a file and format it to be readable. So far, I have a bit of code that will separate a header from the data that goes under it. Here it is:
int main() {
ifstream in("records.txt");
ofstream out("formatted_records.txt");
vector<string> temp;
vector<string> headers;
for (int i = 0; getline(in,temp[i]); ++i) {
static int k = -1;
if (str_isalpha(temp[i])) {
headers[++k] = temp[i];
temp.erase(temp.begin() + i);
}
else {
temp[i] += "," + headers[k];
}
}
}
(str_isalpha() is just a function that applies isalpha() to every character in a string.) Now, the for-loop in this program doesn't execute, and I can't figure out why. Does anybody know?
EDIT: As suggested, I changed it to
string line;
for (int i = 0; getline(in,line); ++i) {
temp.push_back(line);
Still skips the for-loop altogether.
vector<string> temp; makes an empty vector. When you then try to read into temp[0], that is undefined behavior. You should pass as getline's second argument a separate string variable, say string foo; before the loop, then temp.push_back(foo); as the first instruction in the loop's body.
If the loop still doesn't run after ensuring that you're reading into a valid string reference, then you should check that the stream you're reading from is valid. The stream will be invalid if the file doesn't exist or if you lack permission to read it, for instance. When the stream isn't valid, getline won't read anything. Its return value is the same stream, and when converted to bool, it evaluates as false. Check the stream's status before proceeding.
ifstream in("records.txt");
if (!in.is_open()) {
std::cerr << "Uh-oh.\n";
return EXIT_FAILURE;
}