getline c++ problems with pipe overflow (?) - c++

I have made a simple program in c++ to read out a file
#include <string>
#include <iostream>
using namespace std;
int main()
{
string text;
getline(cin, text);
int textlength = 0;
textlength = text.length();
cout << text << endl;
cout << text[3] << endl;
cout << textlength << endl;
int number=0;
cout << "Enter a number: " << endl;
cin >> number;
}
So I compile this program in Win 8.1 pro + mingw and everything is okay. Next I start it by writing in cmd a.exe < sample.txt. The compiled program and the txt must be in the same folder.
sample.txt is a file with that text (some random letters, numbers etc.):
iuhuefusifsduifhsdiufhfdliuhfdslhfdiufhfdslihfsdui 6 rer4 r4 r4t 4t46 t 4t43t 00 00 002 " & %
Everything works fine until the point with the last cin. I cannot enter a number at that point because the entering process is skipped. I also tried to read out the text without the getline function. Instead I simply repeated a cin process and saved the progress one by one in a char. Worked fine until the cin command at the very end. It skipped that yet again.
And ideas how to solve that problem?

At that point, cin is still reading from your file sample.txt - and failing to read a number, because the getline has already read all the contents of the file.
Adding a second line to sample.txt would let you read a number (but beware that the error handling can get quite tricky if the input is not a number).

Related

Why does this code only recognize the first line in the text file? Inputting any number greater than 1 returns "Atomic Number Not Found"

I wanted to make a program that would have a user input a number, and it would search a text file I made on whether or not that number is an atomic number, then pull all the details from the periodic text file and display the info. However, when the user inputs any number greater than 1, it displays atomic number not found.
A solution I have tried is to make a for loop that would continuously go line by line until it finds it, but that did not work, and only made it display "atomic number not found" several times.
#include "pch.h"
#include <string>
#include <iomanip>
#include <iostream>
#include <fstream>
using namespace std;
int main() {
ifstream file_("periodicInfo.txt");
int atomNumReq;
cout << "Please enter atomic number: ";
cin >> atomNumReq;
if (file_.is_open())
{
string Symbol;
string Name;
int atomNum;
int mass;
char line;
while (file_ >> atomNum >> Symbol >> Name >> mass)
{
if (atomNumReq == atomNum) {
cout << atomNum << " " << Symbol << " " << Name << " " << mass << '\n';
}
else {
cout << "Atomic Number Not Found.";
}
}
file_.close();
}
return 0;
}
I expect it to display the line information for the atomic number. I have the text file arranged so that line 1 starts with the number 1, along with the text "1 H Hydrogen 1.01", line 2 of the file being "2 He Helium 4.00", etc all the way until the last atomic number. When the user inputs the number 1, it displays the first line in the text file correctly. When the user inputs any number greater than 1, it displays "Atomic Number Not Found."
1.01 is not an integral value, so file_ >> atomNum >> Symbol >> Name >> mass will read in the 1 into mass but will leave the .01 in the buffer; After that, probably everything is messed up.
Define mass as ...
double mass;
and things should get better.
Further, put the cout << "Atomic Number Not Found."; with some proper condition outside the loop; otherwise you'll get this message for every line that failed before you find the right one.
Fixed it by changing the mass to a double instead of an int. Another problem that showed up was it displaying "Atomic Number Not Found" for all the numbers previous to it. For example, if input was 3, it would display the error twice before displaying the third atomic number. To fix this, I put in a new if statement that solved the problem.
if (atomNumReq != atomNum) continue;

c++ object array string input is not working at console [duplicate]

This question already has answers here:
Why does std::getline() skip input after a formatted extraction?
(5 answers)
Using getline() in C++
(7 answers)
Closed 4 years ago.
Can anyone explain why I am having trouble with the below C++ code?
#include <iostream>
using namespace std;
class stud
{
public:
string name,adrs;
long long unsigned int mob;
};
int main()
{
stud s[10];
unsigned int num;
cout << endl << "Enter the number of students(<10): ";
cin >> num;
cout << endl;
for(int i = 0; i < num; i++)
{
cout << endl << "Enter student " << i+1 << " name(put '.' at end and press enter): ";
getline(cin, s[i].name); // this line skips some data before even they are
//entered and there is no error while compiling
}
system("CLS");
for(int i = 0; i < num; i++)
{
cout << endl << " Student " << i+1 << " name is: ";
cout << s[i].name << endl;
}
return 0;
}
When I try to input a string value for an object in the array as above, using getline() without any delimiter (which uses a new line by default), I don't get correct output since some other data is automatically being skipped.
But, when I use getline() as follows instead of above, it works fine, but it needs a delimiter at the end:
getline(cin, s[i].name, '.');
Please help me find a solution. I think the Enter key is pressed several times at one key press, and that's why the getline() skips some data. I'm not sure about this, though.
before correcting you program one thing to know is that
Actually, a newline is always appended to your input when you select Enter or Return when submitting from a terminal.
cin>> doesn't remove new lines from the buffer when the user presses Enter.
This has little to do with the input you provided yourself but rather with the default behaviour std::getline() exhibits. When you provided your input for the name (std::cin >> num;), you not only submitted the following characters, but also an implicit newline was appended to the stream, getline() mistakes this for user input along with enter.
It is recommended to use cin.ignore() to get rid of those extra characters after using cin>>(whatever) if you are going to use getline(cin,any string) later.
Edit this part of your code:
stud s[10];
unsigned int num;
cout << endl << "Enter the number of students(<10): ";
cin >> num;
cout << endl;
cin.ignore();//just add this line in your program after getting num value through cin
//fflush(stdin);
//cin.sync();
//getchar();
for(int i = 0; i < num; i++)
{
cout<<endl<< "Enter student " << i+1 << " name(put '.' at end and press enter): ";
getline(cin,s[i].name);
}
system("CLS");
you can use and may be tempted to use fflush(stdin) also but it is not recommended as it has undefined behaviour, as
According to the standard, fflush can only be used with output buffers, and obviously stdin isn't one.
about cin.sync():
using “cin.sync()” after the “cin” statement discards all that is left in buffer. Though “cin.sync()” does not work in all implementations (According to C++11 and above standards).
you can also use getchar() to get the newline caused by Enter

C++ File Output Garbage

this is giving me a wicked headache and was hoping I could find some help. The program is supposed to read in a program of 19 integers, then output the smallest (2nd integer) and largest (5th integer) to the screen. However, all my results yield garbage.
#include iostream>
#include <fstream>
#include <cstdlib>
using std::ifstream;
using std::ofstream;
using std::cout;
using std::endl;
//the goal of this program is to read in numbers from a file, then output the
//highest number and the lowest number to the screen
int main() {
ifstream fileInput;
int nOne, nTwo, nThree, nFour, nFive, nSix, nSeven, nEight, nNine, nTen, //there are 19 numbers in the file
nEleven, nTwelve, nThirteen, nFourteen, nFifteen, nSixteen, nSeventeen,
nEighteen, nNineteen;
cout << "Opening File" << endl;
fileInput.open("Lab12A.txt"); //the file is opened
if (fileInput.fail())
{
cout << "Input file opening failed. \n"; //the fail check doesnt pop up, so the file has been opened.
exit(1);
}
fileInput >> nOne >> nTwo >> nThree >> nFour >> nFive >> nSix >> nSeven >> nEight
>> nNine >> nTen >> nEleven >> nTwelve >> nThirteen >> nFourteen >> nFifteen //this is where they should be extracted
>> nSixteen >> nSeventeen >> nEighteen >> nNineteen;
cout << "The highest number is " << nTwo << endl;
cout << "The lowest number is " << nFive << endl;
fileInput.close();
system("pause");
return 0;
}
I wished to add only a comment but since I can't do that, I leave it as an answer.
I have copied your file and created a text file to try to reproduce your issue. At first everything went well (No issue at all). But with comment from Daniel Schepler, I changed file encoding to UTF8-BOM (You can do that easily from Notepad++ Encoding menu) and tried again. I got same values you posted. I can't give more explanation to exactly how values are to be interpreted but I wish someone with more experience enlighten us here.
First I wanted to thank everyone who looked at and commented on this I greatly appreciate it, the issue was ultimately pinned down to needing a full path to the .txt file as opposed to the relative path I initially posted. For what ever reason, my compiler couldn't recognize the file without it. Seems like a silly mistake but I'm relatively new to this so those are sure to squeak by. Thanks again everyone!
You can use class std::vector pushing the values then sorting the container and finally print the second and fifth elements:
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
int main(){
std::ifstream in("test.txt");
std::vector<int> vecInt;
int value;
while(in >> value)
vecInt.push_back(value);
in.close();
std::sort(vecInt.begin(), vecInt.end());
// second value is at index 1 and fifth value is at index 4
for(auto i(0); i != vecInt.size(); ++i)
if(i == 1 || i == 4)
std::cout << vecInt[i] << std::endl;
std::cout << std::endl << std::endl;
return 0;
}
I am not sure about what you mean with "largest fifth integer".

C++ Issue with cin and CTRL + Z

I'm reading c++ primer 5th and I have a little problem with an exercise:
Read a sequence of words from cin and store the values a vector. After
you’ve read all the words, process the vector and change each word to
uppercase. Print the transformed elements, eight words to a line.
My code is this:
#include <iostream>
#include <vector>
#include <string>
#include <cctype>
using std::vector;
using std::string;
using std::cin;
using std::cout;
using std::endl;
int main(){
vector<string> words;
string wordBuffer;
vector<string> output(1);
while (cin >> wordBuffer){
words.push_back(wordBuffer);
}
for (string &word : words){
for (char &letter : word){
letter = toupper(letter);
}
}
unsigned currentLine = 0;
for (decltype(words.size())index = 0; index < words.size(); ++index){
output[currentLine] += words[index] + " ";
if ((index+1) % 8 == 0){
++currentLine;
output.push_back("");
}
}
for (string s : output){
s[s.size() - 1] = 0; //removing the whitespace
cout << s << endl;
}
system("pause");
return 0;
}
Now, everything works well, but i have an issue with the input of the words by console.
If I write
I am writing a random words ^Z
and press Enter nothing happens. I have to rewrite the ^Z after I have pressed the Enter, like here:
I am writing a random words
^Z
Can you expain me why? Thanks!
PS: I'm saying that because in my previous programs writing ^Z in the same line worked fine. Like in this code:
#include <iostream>;
int main(){
int currval = 0,val = 0;
int count = 1;
while (std::cin >> val){
if (currval == val){
++count;
}
else {
std::cout << "The number " << currval << " appears " << count << " times" << std::endl;
currval = val;
count = 1;
}
}
std::cout << "The number " << currval << " appears " << count << " times" << std::endl;
system("pause");
return 0;
}
I can't figure out why :(
The ^Z has to be first in order for Windows to treat it as Ctrl+Z, otherwise it is just treated as meaningless characters.
If you would like it to work like you wrote i'd suggest:
String wordBuffer("")
while (strcmp(wordBuffer[strlen(wordBuffer)-3], "^Z") != 0){
words.push_back(wordBuffer);
cin >> wordBuffer
}
EDIT: in your second example it works because when you read integers c++ knows to divide the given string of numbers in the space (or ENTER if the numbers are entered separately in every line) to read every number separately so if you'll enter:
123 2323 4545 43 ^Z
It will read 123, then 2323, ... and then ^Z and so it will be as though it got it in a separate line but when you read string, it cant do that because a string contain every symbol and so it separate the input in the ENTER pressed and that why the second one works
As far as I know Ctrl+Z is placed in the keyboard buffer before any other entered symbols. Thus any entered characters before Ctrl+Z will be discarded. You need to do the following
I am writing a random words ENTER
^Z ENTER

How do you get a file in C++?

So the teacher has posed this assignment:
You have been hired by the United Network Command for Law Enforcement, and you have been given files containing null cyphers you have to decrypt.
So for the first file given (as an example), every other letter is correct (ie: 'hielqlpo' is hello (assuming you start with the first letter). My first question is, how do I read in a file? The document is on my desktop in a folder and the file is named document01.cry. I'm not sure the command I need to put that file into the program.
I'm also not overly sure how to grab a letter and skip a letter, but honestly I want to tinker with that before I post that question! So for now...my question is as stated in the title: How do you grab a file for reading in C++?
If it makes a difference (As I'm sure it does), I'm using Visual C++ 2008 Express Edition (because it's free and I like it! I've also attached what I have so far, please keep in mind it's -very- basic...and I added the getchar(); at the end so when it does run properly, the window stays open so I can see it (as Visual Express tends to close the window as soon as it's done running.)
The code so far:
#include<iostream>
using namespace std;
int main()
{
while (! cin.eof())
{
int c = cin.get() ;
cout.put(c) ;
}
getchar();
}
PS: I realize that this code grabs and puts out every character. For now that's fine, once I can read in the file I think I can tinker with it from there. I'm also poking at a book or two I have on C++ to see it anything pops up and screams "Pick me!" Thanks again!
EDIT:: Also curious, is there a way to input the file you want?
(I.e.:
char filename;
cout << "Please make sure the document is in the same file as the program, thank you!" << endl << "Please input document name: " ;
cin >> filename;
cout << endl;
ifstream infile(filename, ios::in);
This code doesn't work. It shoots back an error saying the char can't be converted to a const char *. How can this problem be fixed?
EDIT 2:
Never mind about said part 2, I found it out! Thanks again for the assistance!
To do file operations, you need the correct include:
#include <fstream>
Then, in your main function, you can open a file stream:
ifstream inFile( "filename.txt", ios::in );
or, for output:
ofstream outFile( "filename.txt", ios::out );
You can then use inFile as you would use cin, and outFile as you would use cout. To close the file when you are done:
inFile.close();
outFile.close();
[EDIT] include support for command line arguments
[EDIT] Fixed possible memory leak
[EDIT] Fixed a missing reference
#include <fstream>
#include <iostream>
using namespace std;
int main(int argc, char *argv){
ifstream infh; // our file stream
char *buffer;
for(int c = 1; c < argc; c++){
infh.open(argv[c]);
//Error out if the file is not open
if(!infh){
cerr << "Could not open file: "<< argv[c] << endl;
continue;
}
//Get the length of the file
infh.seekg(0, ios::end);
int length = infh.tellg();
//reset the file pointer to the beginning
is.seekg(0, ios::beg);
//Create our buffer
buffer = new char[length];
// Read the entire file into the buffer
infd.read(buffer, length);
//Cycle through the buffer, outputting every other char
for(int i=0; i < length; i+= 2){
cout << buffer[i];
}
infh.close();
}
//Clean up
delete[] buffer;
return 0;
}
Should do the trick. If the file is extremely large, you probably shouldn't load the entire file into the buffer.
Although your queston has been answered, two little tips:
1) Instead of counting x and y to see if you are on an odd or even character you can do the following:
int count=0;
while(!infile.eof())
{
infile.get(letter);
count++;
if(count%2==0)
{
cout<<letter;
}
}
% essentially means 'remainder when divided by,' so 11%3 is two. in the above it gives odd or even.
2) Assuming you only need to run it on windows:
system("pause");
will make the window stay open when its finished running so you don't need the last getchar() call (you may have to #include<Windows.h> for that to work).
I figured it out! To be honest no one answer helped, it was a combination of the three, plus the comments from them. Thank you all very much! I've attached the code I used, as well as a copy of the document. The program reads in every character, then spits out the deciphered text. (IE: 1h.e0l/lqo is hello) The next step (extra credit) is to set it up so the user inputs how many characters to skip before reading in the next character to input.
This step I intend to do on my own, but again, thank you very much for all the assistance everyone! Proving once again how awesome this site is, one line of code at a time!
EDIT:: Code adjusted to accept user input, as well as allow for multiple uses without recompiling (I realize it looks like a huge sloppy mess, but that's why it's EXTREMELY commented...because in my mind it looks nice and neat)
#include<iostream>
#include<fstream> //used for reading/writing to files, ifstream could have been used, but used fstream for that 'just in case' feeling.
#include<string> //needed for the filename.
#include<stdio.h> //for goto statement
using namespace std;
int main()
{
program:
char choice; //lets user choose whether to do another document or not.
char letter; //used to track each character in the document.
int x = 1; //first counter for tracking correct letter.
int y = 1; //second counter (1 is used instead of 0 for ease of reading, 1 being the "first character").
int z; //third counter (used as a check to see if the first two counters are equal).
string filename; //allows for user to input the filename they wish to use.
cout << "Please make sure the document is in the same file as the program, thank you!" << endl << "Please input document name: " ;
cin >> filename; //getline(cin, filename);
cout << endl;
cout << "'Every nth character is good', what number is n?: ";
cin >> z; //user inputs the number at which the character is good. IE: every 5th character is good, they would input 5.
cout << endl;
z = z - 1; //by subtracting 1, you now have the number of characters you will be skipping, the one after those is the letter you want.
ifstream infile(filename.c_str()); //gets the filename provided, see below for incorrect input.
if(infile.is_open()) //checks to see if the file is opened.
{
while(!infile.eof()) //continues looping until the end of the file.
{
infile.get(letter); //gets the letters in the order that that they are in the file.
if (x == y) //checks to see if the counters match...
{
x++; //...if they do, adds 1 to the x counter.
}
else
{
if((x - y) == z) //for every nth character that is good, x - y = nth - 1.
{
cout << letter; //...if they don't, that means that character is one you want, so it prints that character.
y = x; //sets both counters equal to restart the process of counting.
}
else //only used when more than every other letter is garbage, continues adding 1 to the first
{ //counter until the first and second counters are equal.
x++;
}
}
}
cout << endl << "Decryption complete...if unreadable, please check to see if your input key was correct then try again." << endl;
infile.close();
cout << "Do you wish to try again? Please press y then enter if yes (case senstive).";
cin >> choice;
if(choice == 'y')
{
goto program;
}
}
else //this prints out and program is skipped in case an incorrect file name is used.
{
cout << "Unable to open file, please make sure the filename is correct and that you typed in the extension" << endl;
cout << "IE:" << " filename.txt" << endl;
cout << "You input: " << filename << endl;
cout << "Do you wish to try again? Please press y then enter if yes (case senstive)." ;
cin >> choice;
if(choice == 'y')
{
goto program;
}
}
getchar(); //because I use visual C++ express.
}
EDIT:::
I tried inserting the text, but I couldn't get it to come out right, it kept treating some of the characters like coding (ie an apostrophe apparently is the equivalent of the bold command), but you could just try putting in "0h1e.l9lao" without the parenthesis into a .txt and it should give the same outcome.
Thanks again everyone for the help!