I have an assignment which requires "Recursively reads one character at a time from the text file until a separator is encountered" -
Those non-separator characters are then displayed in reverse order, with the last character displayed being capitalized
Let's say file has below line and separator is !, white space and so on.
abc! ndtv
Expected output is:
Cba! Vtdn
I have written below code and I am getting the expected output — but one condition is I am supposed to do it using only two variables, and I am not able to do it with less than 3. Any pointers how to achieve it with 2 variables only?
int Reverse(ifstream &inFile, int level)
{
int myInput;
static int returnValue;
static int levelofinterest;
myInput = inFile.get();
if (!(isspace(myInput) || ((char)myInput == '.') ||
((char)myInput == '!') || ((char)myInput == ',') ||
((char)myInput == '?') || ((char)myInput == ';') ||
((char)myInput == ':') || ((char)myInput == '\0')||
myInput == EOF))
{
level++;
Reverse(inFile,level);
}
else
{
levelofinterest = level;
returnValue = myInput;
}
if(!(isspace(myInput) || ((char)myInput == '.') ||
((char)myInput == '!') || ((char)myInput == ',') ||
((char)myInput == '?') || ((char)myInput == ';') ||
((char)myInput == ':') || ((char)myInput == '\0')||
myInput == EOF))
{
level--;
if ((levelofinterest - 1) == level)
{
cout << (char)toupper(myInput);
}
else
{
cout.put((char)myInput);
}
}
return returnValue;
}
This code almost meets your requirements (but I'm not completely happy with it). It has only one extra variable over and above the arguments to the function. However, I altered the function signature — the code doesn't use the return value, so the function is defined as returning void. It probably can be modified to meet your alternative calling convention and the loop structure outlined in your (transcribed) comments.
#include <iostream>
#include <cctype>
using namespace std;
static void Reverse(istream &inFile, int level)
{
int c = inFile.get();
if (c == EOF)
return;
if (isalpha(c))
{
Reverse(inFile, level + 1);
if (level == 0)
cout << (char)toupper(c);
else
cout << (char)c;
}
else if (level > 0)
inFile.unget();
else
cout << (char)c;
}
int main()
{
while (cin)
Reverse(cin, 0);
return 0;
}
I call the source code recrevstr.cpp and compiled the program (using make) with the command:
g++ -O3 -g -std=c++11 -Wall -Wextra -Werror recrevstr.cpp -o recrevstr
and then run it:
$ ./recrevstr <<< 'abc! ndtv'
cbA! vtdN
$
It takes various short cuts. In particular, all non-alphabetic characters are delimiters. It uses an istream rather than an ifstream, and the main() is configured so standard input (aka cin) is processed. Like your sample code, it relies on a loop in the calling code to make sure the job is complete. I start with level 0; it's trivial to start with level 1 instead.
Note that any code using cout with << operators to produce output is inherently C++ and not directly applicable to C. This effect can be neutralized by using <cstdio> and FILE * (and stdin), plus appropriate I/O functions, which could then make it bilingual, though there'd need to be conditional compilation to get the std namespace out of the way.
Related
I'm writing a programm which gives out the input string without its vowels.but it only gives the first charachter of the string .here is the code:
#include<iostream>
using namespace std;
int main(){
char ch;
while(cin.get(ch)){
cout<<ch;
char a=cin.peek();
while( a==65 || a==69 || a==73 || a==79 || a==85 || a==97 || a==101 || a==105 || a==111 || a==117)
cin.ignore(1 , a);
}
return 0;
}
To solve a problem like this, start by breaking the problem into smaller parts. A possible decomposition is:
Are there characters still to read from the input? No: Great, we are done!
Read in a character
Is the character a vowel? Yes: Goto 1.
Output the character
Goto 1.
Then in code, you can translate this into:
// 1) Are there characters still to read?
while (std::cin.good())
{
// 2) Read in a character
char ch;
std::cin.get(ch);
// 3) Is the character a vowel?
// For the test for a vowel, you can use something similar to
// what you have at the moment, or better still: consider
// writing a function like isVowel in #Shreevardhan answer.
if ( /* TODO: Test if the character is a vowel... */)
{
// Skip the rest of the loop and go back to 1
continue;
}
// 4) Output the good character
std::cout << ch;
// 5) Reached the end of the loop, so goto 1
}
It's a good habit to break your problem down into smaller parts. I often start a new project by first writing out a list/comments (or even drawing a flow diagram) to break up the problem into more manageable pieces.
Other answers show how to solve this problem in a more intuitive manner.
Anyway, when looking at your code consider the following:
while( a==65 || a==69 || a==73 || a==79 || a==85 || a==97 || a==101 || a==105 || a==111 || a==117)
cin.ignore(1 , a);
As you do a while loop with conditions around the value of a, and as cin.ignore(1 , a) does not change the value of a, you wont ever leave this loop unless an exception is thrown, right?
Maybe you can try to use the boost library.
#include <boost/algorithm/string.hpp>
boost::erase_all(str, "a");
Something like this
#include <iostream>
using namespace std;
bool isVowel(char c) {
c = tolower(c);
return c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u';
}
int main() {
char c;
while (cin.get(c))
if (!isVowel(c))
cout << c;
return 0;
}
Add your storing logic inside.
A more C++-ish code
#include <algorithm>
#include <iostream>
using namespace std;
int main() {
string s;
getline(cin, s);
s.erase(remove_if(s.begin(), s.end(), [](char c) {
c = tolower(c);
return c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u';
}), s.end());
cout << s;
return 0;
}
See a demo.
I'm not getting errors, but the output is incorrect. I'm not sure what I'm doing wrong. I can only use functions from string library.
#include <iostream>
#include <string>
#include <cstdlib>
using namespace std;
int main() {
string message, pig_message;
getline(cin, message);
unsigned int x = message.find_first_of("aeiou");
if (message[x] == 'a' || 'e' || 'i' || 'o' || 'u' ) {
pig_message = message + "yay";
cout << pig_message;
}
else if (!(message[x] == 'a' || 'e' || 'i' || 'o' || 'u' )) {
pig_message = message.substr(1) + message[0] + "ay";
cout << pig_message;
}
system("pause");
return 0;
}
The first if statement is always true. You should change it to
if (message[x] == 'a' || message[x] == 'e' || message[x] == 'i' || message[x] == 'o' || message[x] == 'u' ) {
Also, you could change the else if (...) { line to just
else {
if you want it to be executed every time the first if statement is not true.
Your comparison statement is incorrect.
Make sure your function is actually iterating through the letters, and that you're concatenating the strings correctly.
So:
unsigned int x = message.find_first_of("aeiou"); // Returns the first match
if(message[x] == 'a' || message[x] == 'e'...) // Currently your code reads as only checking for a.
Think of it as IF message[x] = a, IF e, IF i
vs
if message[x] = a, IF message[x] = i
What does your code do after it finds a match?
pig_message = message + 'yay' would add "yay" to the whole message string.
It would then print it out and move on, without doing anything to the other vowels.
I'm new to C++ myself but that's how I've understood your code.
It might be better to go through the whole input string one letter at a time in a for loop with your if else statements to add the strings inside the loop.
Here is my code:
#include<stdio.h>
int main()
{
int a = '\0';
while ((a = getchar()) != EOF){
if (a != ' ' || a != '\t' || a != '\n' || a != ';' || a != ',' || a != '.'){
putchar(a);
}
else{
continue;
}
}
system("pause");
return 0;
}
I need to read a poem from an input file, and output the poem with no spaces or punctuation. Must be done using I/O variation. I've searched all over, but I can't seem to find how to do this the way I need. Any help is much appreciated...
Hope this solves your Problem. Use ascii values for character. Also use fgetc/fputc/fscanf/fprintf etc for file i/o related operations. ASCII CHART link here ASCII Chart VALUES.
#include<stdio.h>
int main()
{
FILE *pfile=NULL;
char data[255];
int i=0;
pfile=fopen("poem.txt","r");
while((data[i]=fgetc(pfile)) != EOF)
{
if(data[i]> 32 && data[i] < 123)
{
if(data[i] != 44 && data[i]!= 45 && data[i]!=46 && data[i]!=33)
{
//In the above 'if statement' you can add more characters/special
//characters you wish to exclude/ignore
printf("%c",data[i]);
i++;
}
}
}
return 0;
}
I am trying to read a sequence which is supposed to be in the form of:
variable operator variable operator variable. . . and so on, where the 'variable' consists is either A , B , or C and the 'operators' are one of the four basic operators + - / * , and simply print valid if it conforms to that given form and invalid if it doesn't. Also, the conditions are that the sequence must start with a single variable and be followed (spaces are allowed in between) by an operator.
I have already made up some code where I take the string input and just have a function called 'check' to see if it returns false, making the program print 'Invalid'. Here is my main function:
using namespace std;
int main() {
string m;
cout<<"Please enter a sequence: "<<endl;
getline(cin,m);
bool allow = check(m);
if(allow == true){
cout<<"\n\nCorrect format "<<endl;
}
else{
cout<<"\n\nIncorrect format \n"<<endl;
}
system("PAUSE");
return 0;
}
And here is my check function:
bool check(string mi){
int c=0; //using c as an index,
mi.append("0"); //append a 0 as a signal to when the string ends
while(c < mi.length()){
if(mi.at(c)=='0'){}
else if(isblank(mi.at(c))){} //So it will accept spaces between the input
else if(mi.at(c) == 'A' ||mi.at(c) == 'B' ||mi.at(c) == 'C'){
//The sequence must start with a variable...
c +=1; //increment to start at the next character...
while(c < mi.length()){ //This whole loop is to check if the next
//significant character is one of the operators
if(isblank(mi.at(c))){}
else if(mi.at(c) !='+' ||mi.at(c) != '-' ||mi.at(c) != '/' || mi.at(c) != '*' || mi.at(c) !='0'){
cout<<"\n(Log) Character at "<<c<<" was not an operator? Value: "<<mi.at(c);
//Why does it always come here even if the value was an operator?
return false;
}
c++;
}
}
c++;
}
return true; //Assume true if there are no errors...
}
Even if I input a correct sequence, say A+B+C , it still comes up as being invalid. I have traced the problem to the particular line of code above. Why does it do this?
Because your boolean logic is incorrect.
The expression:
mi.at(c) !='+' || mi.at(c) != '-' || mi.at(c) != '/' || mi.at(c) != '*' || mi.at(c) !='0'
will evaluate as true every time. For example, if mi.at(c) is a '-', then mi.at(c) != '+' evaluates to true and your into that part of the code you don't want to be in. Likewise, if i.at(c) is a '+' then mi.at(c) != '-' evaluates true and again your conditional evaluates as true again.
I believe you want to change your boolean or's (||) to boolean and's (&&).
For some unsolicited advice, personally I would suggest taking a moment to think of the problem as a state machine. This will enable you to clean up and think about what it is doing in a supportable and expandable fashion. I'm not a c++ coder, but here is how I would approach it in c as a state machine. You should be able to translate it to c++:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
main() {
char* VARS = "ABC";
char* OPS = "+-/*";
char c = EOF;
int state = 0;
while (((c = getchar()) != EOF) && (state < 3)) {
// move on to next character if we have a blank or end-of-line
if (c == ' ' || c == '\n')
continue;
// test to see if the character is a var or op
int isvars = (strchr(VARS, c) != NULL);
int isops = (strchr(OPS, c) != NULL);
// based upon character type and current state, determine next state
if (!isvars && !isops) // character is neither a valid var nor op
state = 3;
else if (isvars) // character is a var
if ((state == 0) || (state == 2))
state = 1;
else if (state == 1)
state = 3;
else if (isops) // character is an op
if ((state == 0) || (state == 2))
state = 3;
else if (state == 1)
state = 2;
}
puts((state > 1) ? "bad" : "good");
}
And, here is the result after compiling it to 'varop':
$ echo "" | ./varop
good
$ echo "A" | ./varop
good
$ echo "+" | ./varop
bad
$ echo "A+" | ./varop
bad
$ echo "AA" | ./varop
bad
$ echo "A+" | ./varop
bad
$ echo "A+A" | ./varop
good
$ echo "A++" | ./varop
bad
$ echo "A + B" | ./varop
good
$ echo " A + B" | ./varop
good
$ echo "D" | ./varop
bad
$ echo "%" | ./varop
bad
You are correct in where your problem is, however problem is your basic logic. Because you use || and not &&, that means that your statement will always evaluate to true (i.e. '+' will evaluate to false in the first condition, but will evaluate to true when checking for not -). What you need to do is replace the || operators in the culprit line with && and your check function should behave as expected.
Also, as a style note, on line 8 of your check function, instead of c += 1, you should use c++ for the sake of consistancy.
Try this out, it compiles and gives the desired output. However it still not enforcing that an operator should be followed by a character for example. But i guess you can figure that out.
using namespace std;
To help, i made an array of possible operators along with a function that checks if a character is an operator or not.
unsigned char operators[] = { '+','-','/','*' };
bool isOperator(const unsigned char &m) {
for (int n = 0; n < 4; n++) if (m == operators[n]) return true;
return false;
}
In your check there is only one loop needed and a for loop is much more conveniant. Notice the logic, i continue when the character is a A or B or C or when it is blank.
bool check(string mi){
for (int c = 0; c < mi.size(); c++) {
cout << mi.at(c);
if (isblank(mi.at(c))) continue;
if (mi.at(c) == 'A' || mi.at(c) == 'B' || mi.at(c) == 'C') continue;
if (!isOperator(mi.at(c))) {
cout<<"\n(Log) Character at " << c <<" was not an operator? Value: "<<mi.at(c);
return false;
}
}
return true; //Assume true if there are no errors...
}
int main() {
string m;
cout<<"Please enter a sequence: "<<endl;
getline(cin,m);
cout << "\n\n" << string(check(m) ? "Correct":"Incorrect") << " format." << endl;
system("PAUSE");
return 0;
}
Output:
Please enter a sequence:
A+B+C
A+B+C
Correct format.
Press any key to continue . . .
I would suggest using std::istringstream and using std::copy to get the separate components into a std::vector of characters. Then it's simple to iterate over the vector to check for only the valid components.
To help with getting the components into the vector with std::copy, I suggest you read about std::istream_iterator and std::back_inserter.
I search the most concise and efficient way to find the first printf format sequence (conversion specification) in a C++ string (I cannot use std::regex as they are not yet implement in most in compilers).
So the problem is to write an optimized function that will return the beginning of the first printf-format sequence pos and its length n from an input string str:
inline void detect(const std::string& str, int& pos, int& n);
For example, for:
%d -> pos = 0 and n = 2
the answer is: %05d -> pos = 15 and n = 4
the answer is: %% %4.2f haha -> pos = 18 and n = 5
How to do that (clever and tricky ways are welcome)?
Scan forward for %, then parse the content from there. There are some quirky ones, but not THAT bad (not sure you want to make it an inline tho').
General principle (I'm just typing as I go along, so probably not the BEST form of code ever written - and I haven't tried to compile it at all).
inline void detect(const std::string& str, int& pos, int& n)
{
std::string::size_type last_pos = 0;
for(;;)
{
last_pos = str.find('%', last_pos)
if (last_pos == std::string::npos)
break; // Not found anythin.
if (last_pos == str.length()-1)
break; // Found stray '%' at the end of the string.
char ch = str[last_pos+1];
if (ch == '%') // double percent -> escaped %. Go on for next.
{
last_pos += 2;
continue;
}
pos = last_pos;
do
{
if (isdigit(ch)) || ch == '.' || ch == '-' || ch == '*' ||
ch == '+' || ch == 'l' || ch == 'L' || ch == 'z' ||
ch == 'h' || ch == 't' || ch == 'j' || ch == ' ' ||
ch == '#' || ch == '\'')
{
last_pos++;
ch = str[last_pos+1];
}
else
{
// The below string may need appending to depending on version
// of printf.
if (string("AacdeEfFgGiopusxX").find(ch) != std::string::npos)
{
// Do something about invalid string?
}
n = last_pos - pos;
return;
}
} while (last_pos < str.length());
}
}
edit2: This bit is probably better written as:
if (isdigit(ch)) || ch == '.' || ch == '-' || ch == '*' ||
ch == '+' || ch == 'l' || ch == 'L' || ch == 'z' ||
ch == 'h' || ch == 't' || ch == 'j' || ch == ' ' ||
ch == '#' || ch == '\'') ...
if (string("0123456789.-*+lLzhtj #'").find(ch) != std::string::npos) ...
Now, that's your homework done. please report back with what grade you get.
Edit: It should be noted that some things that a regular printf will "reject" is accepted by the above code, e.g. "%.......5......6f", "%5.8d", "%-5-6d" or "%-----09---5555555555555555llllld". If you want the code to reject these sort of things, it's not a huge amount of extra work, just need a little bit of logic to check "have we seen this character before" in the "check for special characters or digit", and in most cases the special character should only be allowed once. And as the comment says, I may have missed a couple of valid format specifiers. It gets further trickier if you also need to cope with "this 'l' is not allowed with 'c'" or such rules. But if the input isn't "malicious" (e.g. you want to annotate where on which line there are format specifiers in a working C source file), the above should work reasonably well.