program cannot get past "cin" - c++

I'm writing a program that will guess words taken from a big text file. One step is taking user input to determine the length of the string.
edit: added full code, made some changes
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
int i(0),n(0),counter(0),limit(0);
char words[60000][30];
int initarray() {
int length(0);
string line;
char temp;
ifstream wordlist ("text.txt");
if (wordlist.is_open())
{
while (wordlist.good())
{
getline (wordlist,line);
length=line.length();
for (n=0;n!=length;n++)
{
temp=line.at(n);
words[i][n]=temp;
}
i++;
counter++;
}
}
else
{
cout<<"file not opened";
}
wordlist.close();
return 0;
}
int selectlength()
{
int length;
bool shorter(false),longer(false);
cout <<"length of word"<<endl;
cin >> length
limit=counter;
counter=0;
for (i=0;i<limit;i++){
for (n=0;n!=length;n++){
if (words[i][n]=='\0')
{
shorter=true;
break;
}
}
if (words[i][length+1] != '\0')
{
longer=true;
}
if (longer==true || shorter==true)
{
i--;
}
}
return 0;
}
int printresults(){
for (i=0;i!=counter;i++){
for (n=0;n<=20;n++){
cout << words[i][n];
}
cout <<endl;
}
return 0;
}
int main() {
initarray();
selectlength();
printresults();
return 0;
}
but my problem is happens whenever the program, which compiles fine, gets to the "cin" part to read user input for the length. When I enter in any number and hit enter, nothing happens. The program is still running, and just keeps taking input indefinately. Any help? Could it have anything to do with my using ifstream earlier in the prigram, albeit in a different function?

You've got an infinite loop in selectlength(). The outer for loop doesn't terminate because you're decrementing i (the loop counter) inside the loop (not a good idea, perhaps find a better way).
I think you're not terminating on the last line in the input file. longer and shorter will both be true and limit will never be reached. Put in a test for this in the loop:
if (words[i][0] == '\0')
break;
That will at least stop the infinite loop and allow you to relook at your logic (it's not clear what longer and shorter will be used for.
A few general comments:
Putting trace statements inside the problem area can help you identify a problem.
You'll learn more about C++ if instead of the char words[x][y] you use std::vector<std::string> words;
A boolean inside an if statement is easier to read like this: if (longer || shorter) than how you have it.
You're always returning 0 - rather make the function void.
You're also setting the global counter to 0 inside selectlength() but you still need it later in printresults() so you'll get no output.

Related

trying to read data file, store in array and print all the elements but it isnt working

not sure what i'm doing wrong but this is my code
int main (){
int marks [100];
int i=0;
ifstream inputfile;
ofstream outputfile;
inputfile.open("data.txt");
if(!inputfile.is_open())
{
cout<< "File did not open"<< endl;
return 0;
}
cout<<"Marks in File:"<<endl;
while (marks [i] != -1)
{
inputfile>>marks[i];
cout << marks[i] <<endl;
i++;
}
return 0;
}
the output is messed up and returns stuff that was never in the data file to begin with
Here is the minimal code for reading data from a file and write it to console. Description is added as comments
#include <fstream>
#include <sstream>
#include <string>
#include <iostream>
using namespace std;
int main()
{
ifstream configrecord("D:\\Temp\\temp.txt"); // opening the file named temp for reading.
if(configrecord.good()) // check whether the file is opened properly.
{
string line;
while (getline(configrecord, line)) // reading a line from file to std::string
{
cout << line; // printing the line, if you want it to store in an array, you can use the std::string::data() api to get the character pointer.
}
configrecord.close(); // closing the file after reading completed
}
}
If we translate your code to English, we get:
Check if the current array element is -1, if it is, break the loop.
Read the value into the current array element.
Output the value.
Move to the next array element and repeat.
Notice a big problem: We're checking if the value is -1 before we actually read it. We need to reverse the order of steps 1 and 2 so that we get:
Read the value into the current array element.
Check if the current array element is -1, if it is, break the loop.
Output the value.
Move to the next array element and repeat.
We can do this by using true as our loop condition and then using an if statement to check if the inputted value is -1 later in the loop, using break to break the loop if it is.
#include <fstream>
#include <iostream>
//using namespace std; is considered bad practice
int main()
{
std::ifstream inFile("input.txt");
int marks[100];
//check if file is open stuff...
for(int i = 0; true; i++)
{
inFile >> marks[i];
if(marks[i] == -1) break;
std::cout << marks[i] << '\n'; //endl flushes the buffer, unnecessary here.
}
}
Of Note: it is good practice that if you use an if statement, you also include an else statement. Also, your while loop is confusing, because it stops if it encounters negative one, so I am assuming you know that integer -1 is not in the file.
int n = -1;
if(!inputfile.is_open())
{
cout<< "File did not open"<< endl;
}
else
{
cout<<"Marks in File:"<< endl;
while(!inputfile.eof()){ // .eof is bad practice, but for this instance it works.
File >> marks[n];
n++; // Essentially the size of the array (Number of values), keeping track of how many values there are will assist you in the output process.
}
}
When you are done reading the file, you should close it and then use the data in the array.
inputfile.close();
Lastly, in order to output an array of data, you must use a for loop or some type of iterator to access the values stored in the array.
for(int i=0; i < n ; i++) // Output array. Where array size is less than n.
{
cout << marks[i] << " "; // " " inputs a space in between each word.
}

(C++) Learning vectors - problems with coding/input stream termination/comparing vectors

I'm beginner learning my first programming language - C++ - from Bjarne Stroustrup's book "Programming Principles and Practice Using C++". Chapter 4 talks about vectors. Everything explained before I would get easily and code would always work properly, until now.
The code I write doesn't function at all. The following code was made for little exercise, where the input is read in and prints the words out, bleeping out the disliked ones.
#include "std_lib_facilities.h"
int main() {
vector<string>text;
string disliked = "cat";
for (string word; cin >> word;) {
text.push_back(word);
}
for (int a = 0; a < text.size(); ++a) {
if (text[a] != disliked) {
cout << text[a] << endl;
}
else {
cout << "BLEEP\n";
}
}
keep_window_open();
}
My first idea was to create another vector, vector<string>disliked ={"cat", ...} , for disliked words, but then if (text[x] != disliked) didn't seem like a way of comparing elements from each vector (at least it was warning me about operator and operands mismatch). Is there a way for that?
But back to the code: with some modifications and without any disliked word in the input, the program would run sometimes. Still I can't manage to meet the main purpose. And perhaps, the actual mistake is in the input termination. Ctrl+Z doesn't work for me but just inputs a character. And somehow Ctrl+C happened to work properly (if there were no disliked words).
So here come the actual questions:
Is the code correct? (since I can't check it myself while I might have been terminating the input improperly entire time)
How can I terminate input any other way, considering that Ctrl+Z only adds a character to the input?
Is there a way of making this program work by comparing the "input" vector with the "disliked" vector?
Is the code correct? (since I can't check it myself while I might have been terminating the input improperly entire time)
Seems to work for me.
How can I terminate input any other way, considering that Ctrl+Z only adds a character to the input?
I use Ctrl-D to mark end of line.
Is there a way of making this program work by comparing the "input" vector with the "disliked" vector?
Usually when you compare types (with == and !=) they have the same type (or the compiler can convert one type to the same type as the other type (but that's for the pedantic here; for beginners its best to think of comparison comparing objects of the same type)).
vector<string> text;
string disliked = "cat";
// STUFF
if (text[x] != disliked) // disliked is a string
// text[x] is a string (because we are accessing the `x` element.
If we change disliked to a vector:
vector<string> text;
vector<string> disliked = "cat";
// STUFF
if (text[x] != disliked) // disliked is a vector<string>
// text[x] is a string
Since the types do not match they are hard to compare. So you need to loop over all the elements in disliked to see if you can find the word.
bool found = false;
for(std::size_t loop = 0; loop < disliked.size(); ++loop) {
if (text[x] == disliked[loop) { // Types are the same here.
found = true;
break;
}
}
if (!found) {
There are techniques to make the above compact. If you are just started this may be a bit early for this, but for completness I will add it here:
bool found = std::find(std::begin(disliked), std::end(disliked), text[x]) != std::end(disliked);
if (!found) {
I guess you have two options here:
1. Get the input from a text file.
In this case you have to place your data in a text file, in your project directory. For example, in the code posted below, "text.txt" is where the input should be stored (your words).
Minor remarks:
I'm not sure what "std_lib_facilities.h" contains so I added some of the standard headers to make the code compile for me.
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
int main()
{
std::vector<std::string> texts;
std::string dislikedWord = "cat";
std::ifstream fin("text.txt");
for (std::string word; fin >> word;)
texts.push_back(word);
unsigned textsCount = texts.size();
for (unsigned textIndex = 0; textIndex < textsCount; ++textIndex)
if (texts[textIndex] != dislikedWord)
std::cout << texts[textIndex] << '\n';
else
std::cout << "BLEEP\n";
return 0;
}
2. Keep reading words until a condition is finally met.
In this case (if you don't want to read from a text file) you should insert a condition that makes the program stop taking input, so you can preceed further. A condition can be something like maximum number of words that can be read or some 'special' word. In the example below, I chose to end reading at ten words.
Minor remarks: Maybe the chapter from where you got the exercise tells you what condition to insert. I doubt that you have to use CTRL+C or any other key combinations to solve the exercise.
#include <iostream>
#include <vector>
#include <string>
int main()
{
const unsigned totalWords = 10;
std::vector<std::string> texts;
std::string dislikedWord = "cat";
for (std::string word; std::cin >> word;) {
texts.push_back(word);
if (texts.size() == totalWords) // could've put it in the for condition
break; // terminates the for-loop
}
unsigned textsCount = texts.size();
for (unsigned textIndex = 0; textIndex < textsCount; ++textIndex)
if (texts[textIndex] != dislikedWord)
std::cout << texts[textIndex] << '\n';
else
std::cout << "BLEEP\n";
return 0;
}

Read line in C++ till EOF

I'm writing a function that reads line by line from cin and returns when it sees ; character.
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <string.h>
using namespace std;
int read_cmd(char *cmd)
{
cout << "Please enter a string: \n";
cmd[0]='\0';
while(1){
char currentLine[10000];
currentLine[0]='\0';
cin.getline(currentLine,10000);
if (strcmp(currentLine,";")==0){
break;
}
strcat(cmd, "\n");
strcat(cmd, currentLine);
}
return 0;
}
int main(){
char cmd[1000];
while (1){
read_cmd(cmd);
cout<< cmd << endl;
}
}
I then tested it using text fed from another file via pipe.
./read_cmd < test_file
contents of test_file:
line 1
line 2
;
This outputs results just fine, however it gives me a segmentation fault at the end. Is there a way for cin to check if it's coming across an EOF and terminates?
To detect the EOF you should use something like:
while (cin.good() && !cin.eof())
{
// Read the file
}
See the documentation for cin, in particular the good() (for error checking) and eof() member functions.
In particular this example might be helpful.
I would highly suggest the use of the string object for something like this, that way you're not wasting space, as well as ensuring that you have enouch space. You can also do it without a loop.
string currentLine;
getline(cin, currentLine, ';');
Now, if you need to get just the last line with has the semi-colon, a loop is necessary, but still you can do it at little more easily.
string currentLine;
while(getline(cin, currentLine)){
if(currentLine.find(";") != string::npos){
break;
}
}
Use strings to pass things around as well. There's always the .clear() method as well that any string has for easy emptying.
string getline
string Object

How to stop recursion if nothing is inputed in cin?

I am writing a program that must print numbers at first which was entered at last.
So here is my code:
#include <iostream>
using namespace std;
void recursive()
{
long long n;
if((cin>>n)&&(!cin.eof())) // Dont work because enter is ignored in cmd window os
recursive();
cout<<n<<endl;
return;
}
int main()
{
recursive();
return 0;
}
Any idea how to stop function when nothing is input? Or how to solve problem in another way?
Thanks
As your program is right now it will read the long long's until cin's operator void* indicates that the value read was not compatible (but still prints the n , filled with garbage,that it failed to read), as you notice it ignores the blank lines.
If I understand correctly, what you want is that when the user inputs a blank line the program should output the numbers read, a simple way to do this would be to read the input as a string, then check the string's length, and use a stringstream to convert it to the appropriate type.
#include <iostream>
#include <sstream>
#include <string>
void recursive()
{
std::string input;
long long n;
if ( std::getline(std::cin,input) && input.length() > 0 )
{
std::istringstream ss(input);
if (ss >> n)
{
recursive();
std::cout << n << std::endl;
}
}
}
int main ()
{
recursive();
return 0;
}
edit
Here's another way, if your input comes in the form 46 798 4163 4654 32132, it uses std::cin.peek() that returns the next character in the input without extracting it, the result of peek() is compared to '\n' to test if the user pressed enter, and if that's the case it prints the number it just read without waiting for the next number
#include <iostream>
#include <sstream>
#include <string>
void recursive_in_a_line ()
{
long long n;
if (std::cin >> n)
{
if (std::cin.peek() != '\n')
{
recursive();
}
std::cout<< n << std::endl;
}
}
int main ()
{
recursive_in_a_line();
return 0;
}
Do you have to implement the program in a recursive way?
An alternative solution that does not use recursion would be to read the numbers in a while loop and add them to a container (a list or a vector), then display the content of the container.

checking input using a do-while loop with c, c++

Hello i'm trying to use a do-while loop to check the input and repeat the prompt until the user types in a correct integer. So that's my code:
#include <iostream>
#include <stdio.h>
#include <ctype.h>
int main ()
{
int a;
do
{
printf("Please type in your number: ");
}while(scanf_s("%d", &a) == 0);
std::cin.get();
std::cin.get();
return 0;
}
Well it seems to work. When I type in a number the program runs correctly. But when I type in a letter an infinite loop starts. Sincerly I don't know where the problem is.
Again, I suggest reading a line into a string and then trying to parse that string according to your needs. If the parse fails, simply prompt the user again. You can bury the messy details in a function template:
#include <iostream>
#include <sstream>
#include <string>
template <typename T>
T read(std::string prompt)
{
for (; ;)
{
std::cout << prompt;
std::string line;
getline(std::cin, line);
std::istringstream ss(line);
T x;
if ((ss >> x) && (ss >> std::ws).eof()) return x;
}
}
int main ()
{
int a = read<int>("Please type in your number: ");
std::cout << "You entered " << a << '\n';
}
Here's what's going on -- I'll go through step by step. Starting from the do:
output: Please type in your number:
call to scanf Scanf finds that stdin is empty, and therefore waits for a line to be typed in.
input : letter (note that the input buffer now contains "letter")
scanf attempts to parse the string as an integer. Parsing fails before it consumes any characters. Therefore the buffer still contains "letter"
scanf returns EOF (error)
output: Please type in your number:
call to scanf -- scanf sees that there's already waiting input in stdin
scanf attempts to parse the buffer as an integer.....
This will go on forever because scanf will never consume the characters from the buffer. You can solve the problem by correctly checking for an error return code from scanf.
First of all never ever use scanf as its one hell of a dangerous function.
If you want to stick with C you should use fgets to read the input from the user to a buffer and then atoi to convert the input from the user to an integer.
Note: fgets always adds the 'enter' in to the buffer so you want to strip it off before converting the content of the buffer.
this could be easily done as follow:
_buffer[strlen(_buffer)-1] = '\0';
I have modified my code so that it works now. But sincerly it just works for numbers and letters. I want it to work with every char. For example "!?%". I have already tried to change the "isalnum" by "isascii" but that does not work.
#include <stdio.h>
#include <ctype.h>
int main ()
{
int a;
int b = 1;
char c ;
do
{
printf("Please type in a number: ");
if (scanf("%d", &a) == 0)
{
printf("Your input is not correct\n");
do
{
c = getchar();
}
while (isalnum(c));
ungetc(c, stdin);
}
else
{
printf("Thank you! ");
b--;
}
}
while(b != 0);
getchar();
getchar();
return 0;
}
# ordo
Blockquote
I have modified my code so that it works now. But sincerly it just works for numbers and letters. I want it to work with every char. For example "!?%". I have already tried to change the "isalnum" by "isascii" but that does not work.
Blockquote
You can use
if(userInput>='!'&& userInput<= '~') // refer ASCII chart between !and ~.
{ exit=0; }
http://www.cdrummond.qc.ca/cegep/informat/professeurs/alain/images/ASCII1.GIF
int main ()
{
int a;
char userInput,exit=1;
do
{
printf("Please type in your number: ");
userInput=getch();
if(userInput=='1') // suppose the correct input is 1.
{ exit=0; }
}while(exit);
std::cin.get();
std::cin.get();
return 0;
}
If the input is between 0 and 9...
if(userInput>='0'&& userInput<= '9') // suppose the correct input is 1.
{ exit=0; }
Note that we have to use ' ' signs
You can use getchar() function
do
{
printf("Please type in your number: ");
}while((getchar() - '0') == 0);