C++ user input to string array infinite loop - c++

I'm trying to parse a user input string into an array. Example: user inputs "hello to you" array[0]="hello" array[1]="to" array[2]="you' After I prompt the user to input some words, the program seems to infinitely loop. I have also tried using a vector, so it may be my logic in another area. I'm very rusty when it comes to the C language, so please excuse my ignorance. Any help would be greatly appreciated!
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
struct FATNode;
struct FileNode;
class FileList;
class FAT
{
FATNode* head;
};
class FileList
{
FileNode* head;
//methods
public:
int createfile()
{
string word[2];
cout << "Please input file name, followed by file size: ";
int i = 0;
for (string input; cin >> input; i++)
word[i] = input;
for(i=0; i<2; i++)
cout << word[i] << ' ';
return 0;
}
};
struct FileNode
{
string filename;
int filesize;
FAT t1;
FileNode* next;
};
struct FATNode
{
int sectornumber;
FATNode* next;
};
main()
{
FileList myFileSystem;
char start;
int cmd;
bool cont = true;
while(cont == true)
{
cout << "Initializing disk.\n" << "To access menu, type 'Y'. To exit, type 'N': ";
cin >> start;
if(start == 'y' || start == 'Y')
{
cout << "What command would you like to execute on the disk?" << endl;
cout << "1. Format disk\n2. Create file\n3. Delete file\n";
cout << "4. List\n5. Read file\n6. Overwrite file\n7. Append to file\n8. Disk status\nSelection: ";
cin >> cmd;
switch(cmd)
{
case 1 :
break;
case 2 :
myFileSystem.createfile();
break;
default :
cout << "Invalid command" << endl;
}
}
else if(start == 'n' || start == 'N')
{
cont = false;
}
else
{
cout << "Invalid input." << endl;
}
}
}

Your loop condition is cin >> input. This expression returns cin, which can be implicitly converted into a boolean (http://en.cppreference.com/w/cpp/io/basic_ios/operator_bool). However, cin only becomes false, if there's an error or if you have reached end of file (EOF). You can signal EOF by pressing Ctrl+D.
Note also, that you are using a fixed-size array to store information that you get from the user. That's bad, because if the user enters more than 2 words, the array word will overflow. That's undefined behaviour.
If you just want a file name, followed by a file size, why don't you just use:
std::string filename;
std::size_t filesize;
std::cin >> filename >> filesize;

Related

When I try to use cin in my C++ program, it throws a strange exception

So in the program I'm currently writing, the user is supposed to add people to a vector by inputting their names and partisan identities. However, I have been unable to make the code that actually stores the input work. The program first prompts the user for a name; then, once the user gives a name, it prompts the user again for a partisan identity. Whenever I enter more than one word for the name (e.g. "John Smith"), instead of accepting the input, the program throws this exception.
It also gives this error when I enter "D" or "R" in response to the second prompt, no matter how I respond to the first prompt. Does anyone have an idea what I'm doing wrong here? Here's the code I've written so far:
#include "DelibDem.h"
#include <stdio.h>
#include <vector>
//initializing variables
using namespace std;
bool continue_ = true;
string name = "";
string partyID = "";
int numD = 0;
int numR = 0;
int difference = 0;
int vectorSize = 0;
int newVectorSize = 0;
struct person{
string Name;
string PartyID;
string equivalentName;
string equivalenceClass;
};
vector<person> Sample;
int main()
{
//user adds people to the vector. I have not yet implemented the code that actually adds the people specified by the user yet, because I am still trying
//to figure out why my cin code is not working.
while (continue_ == true) {
string personName;
string personPartyID;
cout << "Enter a person's name: ";
cin >> personName;
cout << "Enter the person's party ID (D or R): ";
cin >> personPartyID;
if (personPartyID == "D") struct person inputtedPerson = { personName, personPartyID, NULL, "Republicans" };
else struct person inputtedPerson = { personName, personPartyID, NULL, "Democrats" };
cout << "Do you wish to add more people? (Y/N) ";
string answer;
cin >> answer;
if (answer == "N") continue_ = false;
}
//The number of Democrats in the sample is stored in numD. The number of Republicans is stored in numR.
for (auto& element : Sample)
{
if (element.PartyID == "D") numD++;
else numR++;
}
//print the number of Democrats and Republicans
cout << numD;
cout << numR;
//print the properties of each element in the sample
for (auto& element : Sample)
{
cout << element.Name << endl;
cout << element.PartyID << endl;
cout << element.equivalentName << endl;
cout << element.equivalenceClass << endl;
cout << "\n";
}
return 0;
}

The first character in the input file is the last character in the output file and vice-versa

I want to print out the first character in the input file is the last character in the output file and vice-versa. But I stuck at how to print out the output.
I need to use arrays. I will read from input file into a character array and the write from the array to the output file.
Example:
Input.txt: A B C D E H
output.txt: H B C D E A
This is my code
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
int main()
{
string FileName, FileName2;
string s, temp, FirstChar, LastChar;;
char again = 'Y';
bool close = false;
char MAXSIZE[1024];
while (close == false)
{
cout << "Open the file: ";
cin >> FileName;
ifstream ReadFromFile(FileName);
if (ReadFromFile.is_open())
{
cout << "Succeed to open the file!\n";
// Read character from the input to array
while (!ReadFromFile.eof())
{
ReadFromFile >> MAXSIZE;
cout << MAXSIZE << " ";
}
cout << endl;
cout << "Enter the first character: ";
cin >> FirstChar;
cout << "Enter the last character: ";
cin >> LastChar;
swap(FirstChar, LastChar);
// I stuck at here
ifstream in(FileName);
cout << "Enter a name for a copy file: ";
cin >> FileName2;
ofstream out(FileName2);
while (getline(in, s))
out << s << "\n";
cout << "Close the program and then open your copy file.";
cout << endl << endl;
close = true;
}
else{
cout << "Failed to open the file!\n";
do {
cout << "Do you want to do it again(Y) or Close (N)? ";
cin >> again;
} while (again != 'y' && again != 'Y' && again != 'n' && again != 'N');
if (again == 'y' || again == 'Y')
close = false;
else
close = true;
cout << endl;
}
}
system("pause");
return 0;
}
Your task (according to your explanation) require:
1) reading from input file to array
2) changing the first and the last characters
3) saving array to output file
So, the first and the last characters should not be asked from standard input (keyboard).
#include <iostream>
#include <fstream>
using namespace std;
// filenames can be given as command line arguments
// change the code if you want to read them from standard input
int main(int argc, char* argv[])
{
ifstream inf;
ofstream outf;
size_t counter = 0;
const size_t MAXSIZE = 1024; // MAXSIZE - name of constant
char buffer[MAXSIZE]; // buffer - name of array
// check the command line arguments
// Alternatively you can define: string InpFileName, OutFileName;
// as it is in your code and enter values (cin >>) instead using argv
// if so, you should change inf.open(argv[1]); to inf.open(InpFileName);
// and outf.open(argv[2]); to outf.open(OutFileName);
if (argc != 3)
{
cerr << "Two arguments are required:" << endl
<< " 1) name of existing file (to read)" << endl
<< " 2) name of new file (to create)" << endl;
return 1;
}
// open files
inf.open(argv[1]);
outf.open(argv[2]);
// check files
if (!inf.is_open() || !outf.is_open())
{
cout << "ERROR: some trouble with files." << endl;
return 2; // stop the program
}
// process
// 1) reading
while (counter < MAXSIZE){
buffer[counter] = inf.get();
if (buffer[counter] != EOF)
{
counter++;
}
else
{
counter--; // the last character is not valid
break; // end of file
}
}
// 2) changing
char b = buffer[counter];
buffer[counter] = buffer[0];
buffer[0] = b;
// 3) output
for (int i = 0; i <= counter; i++)
{
outf.put(buffer[i]);
}
// close files
inf.close();
outf.close();
return 0;
}
UPDATE:
Clarify the task for cases when some unprintable character (like space) is the first or the last
Looks like a homework problem for a C++ class. One hint which may help is to
divide the file into blocks of X bytes and read the blocks in reverse order....
std::istream::seekg

Stuck on C++ code using Structure

Currently I am stuck and not sure where to go from here...
I'm supposed to write a program that declares a struct to store the data for a player. Then declare an array of 10 components to store the data for 10 baseball players.
The program reads from a file and stores the data for ten baseball players, including player’s team, name of player, number of homeruns, batting average, and runs batted in.
The program prints out a menu (in a loop, so this can be done again and again) giving the user a choice to:
print out all users and statistics
print out the statistics for a specific player
print out all data for a specific team
update the data for a particular player (change one of the statistics)
Before the program terminates, give the user the option to store the data in an output file.
If anyone has ANY TIPS OR ADVICE I will be very grateful... I'm fairly new to coding in C++ and just stuck here... thank you in advance...
#include <iostream>
#include <fstream>
using namespace std;
struct BaseballID
{
string teamName, playerFirstName, playerLastName;
int homeRuns, rbi;
double batting_average;
};
int main()
{
BaseballID listofplayers[10];
ifstream infile;
infile.open("/users/AlecKleyer/Desktop/computer science term 2/BaseballStats.txt");
if (!infile)
{
cout << "Error opening file!";
return 0;
}
for (int j = 0; j < 10; j++) {
infile >> listofplayers[j].teamName >> listofplayers[j].playerFirstName >> listofplayers[j].playerLastName >>listofplayers[j].homeRuns >> listofplayers[j].rbi >> listofplayers[j].batting_average;
}
cout << "Please Type The Following Letter: ";
cout << "\n(A) For All Users and Stats";
cout << "\n(B) For A Specific Player";
cout << "\n(C) Print out for specific team";
cout << "\n(D) Update stats for a player";
char input = 0;
cin >> input;
if (input == 'A' || input == 'a') {
printInfoAll(*listofplayers[]);
}
if (input == 'B' || input == 'b') {
}
if (input == 'C' || input == 'c') {
}
if (input == 'D' || input == 'd') {
}
}
void printInfoAll(listofplayers1[])
{
for (int i = 0; i < 10; i++) {
cout << &listofplayers[i];
}
}
One thing you did right was making a function of printInfoAll (even if its buggy). Note this will not compile and there might be more errors.
#include <iostream>
#include <fstream>
using namespace std;
struct BaseballID
{
string teamName, playerFirstName, playerLastName;
int homeRuns, rbi;
double batting_average;
};
void printInfo(const BaseballID& id) {
cout << id.teamName << " " << id.playerFirstName // and so on!!!!
<< "\n"; // and a newline.
}
void printInfoAll(const BaseballID listofplayers1[]) // we need a type and a paramter
{
for (int i = 0; i < 10; i++) {
cout << printInfo(listofplayers[i]); // you
}
}
void printMenu() { // factor out the components in easy reusable parts.
cout << "Please Type The Following Letter: ";
cout << "\n(A) For All Users and Stats";
cout << "\n(B) For A Specific Player";
cout << "\n(C) Print out for specific team";
cout << "\n(D) Update stats for a player";
}
int main()
{
BaseballID listofplayers[10]; // consider using std::vector instead
// from here
ifstream infile;
infile.open("/users/AlecKleyer/Desktop/computer science term 2/BaseballStats.txt");
if (!infile.isOpen()) // I think the isOpen is needed.
{
cout << "Error opening file!";
return 0;
}
for (int j = 0; j < 10; j++) {
infile >> listofplayers[j].teamName >> listofplayers[j].playerFirstName >> listofplayers[j].playerLastName >>listofplayers[j].homeRuns >> listofplayers[j].rbi >> listofplayers[j].batting_average;
// hmm you trust your indata I don't check for errors here.
}
// to here should be a function, but then you need to restructure a bit more
printMenu();
char input = 0;
cin >> input;
switch(input) {
case 'A': case 'a':
printInfoAll(*listofplayers[]);
break;
case 'B': // and so on
// code for 'B' and 'b'
break;
....
default:
printMenu();
break;
}
// at this point you will find out you should have put it all in a loop.
return EXIT_SUCCESS;
}
The reason for adding const to the parameters is so that the user of the functions can see it promises not to change the values.

How can you make input take strings and int? c++

is it possible, say your trying to do calculations so the primary variable type may be int... but as a part of the program you decide to do a while loop and throw an if statement for existing purposes.
you have one cin >> and that is to take in a number to run calculations, but you also need an input incase they want to exit:
Here's some code to work with
#include <iostream>
using namespace std;
int func1(int x)
{
int sum = 0;
sum = x * x * x;
return sum;
}
int main()
{
bool repeat = true;
cout << "Enter a value to cube: " << endl;
cout << "Type leave to quit" << endl;
while (repeat)
{
int input = 0;
cin >> input;
cout << input << " cubed is: " << func1(input) << endl;
if (input = "leave" || input = "Leave")
{
repeat = false;
}
}
}
I'm aware they wont take leave cause input is set to int, but is it possible to use a conversion or something...
another thing is there a better way to break the loop or is that the most common way?
One way to do this is read a string from cin. Check its value. If it satisfies the exit condition, exit. If not, extract the integer from the string and proceed to procss the integer.
while (repeat)
{
string input;
cin >> input;
if (input == "leave" || input == "Leave")
{
repeat = false;
}
else
{
int intInput = atoi(input.c_str());
cout << input << " cubed is: " << func1(intInput) << endl;
}
}
You can read the input as a string from the input stream. Check if it is 'leave' and quit.. and If it is not try to convert it to a number and call func1.. look at atoi or boost::lexical_cast<>
also it is input == "leave" == is the equal operator. = is an assignment operator.
int main() {
cout << "Enter a value to cube: " << endl;
cout << "Type leave to quit" << endl;
while (true)
{
string input;
cin >> input;
if (input == "leave" || input == "Leave")
{
break;
}
cout << input << " cubed is: " << func1(atoi(input.c_str())) << endl;
}
}
you can use like
int input;
string s;
cint>>s; //read string from user
stringstream ss(s);
ss>>input; //try to convert to an int
if(ss==0) //not an integer
{
if(s == "leave") {//user don't want to enter further input
//exit
}
else
{
//invalid data some string other than leave and not an integer
}
}
else
{
cout<<"Input:"<<input<<endl;
//input holds an int data
}

Reading string with spaces in c++

How can I read input line(type string) with whitespace? I tried getline but it goes into infinite loop. Following is my code.
#include <iostream>
#include <cstring>
#define MAX 50 //size of array
//Used G++ 4.6.3 compiler
using namespace std;
int main() {
struct Manager {
string name;
int age;
int working_years;
string phone;
int salary;
}info[MAX];
char inp; //To choose options
int array_pos = 0; //Current position in array of Manager structure
string search_name; //Manager name you want to search
cout << "Press 'i' to insert manager information or 's' to search for manager information by name or 'a' to abort: ";
cin >> inp;
while(inp != 'a') {
int search_num = 0; //array position at which search result is found
int found = 0;
if (inp == 'i' || inp == 's') {
if (inp == 'i') {
int k = array_pos;
cout << "Enter the information of the manager no "<<k+1<<" is : ";
cout << "Enter the Name : ";
//infinte loop occurs
getline(info[array_pos].name, '\n');
//cin >> info[array_pos].name;
cout<<"Enter manager age : ";
cin >> info[array_pos].age;
cout << "Enter manage working years : ";
cin >> info[array_pos].working_years;
cout << "Enter manager phone no. : ";
cin >> info[array_pos].phone;
cout << "Enter manager salary : ";
cin >> info[array_pos].salary;
array_pos++;
}
if (inp == 's') {
cout << "Enter the manager name you want to search : ";
cin >> search_name;
for(int i = 0; i < array_pos; i++) {
//using str1.compare(str2) to compare manager name
if(info[i].name.compare(search_name) == 0) { //manager name found in array of structure
found = 1;
search_num = i;
cout << "Name : " << info[search_num].name << "\n";
cout << "Age: " << info[search_num].age << "\n";
cout << "Working Years: " << info[search_num].working_years << "\n";
cout << "Phone No. : " << info[search_num].phone << "\n";
cout << "Salary : " << info[search_num].salary << "\n";
} //end of if loop for comparing string
} //end of for loop for searching
if(found == 0)
cout << "No Manager by this name exist in record" << "\n";
} //end of if loop
} //end of if loop for searching or insertion
if(inp == 'a')
break;
cout << "Press 'i' to insert manager information or 's' to search for manager information by name or 'a' to abort: ";
cin >> inp;
} //end of while loop
return 0;
}
How can I read input line(type string) with whitespace?
std::string line;
if (std::getline(std::cin, line)) {
...
}
Note that apart from checking the return value of std:getline call, you should also avoid mixing >> operator with std::getline calls. Once you decide reading the file line by line, it seems to be cleaner and more reasonable to just make one huge loop and do the additional parsing while using string stream object, e.g.:
std::string line;
while (std::getline(std::cin, line)) {
if (line.empty()) continue;
std::istringstream is(line);
if (is >> ...) {
...
}
...
}
Simplest way to read string with spaces without bothering about std namespace is as follows
#include <iostream>
#include <string>
using namespace std;
int main(){
string str;
getline(cin,str);
cout<<str;
return 0;
}
Solution #1:
char c;
cin >> noskipws; // Stops all further whitespace skipping
while (cin >> c) { // Reads whitespace chars now.
count++;
}
Solution #2:
char c;
while (cin.get(c)) { // Always reads whitespace chars.
count++;
}