How to use c-strings and avoid overflow c++ - c++

How do I use a c-string and avoid overflow? For example if I had the code:
#include <iostream>
using namespace std;
int main()
{
int size = 1000;
char * name = new char[size];
getline(cin, name);
}
I don't know how long that persons name is going to be, so how do you avoid an overflow? If I allocated 1000 as a precaution, they could just as easily input 1001 characters. What can I do to stop this from happening?
edit: I have to be able to do this without the string class

There is a version of std::getline() which accepts std::string as target buffer. It is designed to take advantage of std::string's auto-resize capability and prevent overflows. Example from std::getline manpage:
#include <string>
#include <iostream>
int main()
{
// greet the user
std::string name;
std::cout << "What is your name? ";
std::getline(std::cin, name);
std::cout << "Hello " << name << ", nice to meet you.\n";
}
In addition to the safety you asked about, std::string gives you also automatic memory management - so you don't need to remember to delete anything, which would be necessary in your example.
If you are not allowed to use std::string, you can use std::basic_istream::getline, which comes in two forms:
basic_istream& getline( char_type* s, std::streamsize count );
basic_istream& getline( char_type* s, std::streamsize count, char_type delim );
It allows you to specify max number of characters to read and an optional delimiter. std::basic_istream is the base class for std::istream. A very popular instance of this class is std::cin.
So basically, you can do:
char target[64];
std::cin.getline(target, 64);

Related

How to pass string to gets_s() in C++?

#include<iostream>
using namespace std;
int main() {
string str;
gets_s(str);
cout << str << endl;
return 0;
}
When I tried to run the above code it threw an error that no instance of gets_s() matched the argument list.
How can I pass an std::string instead of a char[] to gets_s() function if is possible?
The C function get_s takes a char* and a length argument, not a std::string.
Your best options are:
Formatted input:
std::cin >> str;
Read a line:
std::getline(std::cin, str);
Don't do that. Use the stream in a normal way:
#include<iostream>
using namespace std;
int main()
{
string str;
cin >> str;
cout << str << endl;
return 0;
}
gets_s has a significant limitation in that you must provide an upper limit on the number of characters you want to read.
Since you are using string the superior alternative is to use getline
#include <iostream>
#include <string>
using namespace std;
string str;
getline(cin, str);
This will expand the string to hold as many characters as are entered by the user.
gets_s() takes two arguments: pointer to char array and maximal size (your call is missing it). You cannot pass std::string - only C style strings.
Instead of C functions, why not use C++ way std::cin >> str or getline(std::cin, str)?
In C also don't use gets_s() (it's optional in C11) or gets() - use fgets() instead.
Well, there are a lot of answers about std::getline, but in case if you really need to use get_s, you may write such code:
size_t length = 10; // Just for example
std::string my_string(length, 0);
get_s(&my_string[0], length); // C++14 and older
get_s(my_string.data(), length); // C++17 and newer

How to use Input String Stream with symbols seperating strings instead of spaces?

note: I just learned about Getline and Streams.
Instead of a space separating first name, last name, and age, how could I separate them with ^ or --?
Is there a function for this? Is this a stupid question, and if so, why?
-The reason for this question is because I was going to make a function for solving polynomial derivatives and failed miserably.
int main() {
istringstream inSS; // Input string stream
string lineString; // Holds line of text
string firstName;
string lastName;
int userAge;
getline(cin, lineString);
inSS.str(lineString);
inSS >> firstName;
inSS >> lastName;
inSS >> userAge;
return 0;
}
The free function getline also offers to have a custom delimiter like user4581301 said. However, it will only extract strings and you also have int.
A similar solution can be found in this answer and I have modified the code to fit your needs: changing the delimiter for cin (c++)
You can use imbue to have some custom delimiter. A simple example is below:
#include <locale>
#include <iostream>
template<char Delim>
struct alternativeDelimiter : std::ctype<char> {
alternativeDelimiter() : std::ctype<char>(get_table()) {}
static mask const* get_table()
{
static mask rc[table_size];
rc[Delim] = std::ctype_base::space;
return &rc[0];
}
};
int main() {
using std::string;
using std::cin;
using std::locale;
cin.imbue(locale(cin.getloc(), new alternativeDelimiter<'^'>));
string word;
while(cin >> word) {
std::cout << word << "\n";
}
}
imbue does take ownership of the ctype, so no worries about calling delete yourself.
If you input some^text, the output will be
some
text
You can also use it with your example, of course.
If you extend the table by writing lines similar to line 11 (rc[Delim] = std::ctype_base::space) only changing Delim, you can have multiple characters that will be interpreted as space.
I am not sure in how far this solves your original problem of writing a math parser, though. The general terminology involves the concepts "parser" and "lexer" and you might research these concepts to build a reliable math solver. Hope it helps, too.

How to scan a string using scanf with C++

I have tried most of the string and char format types and they are not working and I have no Idea why. Here is my code :
#include <iostream>
#include <stdio.h>
using namespace std;
int main(int argc, const char * argv[])
{
// insert code here...
string string2;
string string;
cout << "Hello, World!\n";
printf("Hi my name is Josh %s\n",string2);
scanf("%s",&string);
printf("hi %s",string);
}
What you're showing (scanf("%s",&string);) doesn't work (and never could, by e.g. giving different format specifiers)!
scanf() used with the %s format specifier requires a corresponding char* pointer referencing a raw char[] array to receive the read data in the parameter list. The std::string pointer you're passing in your example, doesn't provide automatic casting to the referred std::string instances internally managed char[] buffer that way though.
You could try to use &string.front() instead, but I wouldn't really recommend that, unless you're very sure what you're doing.
For c++ you should better use std::cin and
std::istream& operator>>(std::istream&, const std::string&)
instead:
std::cout << "Put in string value:" << std::endl;
std::string input;
std::cin >> input;
(xcode isn't relevant for your question BTW!)
You shouldn't mix std::cout with ::printf. Prefer to use the C++ Standard IO library over C functions from stdio.
Your code should look a little like this:
#include <iostream>
int main()
{
std::string string2;
std::string other_string;
std::cout << "Hello, World!\n";
std::cout << "Hi my name is Josh " << string2 << '\n';
std::cin >> other_string;
std::cout << "hi " << other_string;
}

How can I initialize a *char using user input?

Initializing a string in C# is as easy as this:
string str = Console.Read();
with this method, I don't need to know the size of the string which the user enters. But I cannot find a way like this in C++. I want my string to be defined as char *input, and I don't want to know the size of the string.
How can I achieve what I want?
Why not use C++'s string type?
#include <iostream>
#include <string>
int main() {
std::string foo;
std::cin >> foo;
std::cout << foo << "\n";
}
C++ has a string class which works much like C#'s string. So use it. :)
char* is not a string. It's just the closest you get if you're working in C.
So, #include <string>, and then use std::string instead of char*.
Use std::string and std::cin:
std::string str;
std::cin >> str;

How to read and write a STL C++ string?

#include<string>
...
string in;
//How do I store a string from stdin to in?
//
//gets(in) - 16 cannot convert `std::string' to `char*' for argument `1' to
//char* gets (char*)'
//
//scanf("%s",in) also gives some weird error
Similarly, how do I write out in to stdout or to a file??
You are trying to mix C style I/O with C++ types. When using C++ you should use the std::cin and std::cout streams for console input and output.
#include <string>
#include <iostream>
...
std::string in;
std::string out("hello world");
std::cin >> in;
std::cout << out;
But when reading a string std::cin stops reading as soon as it encounters a space or new line. You may want to use std::getline to get a entire line of input from the console.
std::getline(std::cin, in);
You use the same methods with a file (when dealing with non binary data).
std::ofstream ofs("myfile.txt");
ofs << myString;
There are many way to read text from stdin into a std::string. The thing about std::strings though is that they grow as needed, which in turn means they reallocate. Internally a std::string has a pointer to a fixed-length buffer. When the buffer is full and you request to add one or more character onto it, the std::string object will create a new, larger buffer instead of the old one and move all the text to the new buffer.
All this to say that if you know the length of text you are about to read beforehand then you can improve performance by avoiding these reallocations.
#include <iostream>
#include <string>
#include <streambuf>
using namespace std;
// ...
// if you don't know the length of string ahead of time:
string in(istreambuf_iterator<char>(cin), istreambuf_iterator<char>());
// if you do know the length of string:
in.reserve(TEXT_LENGTH);
in.assign(istreambuf_iterator<char>(cin), istreambuf_iterator<char>());
// alternatively (include <algorithm> for this):
copy(istreambuf_iterator<char>(cin), istreambuf_iterator<char>(),
back_inserter(in));
All of the above will copy all text found in stdin, untill end-of-file. If you only want a single line, use std::getline():
#include <string>
#include <iostream>
// ...
string in;
while( getline(cin, in) ) {
// ...
}
If you want a single character, use std::istream::get():
#include <iostream>
// ...
char ch;
while( cin.get(ch) ) {
// ...
}
C++ strings must be read and written using >> and << operators and other C++ equivalents. However, if you want to use scanf as in C, you can always read a string the C++ way and use sscanf with it:
std::string s;
std::getline(cin, s);
sscanf(s.c_str(), "%i%i%c", ...);
The easiest way to output a string is with:
s = "string...";
cout << s;
But printf will work too:
[fixed printf]
printf("%s", s.c_str());
The method c_str() returns a pointer to a null-terminated ASCII string, which can be used by all standard C functions.