The best method for filling char array (gets vs cin.getline) - c++

I'm using C ++ 11. I'm wondering if there are any advantages to using cin.getline () compared to gets ().
I need to fill a char array.
Also, should I use fgets or getline for files?

I'm wondering if there are any advantages to using cin.getline () compared to gets ().
I am assuming you really mean gets, not fgets.
Yes, there definitely is. gets is known to be a security problem. cin.getline() does not suffer from that problem.
It's worth comparing fgets and cin.getline.
The only difference that I see is that fgets will include the newline character in the output while cin.getline won't.
Most of the time, the newline character is ignored by application code. Hence, it is better to use cin.getline() or istream::getline() in general. If presence of the newline character in the output is important to you for some reason, you should use fgets.
Another reason to prefer istream::getline is that you can specify a character for the delimiter. If you need to parse a comma separated values (CSV) file, you can use:
std::ifstream fstr("some file name.csv");
fstr.getline(data, data_size, ',');

Of course.
First of all gets doesn't check of length of the input - so if the input if longer than char array, you are getting an overflow.
On the other hand cin.getline allows to specify the size of stream.
Anyway, the consensus among C++ programmers is that you should avoid raw arrays anyway.

Related

Is getline is as same as gets?

Okay so my question is simple..
We all know that how bad the gets is in C & hence the advice is to use fgets.
Now in C++ we use std::string s and std::getline(std::cin, s)..Now my question is that does getline() has the same boundary checking issue like gets()..
If yes then for char input[100] & cin.getline(input,sizeof(input)); will work for char array but while using string can I write this?
std::string s; & cin.getline(s, s.capacity()); ...is this appropriate or something else can I write??
No, getline does not have the same issues as gets. The function has a reference to the string, and so can call the string's size and capacity member functions for boundary checking purposes. However, it doesn't need to do that, because it also has access the string's resizing member functions, such as push_back, resize or operator+=, which will handle boundary checking automatically, reallocating when necessary.
get() leaves the delimiter in the queue thus letting you able to consider it as part of the next input. getline() discards it, so the next input will be just after it.
If you are talking about the newline character from a console input,it makes perfectly sense to discard it, but if we consider an input from a file, you can use as "delimiter" the beginning of the next field.

C++ tokenization

I am writing a lexer in C++ and I am reading from a file character by character, however, how do you do tokenization in this case? I can't use strtok since I have character not a string. Somehow I need to keep reading until I reach a delimeter?
The answer is Yes. You need to keep reading until you hit a delimiter.
There are multiple solutions.
The simplest thing to do is exactly that: keep a buffer (std::string) of the characters you already read until you reach a delimiter. At that point, you build a token from the accumulated characters in the buffer, clear the buffer, and push the delimiter (if necessary) in the buffer.
Another solution would be to read ahead of the time: ie, pick up the entire line with std::getline (for example), and then check what's on this line. In general the end-of-line is a natural token delimiter.
This works well... when delimiters are easy.
Unfortunately some languages, like C++, have awkward grammars. For example, in C++ >> can be either:
the operator >> (for right-shift and stream extraction)
the end of two nested templates (ie could be rewritten as > >)
In those cases... well, just don't bother with the difference in the tokenizer, and let your AST building pass disambiguate, it's got more information.
On the basis of information provided you.
If you want to read upto a delimiter from a File, use getline(char *,int,char) function.
getline() is use to read upto n characters or upto a delimiter.
Example:
#include<fstream.h>
using namespace std;
main()
{
fstream f;
f.open("test.cpp",ios::in);
char *c;
f.getline(c,2,' ');
cout<<c; // upto 1 char or till a space
}

fgets - maximum size (int num)

In my program, i'm calling the function fgets:
char * fgets ( char * str, int num, FILE * stream );
in a loop several times, and then deal with the new coming input (in case there is one).
in the fgets specifications, it says that:
num:
Maximum number of characters to be read (including the final
null-character). Usually, the length
of the array passed as str is used.
The problem is that i want to rean NO MORE than the specified num - and IGNORE the rest of it, if it's in the same line.
What i've found out, is that the fgets reads the next part of the line in the next call to the function.
How can i avoid this behavior?
You'll need to do it manually - consume the characters with fgets and copy the results to a result array until a newline character is found, dump the contents, and continue with fgets.
The size parameter is intended to be used to prevent reading more data than your buffer can hold. It won't work for skipping over data.
You'll have to write code to throw away the parts of the string you don't want after it's read.
fgets() is a old C function. The idea is that the language will provide minimal complexity functions that you can combine to do what you like. They don't include any extra capability on purpose. This keeps everyone from paying for things they don't use. Think LEGO.

C++ reading CSVs

Im having a bit of trouble reading CSVs. I have multiple types of data, so i am not sure how to get this to work:
string, string, bool, bool, int
I cant simply use >> to read in the data since the deliminator is not whitespace. scanf doesnt work, since it needs a human input, not file input, getline only reads in strings and also includes the \n char for some reason.
how can i read my csv properly?
You CAN use getline. There's an overload where the third argument passed can be a char for the delimiter. Just throw it all in a loop
Another option (which isn't typically recommended for C++, though), is fscanf. You're right that scanf is no good for you, but fscanf is its file-based equivalent.
Another canonical solution typically employed in C, but which isn't so strongly recommended in C++, is to go ahead and use getline, and then use strtok or a simple parser to parse each line.

gets (variable)

can anyone tell me why gets(abc) works with char[] but not with int?
int abc;
char name[] = "lolrofl";
printf("Hello %s.\n",name);
printf("\n >> ");
fflush(stdin);
gets (abc);
printf("\n die zahl ist %i.\n",abc);
system("Pause");
return(0);
The prototype for gets() is:
char* gets(char *s);
Note that the function DOES NOT read just a single character and place it in s; it actually reads an entire string into s. However, since gets() does not provide a way of specifying the maximum number of characters to read, this can actually read more characters into s than there are bytes allocated for s. Thus, this function is a serious buffer overflow vulnerability, and you should not use this function, ever. There are alternative, safer functions which allow you to read input from the user such as fgets() and getc().
If you are using C++, then using the C++ I/O Stream Library (std::cin, std::cout, std::ostream, std::istream, std::fstream, etc.) is a far better way to perform input/output than using these other functions.
The function gets() is so dangerous, in fact, that in my development and coding custom search engine, I have taken out a promotion on gets and several other such functions warning not to use it!
Because it only reads characters. Use scanf() for formatted reading.
By the way, since you appear to be using C++ (or at least your choice of tags says so), perhaps you should try std::cin/std::cout.
If you take a look at the C Reference your question will be answered. I'll paste it for you:
char *gets( char *str );
The gets() function reads characters
from stdin and loads them into str,
until a newline or EOF is reached. The
newline character is translated into a
null termination. The return value of
gets() is the read-in string, or NULL
if there is an error. Note that gets()
does not perform bounds checking, and
thus risks overrunning str. For a
similar (and safer) function that
includes bounds checking, see fgets().
So you won't be able to cast a whole string to an integer.
First, the gets function is for reading strings or text, not numbers.
Second, don't use gets as it has buffer overrun errors. See C Language FAQ for more information. The function fgets is a safer alternative.
Third, you may want to switch to C++ streams and std::string. The C++ streams are more type friendly than C streams.
Fourth, fflush does not function on input streams. The fflush function is for writing the remaining data in stream buffers to the output stream. In C++, there is a method, ignore, which will ignore incoming characters until a newline (default) or a specified character is read (or a limit is reached).
Hope that helps.