I have problem with the following code:
#include<iostream>
using namespace std;
int main()
{
char a[200];
int i;
for (i = 0; cin.get() != '\n'; i++) {
cin >> a[i];
}
cout << i;
system("pause");
return 0;
}
I don't know why when i input without space 10 char for example. i si equal to 10/2=5 ?
You discard every odd symbol, cin.get() read symbol 1,
cin >> read symbol two, and again cin.get() read symbol 3,
and cin >> read symbol 4 from standard input.
You are throwing out half of your cin results.
When you use cin, a character is read, but you are not assigning it to anything inside the for loop criteria; only inside the loop body are you saving it.
Inside the loop, you read in another character (after the one you already read in during the loop's test criteria) and assign that one. The loop repeats, and the next character read is again thrown away with the line cin.get() != '\n' because you are not assigning the results to anything. And this continues, alternating characters you throw away with characters you "save" into the array.
You get two characters, once increment i variable and only second of them insert in array
int main()
{
char a[200];
int i;
\\ cin.get() - get one char and insert it in a[i]
\\ after that, compare this value with '\n'
\\ if equal, break the loop, if different, continue
for (i = 0; (a[i] = cin.get()) != '\n'; i++);
\\ last character ('\n') should be replaced with '\0'
a[i]='\0';
cout << i;
system("pause");
return 0;
}
while solution:
int main()
{
char a[200];
int i=0;
cin >> a[i];
while (a[i] != '\n')
{
i++;
cin >> a[i];
}
a[i]='\0';
cout << i;
system("pause");
return 0;
}
do - while solution:
int main()
{
char a[200];
int i=0;
do
{
cin >> a[i];
}
while(a[i++]!='\n');
a[i-1]='\0';
cout << i-1;
system("pause");
return 0;
}
As a matter of fact, you are reading the standard input (std::cin) in two different ways, storing its output only once every two character extractions.
std::basic_istream::get (cin.get()) extracts character or characters from stream. Once extracted, whey are forgotten, sent to limbo. You simply ignore them. Which is not what I suspect you want to do.
std::basic_istream::operator>> (cin >> ...) also extracts character or characters (following the type of the right hand side operand).
So, with an input of ten characters, you ignore five of them in your for condition check and store five in the loop block.
A correct way to read the characters would be to use std::getline (en.cppreference.com/w/cpp/string/basic_string/getline):
std::string input;
std::getline(cin, input);
std::cout << input << std::endl;
This example code will simply read a line and output it, verbatim, in the standart output.
Related
My program is to read characters into an array and display it to the console. But I don't know why it only reads first 3 characters.
#include <iostream>
using namespace std;
int main() {
int length=0,i;
char str[10];
cout<<"Enter a string"<<"\n";
for(i=0; str[i] != '\0'; i++) {
cin>>str[i];
}
for(int i=0; str[i]!='\0'; i++) {
cout<<str[i];
length++;
}
cout<<"\n"<<"Length of the string="<<""<<length<<"\n";
}
The output looks like:
Here are some of the issues I noticed:
You're checking the contents of str before you even initialize it.
You're assuming the string you're fetching from the stream will be null-terminated, but that's actually not the case.
You aren't checking whether cin is working correctly
You don't check to make sure the string is 10 characters or less, this could cause you to overflow past the end of the buffer
When you're checking the length of the array, again you assume the string is null-terminated
If you want to fix these issues and still use a char buffer, see user4581301's comprehensive answer. However, I'd suggest simply switching to std::string. For example:
#include<iostream>
using namespace std;
int main()
{
string str;
cout<<"Enter a string"<<"\n";
if (cin >> str) {
cout << str << endl;
cout << "Length of the string = " << str.length() << endl;
}
}
TL;DR version
std::string str; //use std::string. practically no reasons not to in C++
if (cin >> str) // read into string and test that read succeeded.
{
std::cout << str << '\n'
<< "Length of the string=" << str.length() << endl;
}
Explaining and salvaging Asker's version
for(i=0; str[i] != '\0'; i++){ // str[i] tested here
cin>>str[i]; // but it has no assigned value until here.
uses str[i] before it is assigned a value. The program likely found a null character in the block of memory allocated for str and stopped prematurely, but technically anything can happen if you use an uninitialized variable. For example, you got the expected result 3 times before finding the null. The program could never found a null and run forever. It could have rained unicorns. Anything.
int i = 0;
do {
cin>>str[i];
} while (str[i++] != '\0');
reads then tests. But lines of data in a stream are not C-style strings and are not terminated with null.
int i = 0;
do {
cin>>str[i];
} while (!std::isspace(str[i++]));
exits when whitespace is found, typically signalling the end of a word, rather than null.
But what if cin>>str[i]; failed for some reason?
int i = 0;
do {
cin>>str[i];
} while (cin && !std::isspace(str[i++]));
Adds a test to ensure something was read. But what if there are more than 10 characters and char str[10]; is overflowed?
int i = 0;
do {
cin>>str[i];
} while (cin && !std::isspace(str[i]) && ++i < sizeof(str));
unless I am reading That is legal unless I'm reading [expr.cond] and [expr.log.and] wrong, sequencing of when ++i occurs in !std::isspace(str[i]) && ++i < sizeof(str)) is guaranteed to not affect !std::isspace(str[i])
But what if you run out of space before find the null? str is unterminated and not a string! This ruins the for loop later in the program.
int i = 0;
do {
cin>>str[i];
} while (cin && !std::isspace(str[i]) && ++i < sizeof(str));
if (i == sizeof(str))
{
str[sizeof(str)-1] = '\0';
}
I think that covers everything you're likely to run into here.
You read in character by character and store it in str[i]; but then you increment i++ before checking str[i]!='\0'.
There are two issues with this approach: First, you check a value at a position that has not been written at that point in time. Second, cin>>str[i] will never write the string termination character - it just reads in valid characters, and if input is terminated (e.g. by EOF), nothing is written.
So you are approaching this the wrong way.
If you want to read at most 10 characters up to a new line (i.e. when the user presses enter), use fgets. Or - and this is the preferred option - use cin and write into an std::string-object.
int main()
{
std::string str;
cin >> str;
std::cout << str << std::endl;
}
str[i] != '\0' checks the pre-existing data stored at str[i], not the user-input value.
Add string initialization:
char str[10] = {'\0'};
and change the reading with:
char c;
for(int i = 0; cin>> c && c!=/*add your termination cond. here*/ && i < 10;++i)
str[i] = c;
So you can ensure that the string is filled with correct values and terminated appropriately.
But better solution would be to use std::string. In that case you dont have to check the sizes, because the string grows by itself.For example:
std::string str;
for(char c; cin>>c && c!=/*add your termination cond. here*/;)
str += c;
I am quite new in c++ and programming so sorry in advance in my question repeats. I have a text file of 3 lines:
7
00000000000000000000000*0000
0 0 0 R 0
What I need to do is read 2nd line and write it into an array as char. But I must not include 3rd line because it will go to a completely different matrix. My code so far :
ifstream input;
input.open("input1.txt");
input >> start;
char a=0;
string line;
while (getline(input, line))
{
a=0;
istringstream iss(line);
int length = line.size();
for (int i=0; i<length; i++)
{
iss >> a;
A[i] = a;
cout << A[i] << " " << i << endl;
}
}
input.close();
However, with this code it always starts new array for 3rd line. What am I doing wrong? What is the easiest way to fix it? Thank you.
-----------------------------Update--------------------------------------
I have modified the code but it still does not work properly. I am getting this kind of result : 5)-└ instead of correct one. My current code:
void Read(int &numLines, int &start, vector<char>&A, char B[][5])
{
ifstream input;
input.open("input.txt");
input >> start;
input.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
string line;
if(getline(input, line))
{
for(char temp: line)
{
A.push_back(temp);
}
}
input.close();
}
A here is a vector I want to write 2nd line to, char by char
Start is just an integer in which I am storing 1st line (7)
Thank you very much for advices
Mixing >> and std::getline is non-trivial. For example, after input >> start; the end of line marker is left in the stream in case it's still needed. In your case it isn't, and it is picked off by the subsequent call to getline, resulting in a read of an empty line.
This is what's complicating your read of line and forcing the while loop and test for empty lines.
Step through your program with your development environment's debugger and you'll see what I'm talking about. Get used to using the debugger. It's possibly the best programming productivity tool you'll ever encounter.
The easiest way to fix it is to place
input.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
after
input >> start;
to eat up the end of the line (and anything else that might be on that line. This needs the addition of #include<limits> to get std::numeric_limits<std::streamsize>::max.
Then you can remove the while loop and replace it with
if (getline(input, line))
No loop, not chance of consuming multiple lines from the file. And the logic for reading and processing the third line can follow.
Side note: instead of that for loop, consider
int i = 0;
while (iss >> a)
{
A[i] = a;
cout << A[i] << " " << i << endl;
i++;
}
This will march through iss until it hits the end of the line. You can also throw iss out entirely and just read the characters directly out of line.
int i = 0;
for(char temp: line)
{
A[i] = temp;
}
And A should probably be a vector if it isn't already to reduce the chances of buffer overruns.
for(char temp: line)
{
A.push_back(temp);
}
I would go with something like this:
std::string start;
std::string Astring;
ifstream input;
input.open("input.txt");
input >> start;
input >> Astring;
// If you really want a char array
char * A = new char[Astring.size()];
for (unsigned int i = 0; i < Astring.size(); i++) {
A[i] = Astring[i];
}
// Don't forget to delete after use
delete[] A;
Moreover, if you just need the char array as an input to something else later, you can call Astring.c_str() instead of that for loop, which returns a C-style char array.
When I enter "111 111" and then press enter, the output shows nothing. Then when I press enter twice, the expected output appears. Why is that?
#include<iostream>
using namespace std;
int main()
{
char seq[10];
//initialize the sequence
for (int i = 0; i<10; i++)
{
seq[i] = ' ';
}
//read characters from the keyboard
for (int i = 0; i<10; i++)
{
cin.get(seq[i]);
if (seq[i] == '\0')
{
break;
}
}
//the output should be the sequence of characters
//users typed before
cout << seq;
system("pause");
return 0;
}
You can use header file string instead, which provides more flexibility like below:
#include<iostream>
#include<string>
using namespace std;
int main()
{
string seq;
//initialize the sequence
//read characters from the keyboard
getline(cin,seq);
//the output should be the sequence of characters
//users typed before
cout << seq;
system("pause");
return 0;
}
In response to OP's question update:
In the described case, You never inputting \0 from standard input, right? Rather you are pressing enter key.
if (seq[i] == '\0'){
Instead, you can replace this checking line with:
if (seq[i] == '\n'){
You can provide std::getline() with an additional char parameter, that defines the line-delimiter. In your case, simply let it read to the next '\0'.
auto seq = std::string{};
std::getline(cin, seq, '\0');
BTW.: are you really sure, you want to read to the next '\0'? It is not too easy to enter a zero character with the keyboard. If you actually are interested in a complete line from the input, just drop the delimiter parameter: std::getline(cin, seq).
This code:
for (int i = 0; i<10; i++){
seq[i] = ' ';
}
initializes all elements in seq to spaces, not '\0'. I don't think your break statement will trigger therefore.
Your program reads 10 characters before it does anything else. So you need to provide 10 characters.
The break check never triggers. why would it.
Finally, cout << seq is not safe, as it may read memory past the end of seq.
Ok, I'm trying to get good at using pointers so I'm trying to write a input validation for the user input to make sure that anything that isn't a number is handled correctly. When I use isdigit() isn't working for me. I still get an exception when I enter a alphabet. Any suggestions? Thanks. Check this out:
#include<iostream>
#include<algorithm>
#include<string>
#include<cctype>
using namespace std;
void EnterNumbers(int * , int);
int main()
{
int input = 0;
int *myArray;
cout << "Please enter the number of test scores\n\n";
cin >> input;
//Allocate Array
myArray = new int[input];
EnterNumbers(myArray,input);
delete[] myArray;
return 0;
}
void EnterNumbers(int *arr, int input)
{
for(int count = 0; count < input; count++)
{
cout << "\n\n Enter Grade Number " << count + 1 << "\t";
cin >> arr[count];
if(!isdigit(arr[count]))
{
cout << "Not a number";
}
}
}
If you test if (!(cin >> arr[count])) ... instead - isdigit(arr[digit]) tests if the value of arr[digit] is the ASCII code of a digit [or possibly matches Japanese, Chinese or Arabic (that is, as an Arabic script typeface, not that it's a 0-9 like our "Arabic" ones) digit]. So if you type in 48 to 57, it will say it's OK, but if you type 6 or 345, it's complaining that it is not a digit...
Once you have discovered a non-digit, you will also need to either exit or clean out the input buffer from "garbage". cin.ignore(1000, '\n'); will read up to the next newline or a 1000 characters, whichever happens first. Could get annoying if someone has typed in a million digits, but otherwise, should solve the problem.
You will of course also need a loop to read the number again, until a valid number is entered.
The way I do this kind of input validation is that I use std::getline(std::cin, str) to get the whole line of input and then I parse it using the following code:
std::istringstream iss(str);
std::string word;
// Read a single "word" out of the input line.
if (! (iss >> word))
return false;
// Following extraction of a character should fail
// because there should only be a single "word".
char ch;
if (iss >> ch)
return false;
// Try to interpret the "word" as a number.
// Seek back to the start of stream.
iss.clear ();
iss.seekg (0);
assert (iss);
// Extract value.
long lval;
iss >> lval;
// The extraction should be successful and
// following extraction of a characters should fail.
result = !! iss && ! (iss >> ch);
// When the extraction was a success then result is true.
return result;
isdigit() applies to char not to int as you're trying. The cin >> arr[count]; statement already ensures an integer numeric digits format is given in the input. Check cin.good() (!cin respectively) for possible input parsing errors.
Say we have a code:
int main()
{
char a[10];
for(int i = 0; i < 10; i++)
{
cin>>a[i];
if(a[i] == ' ')
cout<<"It is a space!!!"<<endl;
}
return 0;
}
How to cin a Space symbol from standard input? If you write space, program ignores! :(
Is there any combination of symbols (e.g. '\s' or something like this) that means "Space" that I can use from standard input for my code?
It skips all whitespace (spaces, tabs, new lines, etc.) by default. You can either change its behavior, or use a slightly different mechanism. To change its behavior, use the manipulator noskipws, as follows:
cin >> noskipws >> a[i];
But, since you seem like you want to look at the individual characters, I'd suggest using get, like this prior to your loop
cin.get( a, n );
Note: get will stop retrieving chars from the stream if it either finds a newline char (\n) or after n-1 chars. It stops early so that it can append the null character (\0) to the array. You can read more about the istream interface here.
#include <iostream>
#include <string>
int main()
{
std::string a;
std::getline(std::cin,a);
for(std::string::size_type i = 0; i < a.size(); ++i)
{
if(a[i] == ' ')
std::cout<<"It is a space!!!"<<std::endl;
}
return 0;
}
To input AN ENTIRE LINE containing lot of spaces you can use getline(cin,string_variable);
eg:
string input;
getline(cin, input);
This format captures all the spaces in the sentence untill return is pressed
Use cin.get() to read the next character.
However, for this problem, it is very inefficient to read a character at a time. Use the istream::read() instead.
int main()
{
char a[10];
cin.read(a, sizeof(a));
for(int i = 0; i < 10; i++)
{
if(a[i] == ' ')
cout<<"It is a space!!!"<<<endl;
}
return 0;
}
And use == to check equality, not =.
Using cin's >> operator will drop leading whitespace and stop input at the first trailing whitespace. To grab an entire line of input, including spaces, try cin.getline(). To grab one character at a time, you can use cin.get().
I thought I'd share the answer that worked for me. The previous line ended in a newline, so most of these answers by themselves didn't work. This did:
string title;
do {
getline(cin, title);
} while (title.length() < 2);
That was assuming the input is always at least 2 characters long, which worked for my situation. You could also try simply comparing it to the string "\n".
Try this all four way to take input with space :)
#include<iostream>
#include<stdio.h>
using namespace std;
void dinput(char *a)
{
for(int i=0;; i++)
{
cin >> noskipws >> a[i];
if(a[i]=='\n')
{
a[i]='\0';
break;
}
}
}
void input(char *a)
{
//cout<<"\nInput string: ";
for(int i=0;; i++)
{
*(a+i*sizeof(char))=getchar();
if(*(a+i*sizeof(char))=='\n')
{
*(a+i*sizeof(char))='\0';
break;
}
}
}
int main()
{
char a[20];
cout<<"\n1st method\n";
input(a);
cout<<a;
cout<<"\n2nd method\n";
cin.get(a,10);
cout<<a;
cout<<"\n3rd method\n";
cin.sync();
cin.getline(a,sizeof(a));
cout<<a;
cout<<"\n4th method\n";
dinput(a);
cout<<a;
return 0;
}
I have the same problem and I just used cin.getline(input,300);.
noskipws and cin.get() sometimes are not easy to use. Since you have the right size of your array try using cin.getline() which does not care about any character and read the whole line in specified character count.