different definitions of string changes answer - c++

I've started learning C++ from HackerRank.
st.first_name outputs concatenated strings(first_name and last_name) when they are defined like char first_name[50]; and char last_name[50];. But when i define them like string first_name; and string last_name; output is fine. Why is it so?
Here is the code:
#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
/*
add code for struct here.
*/
struct Student
{
int age;
//char first_name[50];
//char last_name[50];
string first_name;
string last_name;
int standard;
};
int main() {
Student st;
cin >> st.age >> st.first_name >> st.last_name >> st.standard;
cout << st.age << " " << st.first_name << " " << st.last_name << " " << st.standard;
return 0;
}
Here is the link to this question on HackerRank:
https://www.hackerrank.com/challenges/c-tutorial-struct
input for which i'm getting contradicting output:
11
lwpxiteeppsacowpnbxluqpmasgnwefzcsvrjxxammuqcftzgn uinkydgppulchupyrlwvbisdtqurfcsbaobgtplvvlxbxgltk
10
expected output:
11
lwpxiteeppsacowpnbxluqpmasgnwefzcsvrjxxammuqcftzgn uinkydgppulchupyrlwvbisdtqurfcsbaobgtplvvlxbxgltk
10
my output: 11 lwpxiteeppsacowpnbxluqpmasgnwefzcsvrjxxammuqcftzgnuinkydgppulchupyrlwvbisdtqurfc‌​sbaobgtplvvlxbxgltk
uinkydgppulchupyrlwvbisdtqurfcsbaobgtplvvlxbxgltk
10

In C++ C-style strings (using arrays of char) need a special terminator character, '\0'. This of course take up a character and you need to include that in the array you allocate. If you don't have space for the terminator it will be written out of bounds and you will have undefined behavior.
That's why you really should use std::string when programming in C++, you don't risk buffer overflows.
If you need to use C-style strings and arrays of char you need to add an extra character to your arrays to make space for the terminator. So if you want to allow the users to enter 50 characters, then you need an array of 51 characters. But beware, C++ has no bounds-checking so if the user enters a string longer than 50 characters you will still write out of bounds.

Related

(c++) problem in printing words of char array string

I'm making a c++ program using string(data type) and char array. Now, the data type is printing words alright. But, I'm having some trouble with the char array. Here's the code:
#include<iostream>
#include<string.h>
using namespace std;
int main(){
char str[200];
string str1;
cout<<"Enter a string:\t";
getline(cin,str1);
cout<<str1 <<endl;
cout<<"enter second string:\t";
cin>>str;
cin.get(str,200);
cout<<str;
}
code output
As, you can see in the output, the data type string is printing the words fine. But, the char array is missing the first word. Am I doing something wrong? or does the char array work in different way? Please explain. Thanks.
While you have already discovered that cin >> str; isn't required as you are simply writing again to str with cin.getline (str, sizeof str), there are a number of additional issues you should address:
1. Unless your compiler is ancient, you should #include <string>, not the C-header string.h;
2. Don't use magic-numbers in your code. If you need a constant, e.g. for the maximum number of characters in str, #define a constant or use a global enum to do the same, e.g.
#define MAXC 200 /* if you need a constant, #define one (or more) */
...
char str[MAXC]; /* don't use 'magic-number', use a constant */
That way when, and if you change the number of characters in str in the future, you don't have to pick through your entire code and change every occurrence of the magic-number, e.g. cin.get(str,200);.
3. Validate EVERY user input. Otherwise a failed input can set an error-bit on your input stream and additional attempts to read from a stream with an error-bit set can result in undefined behavior. You could do:
if (!getline(cin,str1)) { /* VALIDATE every input */
cerr << "error: input failure - str1.\n";
return 1;
}
and
if (cin.get (str, sizeof str))
cout << str << endl;
(note: there are no further attempted reads after cin.get (str, sizeof str) so guarding your use of str is sufficient)
4. Always output a newline after your final line output to ensure your program is POSIX compliant. Otherwise on many OS's you will mess up the users prompt if writing to stdout or you will create a non-POSIX compliant output file if redirecting the output to a file, e.g.
my cat has none01:22 wizard:~/dev/src-cpp/tmp/debug>
Putting it altogether, you could do something like:
#include <iostream>
#include <string> /* depending on your compiler */
#define MAXC 200 /* if you need a constant, #define one (or more) */
using namespace std;
int main (void) {
char str[MAXC]; /* don't use 'magic-number', use a constant */
string str1;
cout << "enter a string: ";
if (!getline(cin,str1)) { /* VALIDATE every input */
cerr << "error: input failure - str1.\n";
return 1;
}
cout << str1 << endl;
cout << "enter second string: ";
// cin >> str; /* not needed */
if (cin.get (str, sizeof str))
cout << str << endl;
}
Example Use/Output
$ ./bin/cin.get_getline
enter a string: my dog has fleas
my dog has fleas
enter second string: my cat has none
my cat has none
cout<<"enter second string:\t";
cin>>str;
cin.get(str,200);
here first you are trying to read the second word twice into same variable. comment one of them and try to print the content of str.
#include<iostream>
#include<string.h>
using namespace std;
int main(){
char str[200];
string str1;
cout<<"Enter a string:\t";
getline(cin,str1);
cout<<str1 <<endl;
cout<<"enter second string:\t";
// cin>>str;
cin.get(str,200);
cout<<str<<endl;
}

Making array (char) 1 gives error on stdio.h

I was trying to hold the text entered by user inside an Char array but it does not end up well. I tried this method but i think it deleted after c++ 11.
Here's my code :
#include "stdafx.h"
#include <iostream>
using namespace std;
int main()
{
char sentence[2];
cout << "Enter your sentences : ";
gets_s(sentence);
cout << sentence << endl;
system("PAUSE");
return 0;
}
It gives overload error and doesnt works.
Chances are you are trying to get the string literal that is longer than 2 characters yet not being able to insert it into your buffer of:
char sentence[2];
Increase the buffer size to something more acceptable:
char sentence[255];
That being said in C++ you should prefer std::string to character array and std::getline to gets_s.

C++ : Getline Function Mechanics

#include <iostream>
#include <string>
using namespace std;
int main()
{
int num;
cin >> num;
string s;
getline(cin, s);
cout << s << " " << num << endl;
return 0;
}
In this code if I input 3 and press enter, then s takes an empty string.
1) If it is taking the first character as a newline, then is there a possible solution of taking line as input after taking an integer as input?
2) If my input is 4567artyu then how it is deciding whether 7 has to go into the s or num ?
I recommend that you always read complete lines of input from your users. It will cause the least confusion.
Ask for input.
Use std::getline to read a line of input.
If you don't want a string but, say, an integer, use std::stoi or (more general) boost::lexical_cast to safely convert the input to your desired target type. This is where you catch poor inputs and complain at the user.
I don't think that many users, if prompted for a number, would expect that entering 42bananas would be accepted as 42 and the bananas part be “remembered” for later. It will most likely be a typo and the user will be happy to be asked to correct it.
For taking line as input after taking integer as input you can consider removing the stray '\n' character from the stream.
#include <iostream>
#include <string>
using namespace std;
int main()
{
int num;
cin >> num;
getchar();
string s;
getline(cin, s);
cout << s << " " << num << endl;
return 0;
}
This will do the trick.
For second question, it reads 4567 as integer, it will continue to read it as integer until limit of int is reached and if limit is reached it will not consider anything after that. Then it will put the maximum value of int in the variable num and null int the string s. If limit is not reached, then string will remain in the input stream as it is, and will be fetched by variable s.
Try using cin.clear before you accept string

Using cin for char array

Here is my code:
#include <iostream>
using namespace std;
int main(){
char inp[5], out[4];
cin >> inp >> out;
cout << inp << endl;
cout << out << endl;
system("pause");
return 0;
}
when I type:
12345
6789
It gives me:
6789
Why I failed to save the 5 words char array 'inp' and it showed nothing? The second input looks normal though. However, when I set out[3] or out[5], it seems to work alright? It seem that two char array of [5] then followed by [4] would cause problem...
I see that you enter (type) 1234567890 characters to input data for inp[5] - it is a problem because imp array is able to store 4 characters and null-terminator. When cin >> inp store more than 4 characters to inp array it leads to problem with data (somthing like undefined behaviour). So solution can be in allocation more memory for data, e.g.:
#include <iostream>
using namespace std;
int main(){
char inp[15], out[15]; // more memory
cin >> inp >> out;
cout << inp << endl;
cout << out << endl;
system("pause");
return 0;
}
When you read into a character array the stream keeps reading until it encounters whitespace, the stream is not aware of the size of the array that you pass in so happily writes past the end of the array so if your first string is longer than 4 characters your program will have undefined behaviour (an extra character is used after your input for the null terminator).
Fortunately c++20 has fixed this issue and the stream operators no longer accept raw char pointers and only accept arrays and will only read up to size - 1 characters.
Even with c++20 the better solution is to change your types to std::string which will accept any number of characters end even tell you how many characters it contains:
#include <iostream>
int main(){
std::string inp, out;
std::cin >> inp >> out;
std::cout << inp << "\n";
std::cout << out << "\n";
return 0;
}
Its because, in memory layout of computer out[4] is laid out first and then inp[5]. Something like this:
out[0],out[1],out[2],out[3],inp[0],inp[1],inp[2],inp[3],inp[4]
So, when you write 6789 in out[4], you are overflowing null character to inp[0]. So, inp becomes NULL.

Full String is not showing in C++ program

I have following Simple program to print string in C++, But this program only reads characters before space, not reading full string.
#include<iostream>
using namespace std;
int main()
{
char str[90];
cout << "Enter a string:";
cin >> str;
cout << str;
system("pause");
}
This is by design: cin "breaks" lines on whitespace characters, such as spaces and tabs.
Moreover, you are limiting the input to 90 characters, which is not good either: typing more than 90 characters with no spaces in between would overflow the buffer.
Here is a way to fix it:
std::string str;
std::cout << "Enter a string: ";
std::getline(std::cin, str);
Unlike character arrays, std::string objects can grow dynamically, so they would accommodate any number of characters the user chooses to enter.
You need to add two headers in order for this to compile:
#include <string>
#include <iostream>
>> reads a single word. You want getline to read a whole line:
cin.getline(str, sizeof str);
Now the problem is that the line will be truncated if it's too long. To fix that, use a string rather than a fixed-size buffer:
string str;
getline(cin, str);