C++ structure string and integer input - c++11

I wrote the following simple C++ structure implementation to see the usage of pointer to structure.
#include <iostream>
struct Employee
{
std::string name;
std::string sex;
int e_id;
}emp[2];
void printEmployee(struct Employee *e)
{
std::cout << e->name << std::endl;
std::cout << e->sex << std::endl;
std::cout << e->e_id << std::endl;
}
int main(int argc, char const *argv[])
{
struct Employee *e_ptr;
e_ptr = emp;
for (int i = 0; i < 2; ++i)
{
std::getline(std::cin, emp[i].name);
std::getline(std::cin, emp[i].sex);
std::cin >> emp[i].e_id;
}
for (int i = 0; i < 2; ++i)
{
printEmployee(e_ptr+i);
std::cout << std::endl;
}
return 0;
}
The inputs are
John Smith
male
123
Sarah Collin
female
After these input the program shows the output although the code is supposed to take one more input. The output is
John Smith
male
123
Sarah Collin
0
But If I don't include int e_id as a member then the code works perfectly.

This is from mixing getline and cin. Getline reads in the input until it hits a (generally) newline '\n'. It takes everything up to the newline, and throws away the newline.
cin reads until you hit white space (like, say, a newline), but doesn't throw it out of the stream. So, you type in 123 ENTER, meaning you have 123\n in the stream. Cin takes the 123 but leaves the \n.
Now you go back to the getline for employee name and immediately it sees the \n in the stream, which means it's done, and it throws it away. Out of curiosity, does it work if you type 123 SPACE instead of enter?
So what's actually happening is John Smith is good, male is good, 123 is good, but then the second employee's name is skipped, you typed Sarah Collin in for what was technically gender, then typed female for what was supposed to be e_id. Since female isn't an integer, what happens? Cin, by default, enters an error state and skips futher cin operations (you can also configure it to throw an exception). So really you actually never enter anything for the second e_id, and the 0 that you see is what it happened to be when it was created (you never initialized it, so it could actually be ANY value! Reading an uninitialized value is undefined behavior. Your compiler may help you out by setting ints to 0 for you, but that's not a kindness you can count on).
Here's someone else with your problem, and an example of how to use
cin.ignore();
to work around this. You need to manually ignore that newline character.
When and why do I need to use cin.ignore() in C++?

While reading integer std::cin stops when it encounters a character other than [+][-][0-9]. That is, std::cin stops at a character which cannot be included in a valid representation of an integer.
In the third line of input there are 4 characters are 123\n.
While reading std::string, std::getline stops reading characters when it encounters \n or delim characters. Also, std::getline does not store \n or delim characters in the string which is reads.
So, std::cin reads the integer emp[0].e_id as expected and stops at \n. After this std::getline reads \n and stops and stores nothing in emp[1].name

Related

Program isn't printing first digits of two strings

Hi I'm learning C through the Modern Approach book. For this program, we just need to input a first name and last name, and the program should return Last Name, First Initial.
char *first [255];
char *last [255];
printf("Enter a first name and a last name: ");
while (getchar() == ' ');
scanf("%s", first);
while (getchar() == ' ');
scanf("%s", last);
while (getchar() == ' ');
char firstInitial = (char) first[0];
printf("%s, ", last);
putchar(firstInitial);
When I run it, it doesn't print the first two characters.
e.g
Enter a first name and a last name: Aaron Smith
mith, a
This will get you started with getting the the first name.
#include <stdio.h>
int main() {
// Create a string
char firstName[255];
// Ask the user to input some text
printf("Enter your first name: \n");
// Get and save the text
scanf("%s", firstName);
// Output the text
printf("first name %s. 1st char %c", firstName, firstName[0]);
return 0;
}
#include <stdio.h>
void main()
{
char a = getchar();
char b;
scanf("%c",&b);
printf("%c",b);
}
Run the above code and see the result for yourself.
you can see that the getchar() function terminates only after when a “enter” key is pressed.
this causes an additional ‘\n’ character along with the single character you entered, to be in the input queue.
so character ‘b’ is assigned ‘\n’ and the compiler does not prompt you to provide input for ‘b’.

trying the check if cin.get() leaves the end of line character in stream

1.i am trying to check whether the cin.get() leaves the end line character in stream and considered it for next input.
i have tried this code in code blocks but unable to provide input for next string,i am attaching code i have tried and the output .could anyone please explain.
#include<iostream>
using namespace std;
int main()
{
char s1[10];
char s2[10];
cout << "enter the first string: ";
cin.get(s1, 10);
cout << "enter the second string: ";
cin.getline(s2, 10);
cout << s1 << " " << s2;
return 0;
}
enter the first string: hello
enter the second string: hello
please explain the output
This get function reference says that your overload is
Same as get(s, count, widen('\n'))
And that overload of the function reads until (among other things)
the next available input character c equals delim, as determined by Traits::eq(c, delim). This character is not extracted (unlike basic_istream::getline())
[Emphasis mine]
So the newline is left in the input buffer, for the getline call to read as an "empty" line.
If you want to read lines, I suggest you use std::string and std::getline (which does read, and throw away, the newline).
cin.get() grabs the newline character by default. It will not leave the newline in the stream.

Reading from a .txt file and looping until new line

I am having trouble understanding the output of my very little program which should read characters from a text file until it finds a new line.
It correctly outputs the characters and stops, but I don't understand why it still outputs the newline ('\n) character in the terminal and doesn't end before getting to it.
I know that I could use getline() or find another way but I would really understand the reason behind this behaviour.
Thank you in advance!
Edo
Code:
int main() {
std::ifstream in_file;
in_file.open("../responses.txt");
char c;
while(c != '\n'){
in_file.get(c);
std::cout << c << std::endl;
}
return 0;
}
Output:
A
B
C
D
E
Time elapsed: 000:00:000
The

Extract trailing int from string containing other characters

I have a problem in regards of extracting signed int from string in c++.
Assuming that i have a string of images1234, how can i extract the 1234 from the string without knowing the position of the last non numeric character in C++.
FYI, i have try stringstream as well as lexical_cast as suggested by others through the post but stringstream returns 0 while lexical_cast stopped working.
int main()
{
string virtuallive("Images1234");
//stringstream output(virtuallive.c_str());
//int i = stoi(virtuallive);
//stringstream output(virtuallive);
int i;
i = boost::lexical_cast<int>(virtuallive.c_str());
//output >> i;
cout << i << endl;
return 0;
}
How can i extract the 1234 from the string without knowing the position of the last non numeric character in C++?
You can't. But the position is not hard to find:
auto last_non_numeric = input.find_last_not_of("1234567890");
char* endp = &input[0];
if (last_non_numeric != std::string::npos)
endp += last_non_numeric + 1;
if (*endp) { /* FAILURE, no number on the end */ }
auto i = strtol(endp, &endp, 10);
if (*endp) {/* weird FAILURE, maybe the number was really HUGE and couldn't convert */}
Another possibility would be to put the string into a stringstream, then read the number from the stream (after imbuing the stream with a locale that classifies everything except digits as white space).
// First the desired facet:
struct digits_only: std::ctype<char> {
digits_only(): std::ctype<char>(get_table()) {}
static std::ctype_base::mask const* get_table() {
// everything is white-space:
static std::vector<std::ctype_base::mask>
rc(std::ctype<char>::table_size,std::ctype_base::space);
// except digits, which are digits
std::fill(&rc['0'], &rc['9'], std::ctype_base::digit);
// and '.', which we'll call punctuation:
rc['.'] = std::ctype_base::punct;
return &rc[0];
}
};
Then the code to read the data:
std::istringstream virtuallive("Images1234");
virtuallive.imbue(locale(locale(), new digits_only);
int number;
// Since we classify the letters as white space, the stream will ignore them.
// We can just read the number as if nothing else were there:
virtuallive >> number;
This technique is useful primarily when the stream contains a substantial amount of data, and you want all the data in that stream to be interpreted in the same way (e.g., only read numbers, regardless of what else it might contain).

8051 sentence and word counter

I found this code below on the internet which is suppose to count the sentences on an 8051 MCU.
Can someone please explain to me what is exactly happening where there are question marks.
Any kind of help would be highly appreciated.
#include<string.h>
char code *text=" what is a program? that has, a a lot of errors! When " ;
char code *text1=" you compile. this file, uVision. reports a number of? ";
char code *text2=" problems that you! may interactively correct. " ; //Null characters are also included in array!!!
void count ( char pdata* , char pdata*);
void main (void){
char pdata Nw,Ns;
char data TextNw[2],TextNs[2];
count(&Nw, &Ns); // call subroutine
TextNw[0]=Nw/10; //?????????????????????????????????
TextNw[1]=Nw%10; //?????????????????????????????????
TextNs[0]=Ns/10; //?????????????????????????????????
TextNs[1]=Ns%10; //?????????????????????????????????
while(1);
}
void count ( char pdata *Nw, char pdata *Ns ){
unsigned char N, i, ch;
typedef enum {idle1, idle2} state; //?????????????????????????????????
state S; // begining state
P2=0x00; // pdata bank definition it must be performed first!!
*Ns=*Nw=0; // without proper start-up there is no initialisation, initialise now!!
S=idle1; // beginning state
N=strlen(text)+strlen(text1)+strlen(text2)+3; //????????????? + 3 to acount 3 Null characters!
P2=0x00; // pdata bank definition
for(i=0;i!=N;i++){
ch=text[i]; // take a caharacter from the text
switch (S)
{
case (idle1):{
if (ch==0) break; // skip NULL terminating character!
if (ch!=' '){
S=idle2;
(*Nw)++;
}
break;
}
case(idle2):{
if (ch==0) break; // skip NULL terminating character!
if((ch==' ')||(ch==','))S=idle1;
else if ((ch=='?')||(ch=='.')||(ch=='!')){
S=idle1;
(*Ns)++;
}
break;
}
}
}
}
This program does 2 things in conjunction - counts number of sentences in the text and counts the number of words in the text. Once the counting is done, the results are stored in 2-char arrays. For example, for 57 words in 3 sentences the results will be stored as this: TextNw = {'5','7'} and TextNs = {'0','3'}.
The variable N contains the full length of the text with the addition of 3 null terminating characters (one per sentence).
The algorithm simultaneously counts words and sentences. In idle1 state the counting is in word-counting mode. In idle2 state the counting is in sentence-counting mode. The modes are interchanged according to current character being read - if delimiter is encountered, the appropriate counter is increased.

Resources