I'm trying to write a simple test program in VS 2013. It's telling me that scanf() is unsafe, and that I should use scanf_s() instead. Even worse, it's telling me that int x is uninitialized (and not just as a warning, as an error), even though it doesn't need to be initialized there. I'm wondering if it's possible to change settings so that VS2013 does not give me these error messages, or figure out what I am doing wrong.
#include <stdio.h>
int main(){
printf("How many pizzas did you make: ");
int x;
scanf("%d", x);
}
use cout instead of printf() and cin instead of scanf
example:
const int SIZE = 5;
char word[SIZE];
cout << "Enter a word: ";
cin >> setw(SIZE) >> word;
cout << "You entered " << word << endl;
don't forget to import the std library
using std;
you may be making mistake in the this line
scanf("%d", &x);
scanf is warned as unsafe because it may cause buffer overflow. And scanf needs address of x, so it should be &x.
There is one outright error and a probable bug in your example code:
scanf("%d", x);
The above needs a pointer, and you must always verify that all output parameters were matched.
To the second, Microsoft is behind the drive to force you to abandon the standard C library functions, going so far as to declaring their use an unsupportable risk, not that the safer functions in an optional part of the C standard cannot be used in an unsafe manner too.
Look in the compiler documentation, there is a flag to suppress this irritating behavior.
Anyway, you are writing in C++, so just about everyone here will say you should use iostreams and idiomatic C++, regardless of how you ask or why.
Related
I came across a code example learncpp.com where they zero-initialized a variable, then defined it with std::cin:
#include <iostream> // for std::cout and std::cin
int main()
{
std::cout << "Enter a number: "; // ask user for a number
int x{ }; // define variable x to hold user input (and zero-initialize it)
std::cin >> x; // get number from keyboard and store it in variable x
std::cout << "You entered " << x << '\n';
return 0;
}
Is there any reason that on line 7 you wouldn't just not initialize x? It seems zero-initializing the variable is a waste of time because it's assigned a new value on the next line.
Is there any reason that on line 7 you wouldn't just not initialize x?
In general, it is advised that local/block scope built in types should always be initialized. This is to prevent potential uses of uninitialized built in types which have indeterminate value and will lead to undefined behavior.
In your particular example though since in the immediate next line we have std::cin >> x; so it is safe to omit the zero initialization in the previous line.
Note also that in your example if reading input failed for some reason then prior to C++11, x still has indeterminate value but from C++11(&onwards) x will no longer has indeterminate value according to the below quoted statement.
From basic_istream's documentation:
If extraction fails (e.g. if a letter was entered where a digit is expected), zero is written to value and failbit is set. For signed integers, if extraction results in the value too large or too small to fit in value, std::numeric_limits<T>::max() or std::numeric_limits<T>::min() (respectively) is written and failbit flag is set. For unsigned integers, if extraction results in the value too large or too small to fit in value, std::numeric_limits<T>::max() is written and failbit flag is set.
It seems zero-initializing the variable is a waste of time because it's redefined on the next line.
As i said, in your example and assuming you're using C++11(& higher), you can safely leave off the zero-initialization.
then defined it with std::cin
No the use of std::cin does not "define" it(x). Definition happened only once when you wrote:
int x{ }; //this is a definition
Even if you leave the zero initialization, then also it will be a definition:
int x; //this is also a definition but x is uninitialized here
The problem you're encountering is, that in order to use the >> operator of std::cin, you have to have your variable declared beforehand, which is, well, undesirable. It also leads to your question of whether or not to initialize the variable.
Instead, you could do something like this:
#include <iostream>
#include <iterator>
int main()
{
std::cout << "Enter a number: ";
auto const i = *std::istream_iterator<int>(std::cin);
std::cout << "You entered " << x << '\n';
}
... although that's also problematic, since you're at the end-of-file, then the behavior is undefined.
Now, you might be asking "why is this guys talking to me about alternatives to the common way of doing things, then telling me that the alternative isn't good enough either?"
The point of my doing this is to introduce you to an uncomfortable fact of "C++ life", which is: We are often stuck with design decisions of the standard library which are not optimal. Sometimes, there's really no better alternative; and sometimes there is, but it wasn't adopted - and since C++ does not easily change designs of standard library classes, we may be stuck with some "warts" in the language. See also the discussion in the related question I've opened:
Why do C++ istreams only allow formatted-reading into an existing variable?
I was trying to solve this exercise from www.spoj.com : FCTRL - Factorial
You don't really have to read it, just do it if you are curious :)
First I implemented it in C++ (here is my solution):
#include <iostream>
using namespace std;
int main() {
unsigned int num_of_inputs;
unsigned int fact_num;
unsigned int num_of_trailing_zeros;
std::ios_base::sync_with_stdio(false); // turn off synchronization with the C library’s stdio buffers (from https://stackoverflow.com/a/22225421/5218277)
cin >> num_of_inputs;
while (num_of_inputs--)
{
cin >> fact_num;
num_of_trailing_zeros = 0;
for (unsigned int fives = 5; fives <= fact_num; fives *= 5)
num_of_trailing_zeros += fact_num/fives;
cout << num_of_trailing_zeros << "\n";
}
return 0;
}
I uploaded it as the solution for g++ 5.1
The result was: Time 0.18 Mem 3.3M
But then I saw some comments which claimed that their time execution was less than 0.1. Since I couldn't think about faster algorithm I tried to implement the same code in C:
#include <stdio.h>
int main() {
unsigned int num_of_inputs;
unsigned int fact_num;
unsigned int num_of_trailing_zeros;
scanf("%d", &num_of_inputs);
while (num_of_inputs--)
{
scanf("%d", &fact_num);
num_of_trailing_zeros = 0;
for (unsigned int fives = 5; fives <= fact_num; fives *= 5)
num_of_trailing_zeros += fact_num/fives;
printf("%d", num_of_trailing_zeros);
printf("%s","\n");
}
return 0;
}
I uploaded it as the solution for gcc 5.1
This time the result was: Time 0.02 Mem 2.1M
Now the code is almost the same, I added std::ios_base::sync_with_stdio(false); to the C++ code as was suggested here to turn off the synchronization with the C library’s stdio buffers. I also split the printf("%d\n", num_of_trailing_zeros); to printf("%d", num_of_trailing_zeros); printf("%s","\n"); to compensate for double call of operator<< in cout << num_of_trailing_zeros << "\n";.
But I still saw x9 better performance and lower memory usage in C vs. C++ code.
Why is that?
EDIT
I fixed unsigned long to unsigned int in the C code. It should have been unsigned int and the results which are shown above are related to the new (unsigned int) version.
Both programs do exactly the same thing. They use the same exact algorithm, and given its low complexity, their performance is mostly bound to efficiency of the input and output handling.
scanning the input with scanf("%d", &fact_num); on one side and cin >> fact_num; on the other does not seem very costly either way. In fact it should be less costly in C++ since the type of conversion is known at compile time and the correct parser can be invoked directly by the C++ compiler. The same holds for the output. You even make a point of writing a separate call for printf("%s","\n");, but the C compiler is good enough to compile this as a call to putchar('\n');.
So looking at the complexity of both the I/O and computation, the C++ version should be faster than the C version.
Completely disabling the buffering of stdout slows the C implementation to something even slower than the C++ version. Another test by AlexLop with an fflush(stdout); after the last printf yields similar performance as the C++ version. It is not as slow as completely disabling buffering because output is written to the system in small chunks instead of one byte at a time.
This seems to point to a specific behavior in your C++ library: I suspect your system's implementation of cin and cout flushes the output to cout when input is requested from cin. Some C libraries do this as well, but usually only when reading/writing to and from the terminal. The benchmarking done by the www.spoj.com site probably redirects input and output to and from files.
AlexLop did another test: reading all the inputs at once in a vector and subsequently computing and writing all output helps understanding why the C++ version is so much slower. It increases performance to that of the C version, this proves my point and removes suspicion on the C++ formatting code.
Another test by Blastfurnace, storing all outputs in an std::ostringstream and flushing that in one blast at the end, does improve the C++ performance to that of the basic C version. QED.
Interlacing input from cin and output to cout seems to cause very inefficient I/O handling, defeating the stream buffering scheme. reducing performance by a factor of 10.
PS: your algorithm is incorrect for fact_num >= UINT_MAX / 5 because fives *= 5 will overflow and wrap around before it becomes > fact_num. You can correct this by making fives an unsigned long or an unsigned long long if one of these types is larger than unsigned int. Also use %u as the scanf format. You are lucky the guys at www.spoj.com are not too strict in their benchmarks.
EDIT: As later explained by vitaux, this behavior is indeed mandated by the C++ standard. cin is tied to cout by default. An input operation from cin for which the input buffer needs refilling will cause cout to flush pending output. In the OP's implementation, cin seems to flush cout systematically, which is a bit overkill and visibly inefficient.
Ilya Popov provided a simple solution for this: cin can be untied from cout by casting another magical spell in addition to std::ios_base::sync_with_stdio(false);:
cin.tie(nullptr);
Also note that such forced flush also occurs when using std::endl instead of '\n' to produce an end of line on cout. Changing the output line to the more C++ idiomatic and innocent looking cout << num_of_trailing_zeros << endl; would degrade performance the same way.
Another trick to make iostreams faster when you use both cin and cout is to call
cin.tie(nullptr);
By default, when you input anything from cin, it flushes cout. It can significantly harm performance if you do interleaved input and output. This is done for the command line interface uses, where you show some prompt and then wait for data:
std::string name;
cout << "Enter your name:";
cin >> name;
In this case you want to make sure the prompt is actually shown before you start waiting for input. With the line above you break that tie, cin and cout become independent.
Since C++11, one more way to achieve better performance with iostreams is to use std::getline together with std::stoi, like this:
std::string line;
for (int i = 0; i < n && std::getline(std::cin, line); ++i)
{
int x = std::stoi(line);
}
This way can come close to C-style in performance, or even surpass scanf. Using getchar and especially getchar_unlocked together with handwritten parsing still provides better performance.
PS. I have written a post comparing several ways to input numbers in C++, useful for online judges, but it is only in Russian, sorry. The code samples and the final table, however, should be understandable.
The problem is that, quoting cppreference:
any input from std::cin, output to std::cerr, or program termination forces a call to std::cout.flush()
This is easy to test: if you replace
cin >> fact_num;
with
scanf("%d", &fact_num);
and same for cin >> num_of_inputs but keep cout you'll get pretty much the same performance in your C++ version (or, rather IOStream version) as in C one:
The same happens if you keep cin but replace
cout << num_of_trailing_zeros << "\n";
with
printf("%d", num_of_trailing_zeros);
printf("%s","\n");
A simple solution is to untie cout and cin as mentioned by Ilya Popov:
cin.tie(nullptr);
Standard library implementations are allowed to omit the call to flush in certain cases, but not always. Here's a quote from C++14 27.7.2.1.3 (thanks to chqrlie):
Class basic_istream::sentry : First, if is.tie() is not a null pointer, the function calls is.tie()->flush() to synchronize the output sequence with any associated external C stream. Except that this call can be suppressed if the put area of is.tie() is empty. Further an implementation is allowed to defer the call to flush until a call of is.rdbuf()->underflow() occurs. If no such call occurs before the sentry object is destroyed, the call to flush may be eliminated entirely.
My program is this:
#include<iostream>
#include<fstream>
using namespace std;
int main()
{
char choice;
int o,i,marks[i],ttlcredit=0;
double ttlGPA=0,finalGPA=0,credit[7][2],clsavg;
cout<<"Please enter what you want to calculate"<<endl;
cout<<"A for calculating Class Average GPA"<<endl;
cout<<"B for calculating a Specific GPA"<<endl;
cout<<"Your choice is? ";
cin>>choice;
cout<<endl;
if (choice == 'A'||choice == 'a')
{
cout<<"=========================================="<<endl;
cout<<" Class Average GPA"<<endl;
cout<<"=========================================="<<endl<<endl;
cout<<"Please enter the number of students in the class: ";
cin>>number;
for(i=0;i<number;i++)
{
cout<<"\nEnter student #"<<i+1<<"'s marks: ";
cin>>marks[i];
ttlGPA=ttlGPA+marks[i];
}
clsavg=ttlGPA/number;
cout<<"\nThe Average is: "<<clsavg<<endl;
}
else
{
}
}
It is half completed. When I build and run on CodeBlocks, an error instantly appeared:
I tried finding the source of error and I think that it is caused by the following in the code:
int o,i,marks[i],ttlcredit=0;
What makes me think so is because when I remove the [i] from marks[i], I will be not receive that error.
I think is stack overflow because I use Microsoft Visual Studio to help me debug and this is the error they gave me:
Unhandled exception at 0x0041419e in Project (1).exe: 0xC00000FD: Stack overflow.
My question is...
Is that the main cause of problem?
How do I resolve this issue?
You have to initialize the marks array with a positive length.
Get the number of students first, THEN create the array using that number.
Also, you need to declare the variable number.
As the other answers stated correctly, the problem is that int i is used uninitialized. However, the proposed fix
// initialze i
int marks[i];
is not standard C++, but only available through a compiler extension. In C++, the length of a built-in array must be a compile time constant. The better solution would be using std::vector:
// initialize i (better make it std::size_t instead of int)
std::vector<int> marks (i);
This will create a variable length array in a safe and standard conforming way.
First thing to say is that you simply shouldn't use arrays. They just are too weird in C and C++, and we have superior alternatives in modern C++.
Anyway, whether you use arrays or vectors, there are some important issues. Before discussing marks[i], it's simpler to look at credit[7][2] in this code.
int o,i,marks[i],ttlcredit=0;
double ttlGPA=0,finalGPA=0,credit[7][2],clsavg;
The dimensions are explicit in this declaration of credit. It's seven-times-two. Simple enough. You can read and write to credit[0][0] and credit[6][1] and many other values. But if you go outside the range, e.g. try to use credit[7][0], your program will compile and will probably appear correct for a while, but it could behave very badly and it is undefined how it will behave. It could decide to delete all the files on your computer, it is (seriously) entitled to do anything random and crazy. This is Undefined Behaviour.
Anyway, the really weird line is the declaration of marks.
int marks[i];
This definitely doesn't do what you think it does. It doesn't create an array that can be "indexed with arbitrary i". No, it allocates an array whose size is the initial value of i. But i is undefined at this stage so this is meaningless.
But i isn't relevant here anyway. How big do you want this array to be? The answer is number, isn't it? That is the number of people you'll store in your array.
So, a small improvement is to do this instead of int marks[i].
int marks[number];
But even this isn't correct. The value of number isn't set until the line cin >> number;, therefore you must declare int marks[number] after the line cin >> number; in order to ensure that marks has the correct size.
But, but, but, even after all this, we still don't have standard C++. It's OK to do int credit[7][2] because the size is fixed at compile time. You are normally not allowed to set the size of an array at runtime, e.g. int marks[number]. You might be able to use it if your compiler allows this extension (it's called Variable Length Array, from C).
So, this is not standard C++, and it's potentially very dangerous (see the Undefined Behaviour). What's the solution?
The solution is the standard solution for any problem involving arrays. Stop using arrays. (Really advanced programmers, in particular situations, might use std::array in modern C++, or even write their own clone of std:: array in older C++. But raw C [] arrays are to be avoided where possible.)
#include<vector>
int o,i,ttlcredit=0;
std::vector<int> marks;
marks is initially empty. We don't do cin >> marks[i];. Instead we use push_back to append new items to the end of the list.
int next_mark;
cin >> next_mark;
marks.push_back(next_mark);
Also, don't use marks[i] with a vector. It might look OK, but it is dangerous. Better to use marks.at(i) to read or write the element. at will do bounds checking for you, giving you a proper error message if i is too small (less then 0) or too big for the size of the vector.
int o,i,marks[i],ttlcredit=0;
i is not initialized. initialize i first.
If you are not sure of the size of the array, allocate it dynamically.
use new
refer this link on how to use new - cpluspluss
I just started teaching myself C++ on the Mac, and I have run into some issues.
I have written some code that allows the user to enter a number and when they hit enter, the number will be returned to the user.
Xcode will absolutely not have it though. Every time I try to run my code, it says that there is an issue with the cin>> thisisanumber; code.
The error comes up and says
Invalid operands to binary expression. Error is on line 10.
What am I doing wrong?
#include <iostream>
using namespace std;
int main()
{
int thisisanumber();
cout << "Please enter a number: ";
cin >> thisisanumber;
cin.ignore();
cout << "You entered"<< thisisanumber <<"\n";
cin.get();
}
You've fallen victim to the most vexing parse, which means thisisanumber is being treated as a function. Take out the parentheses and you should be fine:
int thisisanumber;
Also consider making it a bit more readable, such as thisIsANumber. If you ever need to know it, thisIsANumber uses the camel-case naming convention.
Declare your variable without brackets, like
int thisisanumber;
With brackets, it is interpreted as a function, and a function can't be passed as a parameter to the >> operator.
Your problem is the so called most vexing parse. Basically everything, which could be parsed as a function declaration will be parsed as such. Therefore the compiler will interpret int thisisanumber(); as a declaration of a function thisisanumber taking zero arguments and returning an int. If you consider this behaviour the problems with cin>>thisisanumber; should be somewhat selfevident.
If you remove the parantheses, changing the variable declaration to int thisisanumber;, your program should behave like you'd expect it to with thisisanumber being a variable of type int.
You might however reconsider your naming conventions, thisisanumber isn't exactly readable. I would suggest going with this_is_a_number, thisIsANumber or ThisIsANumber.
int thisIsANumber;
try making it variable declaration because what you wrote has been interpreted as function.
delete () after thisisanumber, because () after thisisanumber means that it's a function, when it's not.
This code is C/C++ and runs without warnings or debug messages. I'm using Code::blocks with the GNU GCC compiler. This app worked perfectly once, then somewhere along the lines I messed up without noticing. Now every time it will allow a ip address input, but then freeze up and close. Why?
#include <iostream>
#include <string>
#include <cstdio>
using namespace std;
int ip[3];
char * inputIP;
int x;
string classValue;
void subnetClass()
{
if (x==0) classValue="Error: first octet may not be zero.";
if (x>0 && x<=126) classValue="Class A";
if (x==127) classValue="Loopback Address";
if (x>=128 && x<=191) classValue="Class B";
if (x>=192 && x<=223) classValue="Class C";
if (x>=224 && x<=239) classValue="Class D";
if (x>=240 && x<=255) classValue="Class E";
if (x>255) classValue="Error: an octet may not be more than 255.";
cout << classValue << endl;
}
int main()
{
cout << "Enter IP address in dotted-decimal form." << endl;
cin >> inputIP;
scanf(inputIP, "%d.%d.%d.%d" , &ip[0],&ip[1],&ip[2],&ip[3]);
int x=ip[0];
subnetClass();
return 0;
}
Build Log:
Checking for existence: C:...\IP subnetting app\bin\Debug\IP subnetting app.exe
Executing: "C:...\CodeBlocks/cb_console_runner.exe" "C:...\IP subnetting app\bin\Debug\IP subnetting app.exe" (in C:...\IP subnetting app.)
Process terminated with status -1073741510 (0 minutes, 27 seconds)
You are declaring a variable 'x' that is hiding the global one.
int x=ip[0];
However, don't do it this way. Add an int parameter to subnetClass and pass in the value that way, and remove the global variable.
Really, removing all of your globals should be a goal and easy to accomplish. Several are only used in main().
It might have worked with a little help from sheer luck even if you messed things up later, I believe. More or less everything is wrong. First you read the line into the area pointed to by uninitialized pointer (or maybe you read the pointer value, I'm not even sure what >> (char*) is supposed to do). You better change the definition to
std::string inputIP;
then you try to parse it used scanf and pass this pointer as a format string. What you meant is using sscanf. Assuming you changed the inputIP type, you can use
sscanf(inputIP.c_str(),"%d....
Then you assign to local main variable x that shadows global, which remains uninitialized when you use it in the function. Just remove the int part in the assignment like this:
x=ip[0];
and make the ip array of four elements.
int ip[4];
Then it may work. Unless I missed something else.
And one more thing: if you use some source control (for instance using git you may start new project in no time) then you'd know what you've changed when you mess up, just commit early, commit often.
Use sscanf instead of scanf