Here is a simple C++ code:
#include <cstring>
using namespace std;
int main(int argc, _TCHAR* argv[])
{
char str[80];
cout << "輸入字串:";
gets(str);
cout << "輸入的字串:" << str << endl;
return 0;
}
When compiling it, I get the following error:
"错误1 error C4996: 'gets': This function or variable may be unsafe.
Consider using gets_s instead. To disable deprecation,
use _CRT_SECURE_NO_WARNINGS. See online help for details."
In genuine C++11 or C++14 the correct way to read an entire line is std::getline or std::basic_istream::getline.
Also, you'll better flush the output before reading an input; remember that C++ and C standard IO functions are buffering.
The old C89 gets function is deprecated since a long time (probably more than ten years), and now forbidden because it is so dangerous (can't avoid a buffer overflow). So please forget it (in C99 or C11, use fgets instead, on POSIX with C99 or C11, use getline; in C++11 or C++14 use as I said std::getline or std::basic_istream::getline).
Your main's body should be:
string str;
cout << "輸入字串:" << flush;
getline(cin,str);
cout << "輸入的字串:" << str << endl;
return 0;
The advantage of using a std::string is that your user could input an arbitrarily long line (up to implementation limits, perhaps million of characters).
If you are coding on a POSIX system like MacOSX or Linux, you could use the GNU readline library and function (see also ncurses) when reading on a terminal. The big advantage is that your user is given editing ability (and completion) when typing his line.
PS. General hint when programming: read the documentation of every function that you are using before coding.
It means that you should use gets_s() instead of gets()
The compiler usually knows what's best for the program and what shouldn't be allowed.
Related
I was seeing an old simple algorithm I had done a while ago. I did it using dev-c ++, but now I compiled it in visual studio and it doesn't work. Visual studio compiler says: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. (line 17)
In this easy project you will type a phrase, then you get the phrase translated in hex (each character).
So why dev-c++ doesn't tell me that? Did I make any mistakes? Or not... The code is ok? I want to understand that because it's not the first time i receive that error.
Code execution example:
Please insert a phrase: hello world!
The string -hello world!- converted in hex is
68 65 6c 6c 6f
20 77 6f 72 6c
64 21
#include <iostream>
#include <iomanip>
#include <string>
#include <cstring>
using namespace std;
int main()
{
string phrase;
char* chArray;
cout << "Pls insert a phrase:\t";
getline(cin, phrase);
chArray = new char[phrase.size() + 1];
strcpy(chArray, phrase.c_str()); //THE ERROR IS HERE!
cout << "The string -" << phrase << "- converted in hex is\n";
for (int i = 1; i < static_cast<int>(phrase.size() + 1); i++)
{
int ch = (int)chArray[i-1];
cout << setbase(16) << ch << " ";
if (i % 5 == 0)
cout << "\n";
}
return 0;
}
You get this warning when you use any of the "unsafe" byte copying functions. It's mostly specific to MSVC.
To fix it, use strcpy_s which requires you to also pass a maximum number of bytes to copy (which should be the size of the destination buffer). This prevents buffer overflows.
strcpy_s(chArray, phrase.size()+1, phrase.c_str());
That said, it's easier to use std::string for all this in C++
Visual studio compiler says: 'strcpy': This function or variable may be unsafe.
This is because you've used strcpy, and your compiler considers it a potentially unsafe function. The purpose of the warning is to inform you of this perceived lack of safety. The message advises you how to disable the warning in case you wish to keep using the function.
The typical, safer alternative is to use std::string instead. In case of your particular program, the use of strcpy seems completely redundant. Instead of chArray[i-1], you could use phrase[i-1].
So why dev-c++ doesn't tell me that?
Diagnostic messages are up to discretion of the implementation. You're using another compiler with this IDE, and that one does not warn you for using strcpy.
Did I make any mistakes?
Someone might argue that the choice to use strcpy is a mistake. But it's a mistake because it is easy to misuse by accident. As far as I can tell, you've used it correctly.
That said, part of the unsafety is that incorrect use is not necessarily easy to recognise. If it was easy, then the compiler would tell you when you use it incorrectly. But it's not easy, and the compiler cannot do that in general.
Besides the use of strcpy, there is another potential issue: You leak the memory that you allocate for the character array.
I have read three ways to print things to the console in c++ from various sources.
Using using namespace std; and then using cout (CodeBlocks Standard)
Not using the above and using std::cout and std::endl; (C++ Primer)
Using printf (HackerRank)
Which is preferred and why?
Number 2 with amendment. (std::cout and '\n')
Why?
Because you should avoid using namespace std. Source
(Among other reasons) Because cout is typesafe and printf is not. Source
std::endl will force a flush of the output buffer to the console. Unless you specifically want this to happen use << '\n' or << "...string\n". Source
Unless you really care about speed, both cout and printf are fine. If you want faster runtimes, here are a few pointers :
Use only printf with no cout. This will give more speed than using a mixture of printf and cout or just cout.
Or use only cout but add the following at the beginning of execution
ios_base::sync_with_stdio(false);cin.tie(NULL); . There are two separate streams for printf and cout and they are synchronized by default. Lot of running time is wasted due to this synchronisation. These two lines of code will stop the synchronisation, but take care that you don't use any printf if you add these lines, otherwise printing might happen in random order.
Do not use endl unless you want to flush the output buffer. Lots of endl can make the code slower. Use cout<<'\n'; instead.
these is my debugger code that during these 10 years of c++ working helped me.
std::ostream &debugRecord (const char* fileName, int lineNum, const char* funcName)
{
std::lock_guard<std::mutex> lock(streamMutex_);
return std::cout << "Thread # " << getCurrentThreadId() << " -- "
<< "(" << fileName << ":" << lineNum << "): " << funcName << std::endl;
}
Both your first points do basically the same thing. It's better practice to use std:: instead of using namespace std; as the latter pollutes the global namespace and can cause naming conflicts.
Something not mentioned is that you can selectively expose parts of a namespace with using <namespace>::<element>; (e.g. using std::cout;). It's still better practice to be verbose with your statements, but this option still isn't as bad as exposing the entire namespace.
printf isn't as safe as cout (the stream << operators do a good job of printing what you want), you ought to avoid it while starting out.
The answer depends a lot on what you want to do. For output which largely uses default formats cout is indeed preferred because of the type safety and because it's very intuitive.
If you want to heavily format your output though I can only recommend the surprisingly versatile and straight-forward printf because manipulators in cout are a pain. True: The printf format syntax, does, let's say, take some getting used to, but it's surely worth it. Just double check the format string, listen to the warnings of your compiler, and use the proper format specifiers e.g. for size_t and other system dependent data in order to stay portable.
There is also a boost facility for combining streams and printf style formatting, see https://stackoverflow.com/a/15106194/3150802, but I have never used it. Perhaps somebody can comment on its usability?
While doing cppcheck, cppcheck is showing 'invalid scanf' and it is saying:
scanf without field width limits can crash with huge input data on some versions of libc.
Does it give any crash for my program? How to get rid of this issue?
int a;
char str[32];
int part[4];
// after this i am storing some string in 'str'.
a = sscanf(str, "%d%d%d%d", &part[0], &part[1], &part[2], &part[3]); // here i am getting that cppcheck portability error.
How to get rid of this issue
By writing C++ rather than C, and using C++ Standard Library tools rather than the out-dated and often unsafe C Standard Library tools.
#include <iostream>
#include <sstream>
void test()
{
std::string str("4 5 6 7");
int part[4];
std::istringstream ss(str);
ss >> part[0]
>> part[1]
>> part[2]
>> part[3];
}
What you are getting is just a warning: some libc implementations might crash if, say, you give too long strings to %s etc. CPPCheck recommends you to use other, typesafe, c++ methods to achieve your aim (i.e. streams and std::to_string() convertors etc.)
I am relatively new to the C++ world.
I know std::cout is used for console output in C++. But consider the following code in C :
#include<stdio.h>
int main(){
double dNum=99.6678;
printf("%.02lf",dNum);
//output: 99.67
return 0;
}
How do I achieve the similar formatting of a double type value upto 2 decimal places using cout in C++ ?
I know C++ is backward compatible with C. But is there a printf() equivalent in C++ if so, then where is it defined ?
This is what you want:
std::cout << std::fixed << std::setprecision(2);
std::cout << dNum;
and don't forget to :
#include <iostream>
#include <iomanip>
There is no equivalent. It is a pain using cout for formatted output.
All suggested solutions calling setprecision and similar are awfull when using long formats.
boost::format does not support some very nice features. Incompatibilities with printf. I still use printf because it is unbeatable.
If you want to use printf like formatting you should probably use snprintf (or build an allocating variant of that on top of that). Note that sprintf requires you to be able to guarantee that the result will not overrun the buffer you have to keep defined behaviour. With snprintf on the other hand can guarantee that it will not overrun the buffer since you specifiy the maximal number of characters that will be written to the string (it will instead truncate the output).
You could even build something that can directly be fed to an ostream on top of snprintf by automatically allocate the buffer and place in an object that on destruction free that memory. This in addition with a method to feed the object to an ostream would finish it off. Something like (with room for improvements):
struct Format {
char buf[999];
Format(fmt, ...) {
va_list ap;
va_start(fmt, ap);
vsnprintf(buf, sizeof(buf), fmt, ap);
va_end(ap);
}
}
ostream& operator<< (ostream& os, Format const& str);
then you use this as:
cout << Format("The answer is %d", 42) << endl;
If you're using the GNU libraries you could of course use printf directly since cout and stdout are the same object then. Otherwise you should probably avoid mixing stdio and iostreams as there is no guarantee that these are synchronized with each other.
If you really want to reuse the same formatting techniques as in C, you may use Boost::format, which does exactly that:
cout << boost::format("%.02lf") % dNum;
But is there a printf() equivalent in C++ if so, then where is it defined?
There is a standards proposal P0645 to add a similar formatting facility to C++. In the meantime you can use the {fmt} library that implements this proposal and more:
#include <fmt/core.h>
int main()
fmt::print("{:.02f}", 99.6678);
}
P0645 and {fmt} use Python-like format string syntax which is similar to printf's but uses {} as delimiters instead of %.
Also the type information is preserved so you don't need l or other noisy specifiers.
Save your program as CPP and run it.
It runs and prints the answer.
Because C++ also has the printf() and scanf() like C.
You can also use sprintf in C++ to 'print' into a string and then cout that string. This strategy leverages your experience with printf-style formatting.
To output a value to the console using C++, you need the global ostream object cout and the << operator. endl is another global ostream object used as line break.
All are defined in the <iostream> header file. You can also use various formatting flags to control the presentation of the output...
#include<iostream>
using namespace std;
int main() {
double dNum = 99.6678;
cout << dNum;
cout.setf(ios::scientific, ios::floatfield); // format into scientific notation
cout << dNum;
cout.precision(8); // change precision
cout << dNum;
system("pause");
return 0;
}
The functional equivalent of your printf() call, using std::cout, is
std::cout << fixed << setprecision(2) << dNum;
It is necessary to #include <iomanip> and <iostream>.
The printf() equivalent in C++ is std::printf(), declared in <cstdio>.
Also, thanks to backward compatibility to C - specifically C++98 was required to maximise backward compatiblility to C89 - C's printf() declared in <stdio.h> is also available in C++. Note, however, that <stdio.h> is deprecated (tagged for removal from a future version of the C++ standard). Also, not all features of printf() introduced in C99 (the 1999 C standard) or later are necessarily supported in C++.
My understanding is that string is a member of the std namespace, so why does the following occur?
#include <iostream>
int main()
{
using namespace std;
string myString = "Press ENTER to quit program!";
cout << "Come up and C++ me some time." << endl;
printf("Follow this command: %s", myString);
cin.get();
return 0;
}
Each time the program runs, myString prints a seemingly random string of 3 characters, such as in the output above.
C++23 Update
We now finally have std::print as a way to use std::format for output directly:
#include <print>
#include <string>
int main() {
// ...
std::print("Follow this command: {}", myString);
// ...
}
This combines the best of both approaches.
Original Answer
It's compiling because printf isn't type safe, since it uses variable arguments in the C sense1. printf has no option for std::string, only a C-style string. Using something else in place of what it expects definitely won't give you the results you want. It's actually undefined behaviour, so anything at all could happen.
The easiest way to fix this, since you're using C++, is printing it normally with std::cout, since std::string supports that through operator overloading:
std::cout << "Follow this command: " << myString;
If, for some reason, you need to extract the C-style string, you can use the c_str() method of std::string to get a const char * that is null-terminated. Using your example:
#include <iostream>
#include <string>
#include <stdio.h>
int main()
{
using namespace std;
string myString = "Press ENTER to quit program!";
cout << "Come up and C++ me some time." << endl;
printf("Follow this command: %s", myString.c_str()); //note the use of c_str
cin.get();
return 0;
}
If you want a function that is like printf, but type safe, look into variadic templates (C++11, supported on all major compilers as of MSVC12). You can find an example of one here. There's nothing I know of implemented like that in the standard library, but there might be in Boost, specifically boost::format.
[1]: This means that you can pass any number of arguments, but the function relies on you to tell it the number and types of those arguments. In the case of printf, that means a string with encoded type information like %d meaning int. If you lie about the type or number, the function has no standard way of knowing, although some compilers have the ability to check and give warnings when you lie.
Please don't use printf("%s", your_string.c_str());
Use cout << your_string; instead. Short, simple and typesafe. In fact, when you're writing C++, you generally want to avoid printf entirely -- it's a leftover from C that's rarely needed or useful in C++.
As to why you should use cout instead of printf, the reasons are numerous. Here's a sampling of a few of the most obvious:
As the question shows, printf isn't type-safe. If the type you pass differs from that given in the conversion specifier, printf will try to use whatever it finds on the stack as if it were the specified type, giving undefined behavior. Some compilers can warn about this under some circumstances, but some compilers can't/won't at all, and none can under all circumstances.
printf isn't extensible. You can only pass primitive types to it. The set of conversion specifiers it understands is hard-coded in its implementation, and there's no way for you to add more/others. Most well-written C++ should use these types primarily to implement types oriented toward the problem being solved.
It makes decent formatting much more difficult. For an obvious example, when you're printing numbers for people to read, you typically want to insert thousands separators every few digits. The exact number of digits and the characters used as separators varies, but cout has that covered as well. For example:
std::locale loc("");
std::cout.imbue(loc);
std::cout << 123456.78;
The nameless locale (the "") picks a locale based on the user's configuration. Therefore, on my machine (configured for US English) this prints out as 123,456.78. For somebody who has their computer configured for (say) Germany, it would print out something like 123.456,78. For somebody with it configured for India, it would print out as 1,23,456.78 (and of course there are many others). With printf I get exactly one result: 123456.78. It is consistent, but it's consistently wrong for everybody everywhere. Essentially the only way to work around it is to do the formatting separately, then pass the result as a string to printf, because printf itself simply will not do the job correctly.
Although they're quite compact, printf format strings can be quite unreadable. Even among C programmers who use printf virtually every day, I'd guess at least 99% would need to look things up to be sure what the # in %#x means, and how that differs from what the # in %#f means (and yes, they mean entirely different things).
use myString.c_str() if you want a c-like string (const char*) to use with printf
thanks
Use std::printf and c_str()
example:
std::printf("Follow this command: %s", myString.c_str());
You can use snprinft to determine the number of characters needed and allocate a buffer of the right size.
int length = std::snprintf(nullptr, 0, "There can only be %i\n", 1 );
char* str = new char[length+1]; // one more character for null terminator
std::snprintf( str, length + 1, "There can only be %i\n", 1 );
std::string cppstr( str );
delete[] str;
This is a minor adaption of an example on cppreference.com
printf accepts a variable number of arguments. Those can only have Plain Old Data (POD) types. Code that passes anything other than POD to printf only compiles because the compiler assumes you got your format right. %s means that the respective argument is supposed to be a pointer to a char. In your case it is an std::string not const char*. printf does not know it because the argument type goes lost and is supposed to be restored from the format parameter. When turning that std::string argument into const char* the resulting pointer will point to some irrelevant region of memory instead of your desired C string. For that reason your code prints out gibberish.
While printf is an excellent choice for printing out formatted text, (especially if you intend to have padding), it can be dangerous if you haven't enabled compiler warnings. Always enable warnings because then mistakes like this are easily avoidable. There is no reason to use the clumsy std::cout mechanism if the printf family can do the same task in a much faster and prettier way. Just make sure you have enabled all warnings (-Wall -Wextra) and you will be good. In case you use your own custom printf implementation you should declare it with the __attribute__ mechanism that enables the compiler to check the format string against the parameters provided.
The main reason is probably that a C++ string is a struct that includes a current-length value, not just the address of a sequence of chars terminated by a 0 byte. Printf and its relatives expect to find such a sequence, not a struct, and therefore get confused by C++ strings.
Speaking for myself, I believe that printf has a place that can't easily be filled by C++ syntactic features, just as table structures in html have a place that can't easily be filled by divs. As Dykstra wrote later about the goto, he didn't intend to start a religion and was really only arguing against using it as a kludge to make up for poorly-designed code.
It would be quite nice if the GNU project would add the printf family to their g++ extensions.
Printf is actually pretty good to use if size matters. Meaning if you are running a program where memory is an issue, then printf is actually a very good and under rater solution. Cout essentially shifts bits over to make room for the string, while printf just takes in some sort of parameters and prints it to the screen. If you were to compile a simple hello world program, printf would be able to compile it in less than 60, 000 bits as opposed to cout, it would take over 1 million bits to compile.
For your situation, id suggest using cout simply because it is much more convenient to use. Although, I would argue that printf is something good to know.
Here’s a generic way of doing it.
#include <string>
#include <stdio.h>
auto print_helper(auto const & t){
return t;
}
auto print_helper(std::string const & s){
return s.c_str();
}
std::string four(){
return "four";
}
template<class ... Args>
void print(char const * fmt, Args&& ...args){
printf(fmt, print_helper(args) ...);
}
int main(){
std::string one {"one"};
char const * three = "three";
print("%c %d %s %s, %s five", 'c', 3+4, one + " two", three, four());
}