How should the cin.ignore() function be used in this code? - c++

My goal is to solve this:
Given a string S, of length N that is indexed from 0 to N-1, print its even-indexed and odd-indexed characters as 2 space-separated strings on a single line
int main() {
int test;
cin>>test;
for(int j = 0; j < test; j++){
char str[10000];
cin.ignore();
cin.getline(str,9999);
for( int i = 0; i < strlen(str); i++)
{
if(i % 2 == 0)
cout<<str[i];
}
cout <<" ";
for(int i = 0; i < strlen(str); i++)
{
if((i % 2 != 0))
cout<<str[i];
}
cout << endl;
}
return 0;
}
The above code gives me output as :
Hce akr
ak n
for the given input of:
2
Hacker
Rank
But when I use cin>>str instead of the cin.ignore() and cin.getline(), I get the correct expected output: How does that change the result?
Hce akr
Rn ak

You should Write cin.ignore(); before for loop . Your code ignoring first charecter of every string without first iteration. You need to ignore line break for only test not for every string .
see the below code :
int main() {
int test;
cin>>test;
cin.ignore();
for(int j = 0; j < test; j++){
char str[10000];
cin.getline(str,9999);
//cin>>str;
for( int i = 0; i < strlen(str); i++)
{
if(i % 2 == 0)
cout<<str[i];
}
cout <<" ";
for(int i = 0; i < strlen(str); i++)
{
if((i % 2 != 0))
cout<<str[i];
}
cout << endl;
}
return 0;
}
input :
5
Hacker
Rank
WoW
check
lastone
output :
Hce akr
Rn ak
WW o
cek hc
lsoe atn

Using ignore()+getline():
On the first loop iteration, cin.ignore() skips the line break that was left behind from cin>>test, then cin.getline() reads the entire line (Hacker) including but swallowing the line break.
On the second loop iteration, cin.ignore() skips the 1st character of the next line (R), and then cin.getline() reads the remaining characters of the same line (ank) including but swallowing the line break.
The solution is to move the call to cin.ignore() to above the loop:
cin>>test;
cin.ignore(numeric_limits<streamsize>::max(), '\n'); // <-- move here
for(int j = 0; j < test; j++){
char str[10000];
cin.getline(str,9999);
...
}
Using operator>>:
On the first loop iteration, cin>>str skips the line break that was left behind from cin>>test and then reads the next available word (Hacker).
On the second loop iteration, cin>>str skips the line break that was left behind from the previous cin>>str and then reads the next available word (Rank).

Related

For some reason, when i use getch() my program crash, but if i use cin, then it works

I would like to know what knowledge I lack about inputs of arrays. I want to input one character and then automatically go to the next line of the code.
Here is the code:
char word[21];
for(int i = 0;i < 21; i++)
{
word[i] = getch();
//cin>>word[i];
if(word[i] == '/')break;
}
for(int j = 0;j < strlen(word); j++ )
{
if(j < (strlen(word) - 1 ))cout<<word[j];
}
Here's how I would do this:
char c;
std::cin >> c; // Input the character.
std::cin.ignore(10000, '\n'); // Ignore remaining characters on the line.
You could replace 10000 with the maximum value for unsigned integers, but I just use an improbable large number (to fuel the improbability drive).

What can I use to stop a loop instead of 'return 0'?

so I made a simple loop that finds out if an array has the elements with the values of 0 and 1.
if the loop indeed finds 0 or 1 inside of the array, it will say "YES", otherwise "NO".
yes, the program works just fine, but at the end of the program it prints out "YES" or "NO" as many times as i put cin>>dim to.
for example if dim which means (dimension[of the array]) is 5 it's going to print either "YESYESYESYESYES" or "NONONONONO"
I have to use return 0 in order to make it print it out like once, but I feel like this is not the right way to do it. Please help me with this. thanks!
#include <bits/stdc++.h>
using namespace std;
int main()
{
int i, dim, v[100];
cin>>dim;
for(i=0;i<dim;i++)
cin>>v[i];
for(i=0;i<dim;i++)
if(v[i]==0 || v[i]==1){
cout<<"YES"; return 0;}
else{
cout<<"NO"; return 0;}
return 0;
}
The break statement can be used to break out of loops. The example from cppreference:
for (int j = 0; j < 2; j++) {
for (int k = 0; k < 5; k++) { //only this loop is affected by break
if (k == 2) break;
std::cout << j << k << " ";
}
}
As the comment suggests, break only breaks the innermost loop.
In your code you always exit from the loop on the very first iteration, hence you do not need the loop in the first place. This will have the same output as your code:
int main() {
int i, dim, v[100];
cin >> dim;
for(i=0; i < dim; i++)
cin >> v[i];
if(v[0] == 0 || v[0] == 1) {
cout << "YES";
} else {
cout << "NO";
}
}
After reading the question again...
I made a simple loop that finds out if an array has the elements with the values of 0 and 1
If you exit the loop after checking the first element then you only check the first element. If you want to see if an array contains only 1 or 0 or it contains at least one element which is 0 or 1 (not 100% clear which one you want), then you rather need this:
bool only_zero_or_one = true;
bool one_zero_or_one = false;
for (int i = 0; i < dim; ++i) {
zero_or_one = ( v[i] == 0 | v[i] == 1);
only_zero_or_one = zero_or_one && only_zero_or_one;
one_zero_or_one = zero_or_one || one_zero_or_one;
}
Only for one_zero_or_one you can break the loop once zero_or_one == true.
Moreover, you should rather use a std::vector. In your code, if the user enters a dim which is greater than 100 you write beyond the bounds of v. This can be avoided easily:
size_t dim;
std::cin >> dim;
// construct vector with dim elements
std::vector v(dim);
// read elements
for (size_t i=0; i < v.size(); ++i) std::cin >> v[i];
// .. or use range based for loop
for (auto& e : v) std::cin >> e;
but I feel like this is not the right way to do it
Returning is an entirely right way to break out from a loop.
Another right way is the break statement, which jumps to after the loop.
Even better, you can actually check if v[i]==0 or 1 inside the input for loop immediately after taking input and set a flag to true. Depending on requirement, you can either break or wait until the entire input is read and then come out and check for flag==true and then print "YES" and print "NO" if flag==false.
This will save you running the loop again to check for 0 or 1.

How to fix the random character outputs in C++?

When I get string input by using char arrays and I cycle through them with a for loop, my code always has random character outputs that should not be there.
I have tried debugging my code, by checking the output at various stages, but I can't find the reason for what is happening.
int k, s, counter = 0;
char word[21];
std::cin>>k;
std::cin.getline(word,21);
for (int i = 0; word[i] != ' '; i++)
{
s = 3*(i + 1) + k;
std::cout<<s;
for (int k = 0; k < s; k++)
{
word[i]--;
if (word[i] < 'A')
word[i] = 'Z';
}
std::cout<<word[i];
}
When I type in 3 to get the value of k, I already get the output "URORIFCFWOQNJCEBFVSPMJNKD" when I should not get any output.
The problem is that the buffer is not flushed before using getline.
Because of that when you hit enter after entering a number, that enter (character '\n') is passed to getline(), and at that point getline ends his work by leaving the word empty.
The solution to this is simple: Flush the buffer before getline.
Here is the complete solution:
#include <iostream>
int main() {
int k, s, counter = 0;
char word[21];
std::cin>>k;
// Clear the buffer
std::cin.clear();
while (std::cin.get() != '\n')
{
continue;
}
std::cin.getline(word,21);
std::cout<<"TEST>"<<word<<"<TEST"<<std::endl<<std::flush;
for (int i = 0; word[i] != ' '; i++)
{
s = 3*(i + 1) + k;
std::cout<<s;
for (int k = 0; k < s; k++)
{
word[i]--;
if (word[i] < 'A')
word[i] = 'Z';
}
// Use std::flush to forcefully print current output.
std::cout<<word[i]<<std::flush;
}
}
Notes:
I've used the buffer clearing mechanism described there. You might use another, but the idea is the same
If you comment the 4 lines of that buffer clearing part, you'll notice that as soon as you type "3" and hit enter, you see an output like "TEST><TEST" which means that the word inside it, is empty.
Consider using std::flush while using cout if you want forcefully print the output before the for cycle ends.
std::cin >> k; is reading an integer only. It does not read the trailing line break. The documentation of the >> operator says
The extraction stops if one of the following conditions are met:
a whitespace character [...] is found. The whitespace character is not extracted.
As Just Shadow pointed out this line break is causing the getline() call to return an empty string.
You can ignore any number of line breaks by calling
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
BTW: Looking at your outer for loop I would be concerned that you might read beyond the end of word if the string doesn't contain any whitespaces. The following solution fixes that as well:
#include <iostream>
#include <limits>
int main() {
int k, s, counter = 0;
char word[21];
std::cin >> k;
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
std::cin.getline(word, 21);
for (int i = 0; i < sizeof(word) && word[i] != ' '; i++)
{
s = 3 * (i + 1) + k;
std::cout<<s;
for (int k = 0; k < s; k++)
{
word[i]--;
if (word[i] < 'A')
word[i] = 'Z';
}
std::cout << word[i];
}
}

Filling up the vector with given input and searching a word on it later

Here, i am editing my question.
while (iter <= k && getline(input, line))
{
searchWord.clear();
int len = line.length();
if (len == 0) // getline function was not getting the third line. It was empty so. at 2-3 lines below. It was giving run time error because it was trying to access a vector's element fileed with empty string(line)
{
cout << count << " Words are Found:" << total_words << endl;
return 0;
}
for (int i = 0; i < len; i++)
{
ch1 = line.at(i);
searchWord.push_back(ch1);
}
for (int col = 1; col <= n; col++)
{
for (int row = 1; row <= n; row++)
{
if (mat[col][row] == searchWord[0]) // aranıalcak kelımenın boyutuna erisılene kadar harf harf matrix in ilk harfi ile aranan kelımenın ılk harfı sonra 2. harfı uyuyot mu dıye bakılacak bu loop un ıcıne spiral gitme algoritması yazılacak.
{
if (found(mat, searchWord, row, col)) // spiral arama loop u
{
count++;
for (int i = 0; i < searchWord.size(); i++) // if word is found add it to total words and afterwards leave a space.
{
total_words += searchWord[i];
}
total_words += " ";
}
}
}
}
row = 1;
iter++;
}
this code does not work for 3rd time .For example lets say this is our file contains these words seperated with only enter
EXAM
QUIZ
NOTFOUND
it gets exam and quiz perfectly and does eerything right. But it does not gets "NOTFOUND" in line at 3rd iteration of loop. So it does not enter the for loop at beginning and it crashes when it tries to reach outside of the searchWord vector.
What could be done ?
Firstly, I think this might be helpful to your problem
Secondly, in this line
mat[row][col] == ch;
you are comparing an element of matrix with ch
What you really just need to do:
mat[row][col] = ch;
It's a common mistake, so don't forget that comparison operator == is used only when you need to get a bool, and assignment operator = is, well, assignment to some variable.

c++ reading from beginning of file to a specified byte

Trying to write a file that reads from the first byte in a file to a byte specified by the user. I need help on the logic. If the file just has letters a through z and I just want to read and display the first 10, for example. here's a piece of what I wrote:
char byte;
inFile.seekg(0L,ios::beg);
inFile.get(byte);
cout << byte;
for(int i = 0; i < num; i++); //num is an int specified by the user.
{
inFile.seekg(1, ios::cur);
inFile.get(byte);
cout << byte;
}
First problem - the semi-colon on the end of the for() line:
for(int i = 0; i < num; i++);
{
...
}
What the compiler sees is actually this:
for(int i = 0; i < num; i++) { /* do nothing num times */ }
{
// code that will only run once
}
So, remove the semi-colon.
Next, if you're just reading bytes in succession, there's no need to seek in between each one. Just calling get() will get the next byte in the sequence. So remove the seekg() calls.
Final problem - this function is actually calling inFile.get() a total of num + 1 times. The first call is before the for loop. Then in the for loop, get() is called num times (ie. i = 0, 1, 2, 3 ... num-1). You can fix this either by changing the for loop counter to (i = 1; i < num; i++) or just removing the get() call before the for loop. In the code below I've chosen the second way:
void run(int num, istream &inFile)
{
char byte;
for(int i = 0; i < num; i++)
{
inFile.get(byte);
cout << byte;
}
}