Access violation reading location with simple program - c++

Ok so I'm doing a program for class when I run across a bug I've never seen before and no idea what to do about it with only minimal experience with using the debugger, so I've come here hoping someone here can set me down the path to fixing this bug. My bug is the access violation reading location. Here is the portion of code that seems to be giving me the error:
#include "Book.h"
using namespace std;
void add (char*, char*, int);
void remove (int&);
void list ();
int Count;
Book Bookshelf [4];
int main ()
{
char* In = "";
char* N = "";
char* A = "";
int Y;
int Num;
do
{
cout << "Bookshelf> ";
cin >> In;
if (In == "add")
{
cout << "Bookshelf> Enter book: ";
cin >> N >> A >> Y;
add (N,A,Y);
}
else if (In == "remove")
{
cout << "Bookshelf> Select number: ";
cin >> Num;
remove (Num);
}
else if (In == "list")
{
}
} while (cin != "quit");
return 0;
}
void add (char* N, char* A, int Y)
{
if (Bookshelf[4].IsEmpty() == false)
cout << "Error!" << endl;
else
{
Bookshelf[Count] = Book (N,A,Y);
Count++;
}
cout << "Bookshelf> ";
}
I get the error when I type add into the command line to try to call the add function but it happens immediately so the debugger is no help to me. I know the problem is probably really simple but I can't seem to find it. Any help you can offer would be greatly appreciated. Let me know if any more code samples are needed.

You shouldn't use char* unless you really know what you are doing. For example, I rarely use char* at all and I'm programming with C++ since about 20 years. You want to use std::string, e.g. like this:
std::string In;
if (std::cin >> In) { ... }
The reason your code doesn't work is that the input operator wants to store data at the location pointed to by your pointer. However, this pointer is pointing at immutable memory for a c-string literal. When the operator tries to store something at this location it immediately gets an access violation.
The easiest fix is to use std::string. If you can't use std::string for whatever reason, use a preallocated array of char. If you do this, make sure you tell the stream how much characters are available by setting up the width:
char In[16];
if (std::cin >> std::setw(sizeof(In)) >> In) { ... }
(the reason I'm always using a check in these example is that it is very important that you always check whether your input was successful before you do anything with the result).

You cannot write data into space allocated for C-string literals: they are constants.
This is the part that leads to this behavior:
char* In = "";
cin >> In;
Two things are wrong:
Your variable In does not have enough space for any non-empty string.
Even if it did, writing to that space would not be allowed.
To fix this issue you could either (1) switch to using std::string (recommended) or (2) change declarations of your C strings to character arrays, like this:
char In[128];

Related

C++ 'no instance of overload function' why am I getting this error?

#include<iostream>
#include<cmath>
using namespace std;
int main()
{
string name, choice;
int age;
cout << "Enter a name: ";
//Getline will allow to take an entire line as an input and not a char
getline(cin, name);
cout << "Enter choice of meal: ";
getline(cin, choice);
cout << "Enter age: ";
**getline(cin, age);**
cout << "My name is " << name << endl;
return 0;
}
This is my code
The problem is in the bold line can anyone please tell me why the error is coming and the solution for it?
The answer why you code doesn't work is that getline() online allows you to read strings but not integers. Interestingly, there are no facilitien provided for reading other types in the C++ IOStreams library. This is so interesting, because line-based and delimiter-based stream processing, and in particular mixing them, is always a source for problems. Being able to use the approach you tried would be much easier and safer, I would say.
There's a simple solution (untested):
template<typename value_type>
istream&
getline(std::istream& in, value_type& val)
{
std::string line;
if (!getline(in, line)) {
return in;
}
std::istringstream iss(line);
if (!(iss >> val)) {
in.setf(std::ios::failbit);
}
return in;
}
Basically, it reads a line and then converts it to the according target type in two steps.
When you get errors like this, it's time to look up the signature of the function you use. E.g. look at this documentation std::getline. All of the overloads only accept a (template version of) std::basic_string&, there is no version accepting an int. So you need to look for another way of going from a string input an to an integer value. In this case you might want to check the documentation of the <string> header.

Taking char type name using getline in structure

As I declared a structure array: struct name data[5];
When I try to take input using cin.getline(data[i].full_name,75) (which I need) then after first time it skips the char input. I searched on this site and used fgets but was of no use.
The code is :
#include<iostream>
using namespace std;
struct name
{
char full_name[75];
int number;
};
void input(struct name data[])
{
int i=0;
while(i<5)
{
cout<<"Enter the name: ";
fgets(data[i].full_name,75,stdin);
OR
cin.getline(data[i].full_name,75)
cout<<"Enter the number: ";
cin>>data[i].number;
i++;
}
}
int main()
{
int times=0;
struct name data[5];
input(data);
}
here is my suggestion hope it helps:
void input(struct name data[])
{
int i=0;
int number;
char asciNumber[75];
while(i<5)
{
cout<<"Enter the name: ";
cin.getline(data[i].full_name,75);
cout<<"Enter the number: ";
cin.getline(asciNumber,75);
try
{
number = atoi(asciNumber);
data[i].number = number;
}
catch (...)
{
//cout << "error in number parsing" << endl;
// i think its important to check validity of std input\
}
i++;
}
}
Well, for starters, you can't use fgets() here, at all. The results of mixing the C library's stdin-based functions, and C++ library's std::cin are undefined.
But your real problem is this:
cin>>data[i].number;
Your intent here is to read a line of text containing a number.
As you know, each line of text is terminated by a newline.
The >> operator will read the entered number, but it will not actually read the newline character that follows it.
As a result of that, on the next iteration of the loop:
cin.getline(data[i].full_name,75)
All this will do, then, is immediately read the newline character after the entered number, instead of the next line of text.
You will need to replace your usage of the >> operator with another getline() that reads the next line of text into a std::string, and then use std::istringstream to convert it to a number.
That's the cleanest implementation. There are a couple of other possibilities, such as manually reading past the newline character after the number, or another, throw-away call to std::getline().

Dynamic Memory Allocation with reading file in

I am trying to use dynamic memory for this project. I am getting a seg fault but I cannot figure out what I am doing incorrectly. Can anyone point to where my mistake is? The file seems to read in correctly...but im assuming the fault is a rogue pointer..help!
I am just trying to read in "heart two 2" to "spade ace 11" in from a file, all words seperated by a space. my program worked before using dynamic memory..
#include <iostream>
#include <fstream>
#include <ctime>
#include <stdlib.h>
#include <string>
using namespace std;
//global constant(s)
const int maxCards = 52;
//Structs
struct card
{
char *suit;
char *rank;
int cvalue;
char location;
};
void readDeck(card* deckPtr);
void cardsInit(char *finNameP,card *deckPtr);
//program
int main()
{
card *deckPtr = new card[52];
char *finNameP = new char[13];
strcopy(finNameP,"cardFile.txt");
cardsInit(finNameP,deckPtr); // function i wrote that works
readDeck(deckPtr); //simply reads the deck from &deckPtr[0] -> &deck[51]
delete [] finNameP;
}
void cardsInit(char *finNameP, card *deckPtr)
{
//set up card file to be read in
ifstream fin;
cout << "Please enter file name...(cardFile.txt)" << endl;;
cin >> *finNameP;
fin.open(finNameP);
//create pointer and set initial value
card *deckHome = deckPtr;
for(int i=0;i<52;i++)
{
(*deckPtr).suit = new char[9];
(*deckPtr).rank = new char[9];
deckPtr++;
}
deckPtr = deckHome;
//check if cardFile.txt opens correctly
if(!fin.good())
{
cout << "Error with card file" << endl;
}
else
{
while(fin.good())
{
for(deckPtr = &deckPtr[0]; deckPtr < &deckPtr[maxCards];deckPtr++)
{
fin >> (*deckPtr).suit;
fin >> (*deckPtr).rank;
fin >> (*deckPtr).cvalue;
}
}
}
fin.close();
delete []finNameP;
delete [] (*deckPtr).suit;
delete [] (*deckPtr).rank;
}
This is a really ancient way to program. Instead of using new, use std::string or std::vector<char>. Those also use dynamic memory but they make it much harder for you to accidentally cause memory allocation bugs.
The first problem comes here:
cin >> *finNameP;
Since finNameP has type char *, then *finNameP has type char. So this instruction reads a single character. Then you go onto do fin.open(finNameP); which causes undefined behaviour because there is no string in finNameP.
The simplest fix is to make finNameP be a std::string. Note that doing cin >> finNameP (without changing the type) would compile, however it is a bad idea because there is no buffer overflow protection. You could write cin >> setw(12) >> finNameP; but that is still substantially worse than using a string.
deckPtr < &deckPtr[maxCards] is always true, the for loop runs forever.

Restrict user to input real number only in C++

How can I restrict the user to input real numbers only in C++ program?
Example:
double number;
cin >> number;
and it won't accept the input like: '12add' , 'abcd' etc...
can someone guides me to that? using bool value.
Thanks!
You cannot force the user to give correct input. But you can ask them to give another input if previous was invalid. There are different procedures to do so. One is the following:
Use getline to read a line
Parse and understand the line
If line is invalid, give error to user and go to 1
This is alright and quite common. It uses dynamic memory though. Another option would be:
Use cin >> value; like you normally do
Check cin.fail() to see if input was correctly read (check for cin.eof() also)
If failed, ignore all input until whitespace:
char c;
while (cin >> c)
if (isspace(c))
break;
This has the added advantage that in an erroneous input like this:
abc 12.14
you don't ignore the whole line, but just the abc.
I always use this code to request a specific type of input(Except strings and chars).
The idea is to request any numeric type and use stringstream to see if it can be stored as the requested type, if not it will keep prompting the user until he inputs the requested type.
template <typename T> // will not work with strings or chars
T forceInputType_T() {
T name;
bool check = false;
string temp;
while (check == false) {
cin >> temp;
stringstream stream(temp);
if (stream >> number) {
check = true;
} else {
cout << "Invalid input type, try again..." << endl;
}
}
return name;
}
If you want to use a Boolean then you could check every character in the string if it contains a number than return false and keep asking for an valid input with a loop !
You cannot restrict what user types on the keyboard. You can accept it as std::string and use boost::lexical_cast to convert it to your expected number type and catch and process boost::bad_lexical_cast exception.
You can retrieve your data as a std::string then use one of the standard string conversion function to see if the content matches your expectations.
double number
if (cin >> number) {
do_stuff_with(number);
} else {
std::cerr << "That wasn't a number!";
}
Check out the sscanf function.
Unfortunately you cannot avoid it... You can accept a string as input and parse the string (maybe with regex) for correctness.
You can use regex to solve it
double inputNumber()
{
string str;
regex regex_double("-?[0-9]+.?[0-9]+");
do
{
cout << "Input a positive number: ";
cin >> str;
}while(!regex_match(str,regex_double));
return stod(str);
}
Remember that include regex library in the header.
Use this:
#include <conio.h>
#include <string>
#include <iostream>
using namespace std;
int main() {
cout << "Input a positive whole integer: ";
string currentInput;
while (true) {
char ch = getch();
if (ch <= '9' and ch >= '0') cout << ch; currentInput += ch;
// Handle other keys (like backspace, etc)
else if (ch == '\r') cout << endl; break;
}
}

How to validate numeric input in C++

I'd like to know how to limit an input value to signed decimals using std::cin.
double i;
//Reading the value
cin >> i;
//Numeric input validation
if(!cin.eof())
{
peeked = cin.peek();
if(peeked == 10 && cin.good())
{
//Good!
count << "i is a decimal";
}
else
{
count << "i is not a decimal";
cin.clear();
cin >> discard;
}
}
This also gives an error message with the input -1a2.0 avoiding the assignation of just -1 to i.
If the backing variable of the cin is a number, and the string provided is not a number, the return value is false, so you need a loop:
int someVal;
while(!(cin >> someVal)) {
cin.reset();
cout << "Invalid value, try again.";
}
Combining the techniques from the top answer here and this website, I get
input.h
#include <ios> // Provides ios_base::failure
#include <iostream> // Provides cin
template <typename T>
T getValidatedInput()
{
// Get input of type T
T result;
cin >> result;
// Check if the failbit has been set, meaning the beginning of the input
// was not type T. Also make sure the result is the only thing in the input
// stream, otherwise things like 2b would be a valid int.
if (cin.fail() || cin.get() != '\n')
{
// Set the error state flag back to goodbit. If you need to get the input
// again (e.g. this is in a while loop), this is essential. Otherwise, the
// failbit will stay set.
cin.clear();
// Clear the input stream using and empty while loop.
while (cin.get() != '\n')
;
// Throw an exception. Allows the caller to handle it any way you see fit
// (exit, ask for input again, etc.)
throw ios_base::failure("Invalid input.");
}
return result;
}
Usage
inputtest.cpp
#include <cstdlib> // Provides EXIT_SUCCESS
#include <iostream> // Provides cout, cerr, endl
#include "input.h" // Provides getValidatedInput<T>()
int main()
{
using namespace std;
int input;
while (true)
{
cout << "Enter an integer: ";
try
{
input = getValidatedInput<int>();
}
catch (exception e)
{
cerr << e.what() << endl;
continue;
}
break;
}
cout << "You entered: " << input << endl;
return EXIT_SUCCESS;
}
Sample run
Enter an integer: a
Invalid input.
Enter an integer: 2b
Invalid input.
Enter an integer: 3
You entered: 3.
cin's >> operator works by reading one character at a time until it hits whitespace. That will slurp the whole string -1a2.0, which is obviously not a number so the operation fails. It looks like you actually have three fields there, -1, a, and 2.0. If you separate the data by whitespace, cin will be able to read each one without problem. Just remember to read a char for the second field.
I tried many techniques for reading integer input from the user using the >> operator, but in a way or another all my experiments have failed.
Now I think that getline() function (not the method with the same name on std::istream) and the strtol() function from the include cstdlib is the only predictable consistent solution for this problem. I would appreciate if someone proved me wrong. Here is something like the one I use:
#include <iostream>
#include <cstdlib>
// #arg prompt The question to ask. Will be used again on failure.
int GetInt(const char* prompt = "? ")
{
using namespace std; // *1
while(true)
{
cout << prompt;
string s;
getline(cin,s);
char *endp = 0;
int ret = strtol(s.c_str(),&endp,10);
if(endp!=s.c_str() && !*endp)
return ret;
}
}
*1: Placing using namespace whatever; to the global scope may lead to broken "unity builds" (google!) on larger projects, so should be avoided. Practice to not use that way, even on smaller projects!
Reading integers from files is a very different matter. Raúl Roa's approach can be good for that if properly worked out. I also suggest that wrong input files should not be tolerated, but it really depends on the application.
Be warned that using >> and getline() in the same program on cin will lead to some problems. Use one of them only, or google to know how to handle the issue (not too hard).
Something like:
double a;
cin >> a;
Should read your signed "decimal" fine.
You'll need a loop and some code to make sure it handles invalid input in a sensible way.
Good luck!