std::cin.getline(f_name, 10) - c++

If I have for example the following statements:
char f_name[11];
std::cin.getline(f_name,10);
Does thia mean:
* Declare a string with 11-characters wide?
* Read the entered line and pass it as the value for "f_name"?
Thanks.

Yes, you are correct!
char f_name[11];
declares the array f_name with 11 elements.
std::cin.getline(f_name,10);
prompts for the value to be entered, which then stores it in f_name[11].

Yes, and no.
char f_name[11];
declares an array of char with 11 elements. It's not really a string - you could consider it a "C string" if it had a NUL ('\0') at the end (which it does not).
std::cin.getline(f_name, 10);
May or may not read the entire entered line, because it only reads up to 9 chars. You need not make the buffer larger than the value given to cin.getline.
Unless you have a specific reason not to, use std::getline to read a line in C++. An example below.
#include <string>
std::string line;
std::getline(std::cin, line);

Related

How to read a file line by line without using the string class?

So in my c++ class, we're not allowed to use the string class right now. To substitute strings, we're using character arrays.
The assignment requires that i read from a file that contains a sentence on each line. The first line of the file is an integer that tells how many lines are in the file.
My first problem is that reading in the integer into a variable and using that variable in an array causes an error saying that the variable must be constant.
How can I get past that? I need a 2D array to count how many characters each sentence has. I want to initialize my array as char FileSentences[numberOfLines][81]. It's been decided that the sentence character cap will be 80 characters long, so the width of each row has to be 81 to account for the \0.
My second problem comes from how I'm reading in the integer. Since the first line in the file is an integer, I'm reading it like:
int numberOfLines;
ifstream fin;
fin.open("TestTextFile.txt");
fin >> numberOfLines;
This works and it sets the variable numberOfLines to the correct value. However, when I call fin.getline, the next thing it will read in is a blank. If I call fin.getline again, it is the first sentence of the file. Is there another way to read in the integer to prevent that or should I just set a blank sentence in memory to hold the first fin.getline value and then proceed to reading sentences into my array?
For the first problem, use a std::vector.
// Define a typedef for a line.
typedef char Line[81];
// Read the number of lines.
fin >> numberOfLines;
// Define a vector for the lines.
std::vector<Line> lines(numberOfLines);
For the second problem, use ifstream::ignore() to ignore the rest of the line.
fin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
Make sure to add
#include <limits>
to use std::numeric_limits.
I need a 2D array to count how many characters each sentence has. I
want to initialize my array as char FileSentences[numberOfLines][81].
Easy solution is to allocate what you need:
typedef char LINE[81];
LINE* FileSentences = new LINE[numberOfLines];
After you are done iterating on FileSentences, free the memory as follows:
delete [] FileSentences;

Mistake using scanf

could you say me what is the mistake in my following code?
char* line="";
printf("Write the line.\n");
scanf("%s",line);
printf(line,"\n");
I'm trying to get a line as an input from the console.But everytime while using "scanf" the program crashes. I don't want to use any std, I totally want to avoid using cin or cout. I'm just trying to learn how to tak a full line as an input using scanf().
Thank you.
You need to allocate the space for the input string as sscanf() cannot do that itself:
char line[1024];
printf("Write the line.\n");
scanf("%s",line);
printf(line,"\n");
However this is dangerous as it's possible to overflow the buffer and is therefore a security concern. Use std::string instead:
std::string line;
std::cout << "Write the line." << std::endl;
std::cin >> line;
std::cout << line << std::endl;
or:
std::getline (std::cin, line);
Space not allocated for line You need to do something like
char *line = malloc();
or
Char line[SOME_VALUE];
Currently line is a poor pointer pointing at a string literal. And overwriting a string literal can result in undefined behaviour.
scanf() doesn't match lines.
%s matches a single word.
#include <stdio.h>
int main() {
char word[101];
scanf("%100s", word);
printf("word <%s>\n", word);
return 0;
}
input:
this is a test
output:
word <this>
to match the line use %100[^\n"] which means 100 char's that aren't newline.
#include <stdio.h>
int main() {
char word[101];
scanf("%100[^\n]", word);
printf("word <%s>\n", word);
return 0;
}
You are trying to change a string literal, which in C results in Undefined behavior, and in C++ is trying to write into a const memory.
To overcome it, you might want to allocate a char[] and assign it to line - or if it is C++ - use std::string and avoid a lot of pain.
You should allocate enough memory for line:
char line[100];
for example.
The %s conversion specifier in a scanf call expects its corresponding argument to point to a writable buffer of type char [N] where N is large enough to hold the input.
You've initialized line to point to the string literal "". There are two problems with this. First is that attempting to modify the contents of a string literal results in undefined behavior. The language definition doesn't specify how string literals are stored; it only specifies their lifetime and visibility, and some platforms stick them in a read-only memory segment while others put them in a writable data segment. Therefore, attempting to modify the contents of a string literal on one platform may crash outright due to an access violation, while the same thing on another platform may work fine. The language definition doesn't mandate what should happen when you try to modify a string literal; in fact, it explicitly leaves that behavior undefined, so that the compiler is free to handle the situation any way it wants to. In general, it's best to always assume that string literals are unwritable.
The other problem is that the array containing the string literal is only sized to hold 1 character, the 0 terminator. Remember that C-style strings are stored as simple arrays of char, and arrays don't automatically grow when you add more characters.
You will need to either declared line as an array of char or allocate the memory dynamically:
char line[MAX_INPUT_LEN];
or
char *line = malloc(INITIAL_INPUT_LEN);
The virtue of allocating the memory dynamically is that you can resize the buffer as necessary.
For safety's sake, you should specify the maximum number of characters to read; if your buffer is sized to hold 21 characters, then write your scanf call as
scanf("%20s", line);
If there are more characters in the input stream than what line can hold, scanf will write those extra characters to the memory following line, potentially clobbering something important. Buffer overflows are a common malware exploit and should be avoided.
Also, %s won't get you the full line; it'll read up to the next whitespace character, even with the field width specifier. You'll either need to use a different conversion specifier like %[^\n] or use fgets() instead.
The pointer line which is supposed to point to the start of the character array that will hold the string read is actually pointing to a string literal (empty string) whose contents are not modifiable. This leads to an undefined behaviour manifested as a crash in your case.
To fix this change the definition to:
char line[MAX]; // set suitable value for MAX
and read atmost MAX-1 number of characters into line.
Change:
char* line="";
to
char line[max_length_of_line_you_expect];
scanf is trying to write more characters than the reserved by line. Try reserving more characters than the line you expect, as been pointed out by the answers above.

How to read a specific amount of characters from a text file

I tried to do it like this
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
char b[2];
ifstream f("prad.txt");
f>>b ;
cout <<b;
return 0;
}
It should read 2 characters but it reads whole line. This worked on another language but doesn't work in C++ for some reason.
You can use read() to specify the number of characters to read:
char b[3] = "";
ifstream f("prad.txt");
f.read(b, sizeof(b) - 1); // Read one less that sizeof(b) to ensure null
cout << b; // terminated for use with cout.
This worked on another language but doesn't work in C++ for some
reason.
Some things change from language to language. In particular, in this case you've run afoul of the fact that in C++ pointers and arrays are scarcely different. That array gets passed to operator>> as a pointer to char, which is interpreted as a string pointer, so it does what it does to char buffers (to wit read until the width limit or end of line, whichever comes first). Your program ought to be crashing when that happens, since you're overflowing your buffer.
istream& get (char* s, streamsize n );
Extracts characters from the stream and stores them as a c-string into
the array beginning at s. Characters are extracted until either (n -
1) characters have been extracted or the delimiting character '\n' is
found. The extraction also stops if the end of file is reached in the
input sequence or if an error occurs during the input operation. If
the delimiting character is found, it is not extracted from the input
sequence and remains as the next character to be extracted. Use
getline if you want this character to be extracted (and discarded).
The ending null character that signals the end of a c-string is
automatically appended at the end of the content stored in s.

Getting input from user using cin [duplicate]

This question already has answers here:
C++ "cin" only reads the first word [duplicate]
(5 answers)
Closed 4 years ago.
I am using Turbo C++ 3.0 Compiler
While using the following code ..
char *Name;
cin >> Name;
cout << Name;
When I gave input with space ... its only saving characters typed before space ..
like if I gave input "QWERT YUIOP" ... Name will contain "QWERT";
Any explaination why ??
When cin is used to read in strings, it automatically breaks at whitespace unless you specify otherwise.
std::string s;
std::cin >> noskipws >> s;
Alternatively, if you want to get a whole line then use:
std::getline(cin, s);
You'll also want to allocate storage for a raw char array, but with C++ you should use std::string or std::wstring anyway.
You need to allocate space for the char array into which you want to read the Name. char *Name; will not work as it only declares a char pointer not a char array. Something like char Name[30];
Also the cin << only allows us to enter one word into a string (char name[30]).
However, there is a cin function that reads text containing blanks.
cin.get(name, MAX)
get will read all characters including spaces until Max characters have
been read or the end of line character (ā€˜\nā€™) is reached and will put them
into the name variable.
You just declared a character pointer that doesn't point at anything. You need to allocate space for your string. The most common method would be to allocate space on the stack, IE:
char Name[50];
Remember a char pointer by itself is just a place to put an address to where the real memory is. You still have to get a block of memory and store the address in your pointer. The code above creates an array of Names on the stack and you can use Name to store up to 49 chars plus a null terminal.
Alternatively, for variable length strings use std::string.

Strange characters appear when using strcat function in C++

I am a newbie to C++ and learning from the MSDN C++ Beginner's Guide.
While trying the strcat function it works but I get three strange characters at the
beginning.
Here is my code
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int main() {
char first_name[40],last_name[40],full_name[80],space[1];
space[0] = ' ';
cout << "Enter your first name: ";
gets(first_name);
cout << "Enter your last name: ";
gets(last_name);
strcat(full_name,first_name);
strcat(full_name,space);
strcat(full_name,last_name);
cout << "Your name is: " << full_name;
return 0;
}
And here is the output
Enter your first name: Taher
Enter your last name: Abouzeid
Your name is: Y}#Taher Abouzeid
I wonder why Y}# appear before my name ?
You aren't initializing full_name by setting the first character to '\0' so there are garbage characters in it and when you strcat you are adding your new data after the garbage characters.
The array that you are creating is full of random data. C++ will allocate the space for the data but does not initialize the array with known data. The strcat will attach the data to the end of the string (the first '\0') as the array of characters has not been initialized (and is full of random data) this will not be the first character.
This could be corrected by replacing
char first_name[40],last_name[40],full_name[80],space[1];
with
char first_name[40] = {0};
char last_name[40] = {0};
char full_name[80] = {0};
char space[2] = {0};
the = {0} will set the first element to '\0' which is the string terminator symbol, and c++ will automatically fill all non specified elements with '\0' (provided that at least one element is specified).
The variable full_name isn't being initialized before being appended to.
Change this:
strcat(full_name,first_name);
to this:
strcpy(full_name,first_name);
You can not see any problem in your test, but your space string is also not null-terminated after initializing its only character with ' '.
As others have said, you must initialize the data, but have you ever thought about learning the standard c++ library? It is more intuitive sometimes, and probably more efficient.
With it would be:
string full_name=first_name+" "+last_name;
and you won't have to bother with terminating null characters. For a reference go to cplusplus
Oh and a full working example so you could understand better (from operator+=):
#include <iostream>
#include <string>
using namespace std;
int main ()
{
string name ("John");
string family ("Smith");
name += " K. "; // c-string
name += family; // string
name += '\n'; // character
cout << name;
return 0;
}
The problem is with your space text.
The strcat function requires a C-style string, which is zero or more characters followed by a null, terminating, character. So when allocating arrays for C-style strings, you need to allocate one extra character for the terminating null character.
So, your space array needs to be of length 2, one for the space character and one for the null character.
Since space is constant, you can use a string literal instead of an array:
const char space[] = " ";
Also, since you are a newbie, here are some tips:
1. Declare one variable per line.
This will be easier to modify and change variable types.
2. Either flush std::cout, use std::endl, or include a '\n'.
This will flush the buffers and display any remaining text.
3. Read the C++ language FAQ.
Click here for the C++ language Frequently Asked Questions (FAQ)
4. You can avoid C-style string problems by using std::string
5. Invest in Scott Myers Effective C++ and More Effective C++ books.
Strings are null-terminated in C and C++ (the strcat function is a legacy of C). This means that when you point to a random memory address (new char[] variables point to a stack address with random content that does not get initialized), the compiler will interpret everything up to the first \0 (null) character as a string (and will go beyond the allocated size if you use pointer arithmetic).
This can lead to very obscure bugs, security issues (buffer overflow exploits) and very unreadable and unmaintainable code. Modern compilers have features that can help with the detection of such issues.
Here is a good summary of your options.