C++ Cin input to array - c++

I am a beginner in c++ and I want to enter a string as character by character into an array , so that I can implement a reverse function .. However unlike C when the enter is hit a '\n' is not insterted in the stream.. how can I stop data from being entered ?
my code is :
#include<iostream>
#include<array>
#define SIZE 100
using namespace std;
char *reverse(char *s)
{
array<char, SIZE>b;
int c=0;
for(int i =(SIZE-1);i>=0;i--){
b[i] = s[c];
c++;
}
return s;
}
int main()
{
cout<<"Please insert a string"<<endl;
char a[SIZE];
int i=0;
do{
cin>>a[i];
i++;
}while(a[i-1]!= '\0');
reverse(a);
return 0;
}

When you read character by character, it really reads characters, and newline is considered a white-space character.
Also the array will never be terminated as a C-style string, that's not how reading characters work. That means your loop condition is wrong.
To begin with I suggest you start using std::string for your strings. You can still read character by character. To continue you need to actually check what characters you read, and end reading once you read a newline.
Lastly, your reverse function does not work. First of all the loop itself is wrong, secondly you return the pointer to the original string, not the "reversed" array.
To help you with the reading it could be done something like
std::string str;
while (true)
{
char ch;
std::cin >> ch;
if (ch == '\n')
{
break; // End loop
}
str += ch; // Append character to string
}
Do note that not much of this is really needed as shown in the answer by Stack Danny. Even my code above could be simplified while still reading one character at a time.

Since you tagged your question as C++ (and not C) why not actually solve it with the modern C++ headers (that do exactly what you want, are tested, save and work really fast (rather than own functions))?
#include <string>
#include <algorithm>
#include <iostream>
int main(){
std::string str;
std::cout << "Enter a string: ";
std::getline(std::cin, str);
std::reverse(str.begin(), str.end());
std::cout << str << std::endl;
return 0;
}
output:
Enter a string: Hello Test 4321
1234 tseT olleH

Related

Strange things with c++ string input

#include <iostream>
#include <cstring>
using namespace std;
const int BUFFER_SIZE = 80;
void getstr(char* &str);
int main()
{
char* str;
while(true)
{
getstr(str);
if (!strlen(str))
break;
}
delete [] str;
return 0;
}
void getstr(char* &str)
{
char temp[BUFFER_SIZE];
cout<<"Enter a string(empty line to quit): ";
cin.get(temp, BUFFER_SIZE);
while(cin.get()!='\n')
continue;
str = new char [strlen(temp)+1];
strcpy(str, temp);
}
I have a string reading loop above and entering an empty line to terminate the loop doesn't work(after entering an empty line program stops responding to any input). But when I replace a loop in getstr with single cin.get() all works fine. What's wrong?
istream::get() sets failbit when empty string is read.
This makes cin.get() return EOF and this because you couldn't break the loop while(cin.get()!='\n').
You can use ios::clear() to clear failbit.
cin.get(temp, BUFFER_SIZE);
cin.clear(); // add this
while(cin.get()!='\n')
continue;
cin.get(char* s, size_t n) Extracts characters from the stream and stores them in s as a c-string, until either (n-1) characters have been extracted or the delimiting character is encountered: the delimiting character being either the newline character ('\n') or delim (if this argument is specified).
The delimiting character is not extracted from the input sequence if found and remains there as the next character to be extracted from the stream (see getline for an alternative that does discard the delimiting character).
A null character ('\0') is automatically appended to the written sequence if n is greater than zero, even if an empty string is extracted.
So here is the problem. cin.get() need to read at least 1 character. You can close stdin by pressing Ctrl+D and Enter, after that, your program will be finished.
And BTW, you are using new N times, but you have only 1 delete. You need to delete the previous buffer
If you are going to use C++, you should really use cin/cout in an objectively consistent manner. For example:
string name;
cout << "What is your name: ";
getline (cin, name);
cout << "Your name is: " << name;
What you are doing is kind of a C/C++ hybrid (char arrays in leu of string objects, but using std namespace).
Now, I know this isn't your question, but what you are doing right now is slightly unorthodox which makes answering your question a bit difficult without putting the code in to and editor and debugging it.
Given the c++11 tag, I assume that you really want C++ code. The great thing is that C++ simplifies this a lot.
#include <iostream>
#include <string>
int main()
{
std::string str;
while(std::getline(std::cin, str) && !str.empty())
{
// do stuff
}
return 0;
}

C++ "Same Letter" code doesn't work properly

#include <iostream>
#include <string>
using namespace std;
static char sentence[100];
void sameletter(char sentence[100])
{
int meter=0;
char letter;
cout<<"Enter the letter you want to find in this sentence : ";
cin>>letter;
for(int i=0; sentence[i] != '\0'; i++)
{
if(sentence[i]==letter)
{
meter++;
}
}
cout<<letter<<" letter used "<<meter<<" time(s)."<<endl;
}
int main()
{
cout<<"Enter Sentence : ";
cin>>sentence[100];
gets(sentence);
sameletter(sentence);
}
This is code i wrote. But for some reason it never includes the first letter to the end result. For example lets say i write "We love stack overflow" and i wanted how many times this sentence has the letter "w" so i hit w and it only shows : "w letter used 1 many time(s)." instead of 2. other letters like "o" works perfectly so it's only a problem about the first letter :/ can someone help me about it ?
Thanks !
This line:
cin >> sentence[100];
will read a single character into the 100th index of sentence, which invokes underfined behavior.
Also, gets has been removed from c++, and you should no longer use it.
Instead, you should use getline:
int main()
{
std::cout<<"Enter Sentence : ";
std::getline(std::cin, sentence);
sameletter(sentence);
}
Also, avoid using namespace std;, it's bad practice.
There's no reason for sentence to be static, or global.
Also, you could just use std::string, instead of char arrays. It will make your life easier. e.g. your loop could be replaced by an algorithm:
int meter = std::count_if(sentence.begin(), sentence.end(),
[=] (unsigned char c) {
return std::tolower(c) == std::tolower(letter);
});

String won't print

I've been doing programming challenges on coderbyte and while doing one, ran into an issue. I want to isolate a word from a string, do some checks on it and then move to another word. The code I'm going to post is supposed to take only the first word and print it out on the screen. When I run it, it doesn't print anything. I thought that maybe I did something wrong in the while loop so I did a simple test. Let's say my input is "This is a test sentence" and instead of word (in cout), I type word[0]. Then it prints "T" just fine. Can you find what the problem is?
#include <iostream>
#include <string>
using namespace std;
int Letters(string str) {
int i=0;
int len=str.length();
string word;
while(i<len){
if(isspace(str[i])){word[i]='\0'; break;}
word[i]=str[i];
i++;
}
cout<<word;
return 0;
}
int main() {
int test;
string str;
getline(cin, str);
test=Letters(str);
return 0;
}
string word;
is default constructed, which is empty initially. Inside while loop, you tried to do:
word[i] = str[i];
It means you tried to access memory that has not been allocated,resulting in undefined behavior.
Try:
word.append(str[i]);
You can use simpler way to get words from input in C++. It will help you to avoid errors in the future.
#include <iostream>
using namespace std;
int main()
{
string word;
while(cin >> word)
{
// "word" contains one word of input each time loop loops
cout << word << endl;
}
return 0;
}

Counting occurrences of letter in a file

I'm trying to count the number of times each letter appears in a file. When I run the code below it counts "Z" twice. Can anyone explain why?
The test data is:
abcdefghijklmnopqrstuvwxyz
ABCDEFGHIJKLMNOPQRSTUVWXYZ
#include <iostream> //Required if your program does any I/O
#include <iomanip> //Required for output formatting
#include <fstream> //Required for file I/O
#include <string> //Required if your program uses C++ strings
#include <cmath> //Required for complex math functions
#include <cctype> //Required for letter case conversion
using namespace std; //Required for ANSI C++ 1998 standard.
int main ()
{
string reply;
string inputFileName;
ifstream inputFile;
char character;
int letterCount[127] = {};
cout << "Input file name: ";
getline(cin, inputFileName);
// Open the input file.
inputFile.open(inputFileName.c_str()); // Need .c_str() to convert a C++ string to a C-style string
// Check the file opened successfully.
if ( ! inputFile.is_open())
{
cout << "Unable to open input file." << endl;
cout << "Press enter to continue...";
getline(cin, reply);
exit(1);
}
while ( inputFile.peek() != EOF )
{
inputFile >> character;
//toupper(character);
letterCount[static_cast<int>(character)]++;
}
for (int iteration = 0; iteration <= 127; iteration++)
{
if ( letterCount[iteration] > 0 )
{
cout << static_cast<char>(iteration) << " " << letterCount[iteration] << endl;
}
}
system("pause");
exit(0);
}
As others have pointed out, you have two Qs in the input. The reason you have two Zs is that the last
inputFile >> character;
(probably when there's just a newline character left in the stream, hence not EOF) fails to convert anything, leaving a 'Z' in the global 'character' from the previous iteration. Try inspecting inputFile.fail() afterwards to see this:
while (inputFile.peek() != EOF)
{
inputFile >> character;
if (!inputFile.fail())
{
letterCount[static_cast<int>(character)]++;
}
}
The idiomatic way to write the loop, and which also fixes your 'Z' problem, is:
while (inputFile >> character)
{
letterCount[static_cast<int>(character)]++;
}
There are two Q's in your uppercase string. I believe the reason you get two counts for Z is that you should check for EOF after reading the character, not before, but I am not sure about that.
Well, others already have pointed out the error in your code.
But here is one elegant way you can read the file and count the letters in it:
struct letter_only: std::ctype<char>
{
letter_only(): std::ctype<char>(get_table()) {}
static std::ctype_base::mask const* get_table()
{
static std::vector<std::ctype_base::mask>
rc(std::ctype<char>::table_size,std::ctype_base::space);
std::fill(&rc['A'], &rc['z'+1], std::ctype_base::alpha);
return &rc[0];
}
};
struct Counter
{
std::map<char, int> letterCount;
void operator()(char item)
{
if ( item != std::ctype_base::space)
++letterCount[tolower(item)]; //remove tolower if you want case-sensitive solution!
}
operator std::map<char, int>() { return letterCount ; }
};
int main()
{
ifstream input;
input.imbue(std::locale(std::locale(), new letter_only())); //enable reading only leters only!
input.open("filename.txt");
istream_iterator<char> start(input);
istream_iterator<char> end;
std::map<char, int> letterCount = std::for_each(start, end, Counter());
for (std::map<char, int>::iterator it = letterCount.begin(); it != letterCount.end(); ++it)
{
cout << it->first <<" : "<< it->second << endl;
}
}
This is modified (untested) version of this solution:
Elegant ways to count the frequency of words in a file
For one thing, you do have two Q's in the input.
Regarding Z, #Jeremiah is probably right in that it is doubly counted due to it being the last character, and your code not detecting EOF properly. This can be easily verified by e.g. changing the order of input characters.
As a side note, here
for (int iteration = 0; iteration <= 127; iteration++)
your index goes out of bounds; either the loop condition should be iteration < 127, or your array declared as int letterCount[128].
Given that you apparently only want to count English letters, it seems like you should be able to simplify your code considerably:
int main(int argc, char **argv) {
std::ifstream infile(argv[1]);
char ch;
static int counts[26];
while (infile >> ch)
if (isalpha(ch))
++counts[tolower(ch)-'a'];
for (int i=0; i<26; i++)
std::cout << 'A' + i << ": " << counts[i] <<"\n";
return 0;
}
Of course, there are quite a few more possibilities. Compared to #Nawaz's code (for example), this is obviously quite a bit shorter and simpler -- but it's also more limited (e.g., as it stands, it only works with un-accented English characters). It's pretty much restricted to the basic ASCII letters -- EBCDIC encoding, ISO 8859-x, or Unicode will break it completely.
His also makes it easy to apply the "letters only" filtration to any file. Choosing between them depends on whether you want/need/can use that flexibility or not. If you only care about the letters mentioned in the question, and only on typical machines that use some superset of ASCII, this code will handle the job more easily -- but if you need more than that, it's not suitable at all.

std::getline does not work inside a for-loop

I'm trying to collect user's input in a string variable that accepts whitespaces for a specified amount of time.
Since the usual cin >> str doesn't accept whitespaces, so I'd go with std::getline from <string>
Here is my code:
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
int main()
{
int n;
cin >> n;
for(int i = 0; i < n; i++)
{
string local;
getline(cin, local); // This simply does not work. Just skipped without a reason.
//............................
}
//............................
return 0;
}
Any idea?
You can see why this is failing if you output what you stored in local (which is a poor variable name, by the way :P):
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
int main()
{
int n;
cin >> n;
for(int i = 0; i < n; i++)
{
string local;
getline(cin, local);
std::cout << "> " << local << std::endl;
}
//............................
return 0;
}
You will see it prints a newline after > immediately after inputting your number. It then moves on to inputting the rest.
This is because getline is giving you the empty line left over from inputting your number. (It reads the number, but apparently doesn't remove the \n, so you're left with a blank line.) You need to get rid of any remaining whitespace first:
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
int main()
{
int n;
cin >> n;
cin >> ws; // stream out any whitespace
for(int i = 0; i < n; i++)
{
string local;
getline(cin, local);
std::cout << "> " << local << std::endl;
}
//............................
return 0;
}
This the works as expected.
Off topic, perhaps it was only for the snippet at hand, but code tends to be more readable if you don't have using namespace std;. It defeats the purpose of namespaces. I suspect it was only for posting here, though.
Declare a character to get in the carriage return after you have typed in the number.char ws;int n;cin>>n;ws=cin.get();
This will solve the problem.
Using cin>>ws instead of ws=cin.get(),will make first character of your string to be in variable ws,instead of just clearing '\n'.
It's quite simple.
U jst need to put a cin.get() at the end of the loop.
Are you hitting enter? If not get line will return nothing, as it is waiting for end of line...
My guess is that you're not reading n correctly, so it's converting as zero. Since 0 is not less that 0, the loop never executes.
I'd add a bit of instrumentation:
int n;
cin >> n;
std::cerr << "n was read as: " << n << "\n"; // <- added instrumentation
for // ...
why this happens :
This happens because you have mixed cin and cin.getline.
when you enter a value using cin, cin not only captures the value, it also captures the newline. So when we enter 2, cin actually gets the string ā€œ2\nā€. It then extracts the 2 to variable, leaving the newline stuck in the input stream. Then, when getline() goes to read the input, it sees ā€œ\nā€ is already in the stream, and figures we must have entered an empty string! Definitely not what was intended.
old solution :
A good rule of thumb is that after reading a value with cin, remove the newline from the stream. This can be done using the following :
std::cin.ignore(32767, '\n'); // ignore up to 32767 characters until a \n is removed
A better solution :
use this whenever you use std::getline() to read strings
std::getline(std::cin >> std::ws, input); // ignore any leading whitespace characters
std::ws is a input manipulator which tell std::getline() to ignore any leading whitespace characters
source : learncpp website
goto section (Use std::getline() to input text)
hope this is helpful
Is n properly initialized from input?
You don't appear to be doing anything with getline. Is this what you want?
getline returns an istream reference. Does the fact that you're dropping it on the ground matter?
On which compiler did you try this? I tried on VC2008 and worked fine. If I compiled the same code on g++ (GCC) 3.4.2. It did not work properly. Below is the versions worked in both compilers. I dont't have the latest g++ compiler in my environment.
int n;
cin >> n;
string local;
getline(cin, local); // don't need this on VC2008. But need it on g++ 3.4.2.
for (int i = 0; i < n; i++)
{
getline(cin, local);
cout << local;
}
The important question is "what are you doing with the string that gives you the idea that the input was skipped?" Or, more accurately, "why do you think the input was skipped?"
If you're stepping through the debugger, did you compile with optimization (which is allowed to reorder instructions)? I don't think this is your problem, but it is a possibility.
I think it's more likely that the string is populated but it's not being handled correctly. For instance, if you want to pass the input to old C functions (eg., atoi()), you will need to extract the C style string (local.c_str()).
You can directly use getline function in string using delimiter as follows:
#include <iostream>
using namespace std;
int main()
{
string str;
getline(cin,str,'#');
getline(cin,str,'#');
}
you can input str as many times as you want but one condition applies here is you need to pass '#'(3rd argument) as delimiter i.e. string will accept input till '#' has been pressed regardless of newline character.
Before getline(cin, local), just add if(i == 0) { cin.ignore(); }. This will remove the last character (\n) from the string, which is causing this problem and its only needed for the first loop. Otherwise, it will remove last character from the string on every iteration. For example,
i = 0 -> string
i = 1 -> strin
i = 2 -> stri
and so on.
just use cin.sync() before the loop.
just add cin.ignore() before getline and it will do the work
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
int main()
{
int n;
cin >> n;
for(int i = 0; i < n; i++)
{
string local;
cin.ignore();
getline(cin, local);
}
return 0;
}