How to fix the random character outputs in C++? - 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];
}
}

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).

Reading a Text file and Storing data in 2D Array in C++

Basically, I'm reading a file and trying to store the data in a 2D, for the differentiation between rows and columns I use the logic below:
int rows=0,column=0;
char arr[50][50];
while(my_file.eof()==0){
my_file.get(ch);
if(ch=='\n'){
rows++;
}
arr[rows][column]=ch;
column++;
}
for(int j=0;j<rows;j++){
for(int k=0;k<column;k++){
cout<<arr[j][k];}
}
But the when I run It shows the following output: https://i.stack.imgur.com/XzhST.png
And the text file data is:
I am going to school
hi!
Hello
guide me a bit...
Hmm, a 2D char array can indeed be used to store an number of lines, but you should control that you never try to store more than 50 characters for a single line, and that you never try to ouput more characters for a line than what it initially contained.
Here is a minimal fix of your code:
int rows = 0, column = 0;
char arr[50][50] = { {0 } }; // ensure the array is initialized with '\0' chars
for (;;) {
my_file.get(ch);
if (!my_file) break; // eof shall be tested AFTER a read operation
if (ch == '\n') {
rows++;
if (rows == 50) break; // no more than 50 lines
column = 0; // reset column index for next line
}
else if (column < 50) { // no more than 50 columns
arr[rows][column] = ch;
column++;
}
}
for (int j = 0; j < rows; j++) {
for (int k = 0; k < 50; k++) {
if (arr[j][k] == 0) break; // stop on end of line
std::cout << arr[j][k];
}
std::cout << '\n'; // and display the end of line
}
And as you have been said this is rather C-ish... I assume it is only for learning how 2D arrays can work.
As pointed out in comments, you'd be much better off using a std::vectorstd::string to store the strings.
But, this looks like a homework assignment to read then print each byte separately, so let's have a look... I'll add one of the ways this is usually done at the end of this post.
Your output looks like this:
It looks like you are displaying characters beyond the bondary of the strings, or that your strings are not null terminated... Turns out it's both.
Your code:
int rows = 0, column = 0;
char arr[50][50]; // <-- your array is not initialized, while that is not
// a big issue, filling the array with zeroes is easy:
// char arr[50][50] = {};
while (my_file.eof() == 0) {
my_file.get(ch);
if (ch == '\n') {
rows++; // <-- you pass to the next string, but do not put a
// null character to properly terminate your strings
// while this could have been avoided by initializing
// the array, it's best to do it explicitely.
// replace above line contents by:
arr[row][column] = '\0';
if (++row >= 50) // consider using named constants for the size of your array.
break; // No use keeping on reading strings if there is no
// more room to store them
}
arr[rows][column] = ch; // <-- I suspect a bunch un undefined stuff will
// start happening when column >= 50
column++;
// Try replacing above code with:
if (column < 50) // consider using named constants for the size of your array.
arr[rows][column++] = ch;
}
// make sure the last string is null terminated.
if (row < 50 && column < 50)
arr[row][column] = '\0';
// note that strings that are 50 bytes long are NOT null terminated.
// that's important to keep in mind, and only workss because we'll print
// byte by byte.
// your original print routine prints out all characters in the array, even
// stuff that was not in the original file...
for (int j = 0; j < rows; ++j){
for (int k=0 ; k < column; ++k){ // <-- you need to check for a null
// terminating character here...
// also, column is the length of the last
// string in the array. This is not a very
// useful value for displaying any other
// strings, is it?
// try this:
for (int k = 0; k < 50 && arr[j][k] != '\0'; ++k)
cout << arr[j][k];
}
cout << '\n'; // insert a newline after each string.
}
As you can tell, this is overly complex for doing a very common operation... Here's a more concise way of doing the same thing:
#include <vector>
#include <string>
#include <iostream>
#include <fstream>
int main()
{
std::vector<std::string> arr;
std::ifstream ifs("testfile.txt");
while (ifs && !ifs.eof())
{
std::string str;
std::getline(ifs, str);
arr.push_back(str);
}
for (size_t i = 0; i < arr.size(); ++i)
std::cout << arr[i] << '\n';
return 0;
}
Because you haven't compile the array yet
char arr[50][50];
for (int r = 0; r < 50; r++){
for (int c = 0; c < 50; c++){
arr[r][c] = ' ';}
}

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

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).

Last word in a sentence is not printing after the sentence is reversed

When I am reversing a sentence, below code is unable to print the last word in the sentence after it is reversed.
#include "stdafx.h"
#include "conio.h"
#include <string.h>
#include <iostream>
using namespace std;
int main()
{
char sentence[80]={0};
cout<<"Input the string: ";
cin.getline(sentence,80,'\n');
int length=strlen(sentence);
int check=0;
for(int i=length; i>0; i--)
{
if(sentence[i]!=' ')
{
check++;
}
else
{
for(int j=i; j<(check+i); j++)
cout<<sentence[j+1];
cout<<" ";
check=0;
}
}
return 0;
}
If we enter the Sentence as "My Name is Rakesh" the output it is displaying as "Rakesh is Name". It is not displaying "My".
I have found two mistakes in your code.
Mistake # 01:
You are not iterating over the whole input. You are skipping the first index of the array because of the statement i>0.
Possible Solution:
You should change the condition of loop from i>0 to i>=0 in order to iterate the whole input.
Mistake # 02:
You are not checking the case of first word of the input, which is My in your case. You are printing the word in case the condition of sentence[i]!=' ' gets false so what if sentence[0] is not a space character then the statement check++ will be executed and then the loop will be terminated so the first word of input will not be printed.
Possible Solution:
You should handle this case either by printing the word outside the loop or by adding an if condition in the loop to print the word in case if i == 0 && sentence[i] != ' '. I have updated the code according to the first method and now it works fine.
Updated Code:
int i = 0;
for (i = length; i>=0; i--)
{
if (sentence[i] != ' ')
{
check++;
}
else
{
for (int j = i; j<(check + i); j++)
cout << sentence[j + 1];
cout << " ";
check = 0;
}
}
//Printing the missing word outside the loop
for (int j = i; j<(check + i); j++)
cout << sentence[j + 1];
Hope this helps.
Well,
for(int i=length; i>0; i--)
ends when i=1, and array index starts from 0, so that's ONE of problems here.
Change i>0 to i>=0.
If you begin and end your sentence with a space character it will work. You need to treat the space character and your end of string (null terminator) and your start of string as the same delimiter in this case, so you detect the start of the string, end of the string as well as the spaces in between
Try entering: " My Name is Rakesh " (with a space at the start and end)
to see the scope of your problem...Use a debugger to step through
(You indirectly manage the null termintor - by using strlen; and you capture all the space characters, but what do you do with the string remaining, that is the word delimited by being at the beginning of the String - at index 0)

C++ how make a 2D array using strings and spaces instead of ints

I am making a Sudoku program and my i have a test.txt file that reads
53__7____
6__195___
_98____6_
8___6___3
4__8_3__1
7___2___6
_6____28_
___419__5
____8__79
where the "_" are actually spaces. The reason i give you _ is so you can see that there are literally only 9 characters on each line.
I was thinking that I would have to do something like having GRID[row][column], however I frankly don't know what types I should put my arrays as and I am just lost.
I simply want to make it so when i want to output say GRID[0][0] it returns 5, while if i ask for GRID[0][3] it returns a ' '.
It is getting it so the array store both the numbers and the spaces is where i am getting completely lost
What I currently have tried so far:
int main()
{
ifstream myfile(test.txt);
string line;
char sudoku_grid[9][9];
if (myfile.is_open())
{
while(myfile.good())
{
getline(myfile, line);
cout << sudoku_grid[line] << endl;
}
myfile.close();
}
else cout << "error";
return 0;
}
it returns the error line 12: no match for 'operator [ ]' in 'sudoku_grid[line]'
Here is my attempt though guidelines through you guys:
int main()
{
ifstream myfile(test.txt);
string line;
char sudoku_grid[9][9];
if (myfile.good())
{
for(int i = 0; i < 9; i++)
{
getline(myfile, line);
for(int j = 0; j < 9; j++)
{
if (line[j] == ' ')
sudoku_grid[j][i] = -1;
else sudoku_grid[j][i] = line[i];
}
cout << sudoku_grid[i] << endl;
}
myfile.close();
}
else cout << "error";
return 0;
}
The result is a very awkward answer of strange letters and a new numbers.
I'll just give you the algorithm/logic, not going to write the code for you. Try it and come back when stuck.
Initialize output in memory 2D array: numbers[9][9]
Open the file
Until there is no line left in the file:
a. Get the line i
b. Until there are no more characters in the line:
b1. Get each character of the line c
b2. If the character is not space, then numbers[i]=c, else numbers[i]=-1
Your array can be made up of int and in b2 if a whitespace is encountered you can insert -1 to indicate the absence of a number. Of course your code manipulating numbers array needs to take that into account.
Since you need to store both chars and integer type values, use char. each of your integer lies in the range 0-9, so can be stored as a character.
char Grid[9][9];
now you can read each character from the string and store it in the array. It will not only keep your spaces intact but also each character. Always remember to use ASCII codes to access the elements of the grid. For 0-9, ASCII codes are 48-57, ASCII code for space is 32.
Hope it helps...
Edit code: Here is the simplest example... PLace your test file in d:, or edit the path of file in code
int main (void)
{
FILE *fp = fopen("d:\\test.txt","r");
char sudoku_grid[9][9], ch;
// I am assuming that file is valid and data in that is also valid
if(fp)
{
for(int i = 0; i < 9; i++)
{
for(int j = 0; j < 9; j++)
{
//too read each character
ch = fgetc(fp);
sudoku_grid[i][j] = ch;
}
// to read '\n' from the line
ch = fgetc(fp);
}
//for checking if data went correctly
for(int i = 0; i< 9;i++)
{
for(int j= 0; j<9;j++)
cout<<sudoku_grid[i][j];
cout<<endl;
}
}
return 0;
}
In the first code you get the error message because sudoku_grid can
only be indexed by numbers and not by strings.
In the second code the line
sudoku_grid[j][i] = line[i];
should probably be
sudoku_grid[j][i] = line[j];
Does this answer your question?