accessing data within array of structure in C++ - c++

This is an assignment that required me to use ifstream to stream a CSV file. this csv file contains 52 state names and amount of different resources used by each state. for example:
Alabama,410.20,715.70,169.40,18.00,44.90,309.10,11.90,417.30,64.50,167.40,23.70,0.10,0.40,0.00
then I need to prompt the user to type the state name and the output is the percentage of resources used.
I created a struct containing a string type and an array to store the value of each state and created an array of struct to store multiple state's data, but I am not sure whether my code is right, and I want to know how to access other data, such as the data store in my double array, when the user input a state name.
here is my code:
struct statData
{
string statename;
double StatDataNumber[14];
}DataStruc[51];
int main()
{
ifstream indata;
string line;
statData State;
State.statename;
statData Consumption;
Consumption.StatDataNumber;
indata.open("Data2016.csv"); //opening file
if (indata.fail()) //fail safe
{
cout << "Fail to open file";
exit(1);
}
getline(indata, line); //skipping the first line of the csv file
int i;
int N = 0;
int NLoop;
int Loop = 0;
string InvertValueBefore;
double InvertValueAfter;
char comma;
while (indata.eof()) // before file reache the end
{
for (NLoop = 0; NLoop < 51; NLoop++) // struct array loop
{
{
getline(indata, DataStruc[Loop].statename, ',');// getting statename
for (i = 0; i <= 12; i++) // each group of data, except last
{
indata >> DataStruc[Loop].StatDataNumber[N] >> comma;// storing data in struct
N++;
}
getline(indata, InvertValueBefore); // store last value as string
InvertValueAfter = stoi(InvertValueBefore); // convert it into double
InvertValueAfter = DataStruc[Loop].StatDataNumber[N]; // store it in array of struct
}
Loop++;
}
}
ReadData();
return 0;
}
void ReadData (ifstream& indata , statData DataStruc[] )
{
int i;
string input;
bool stayinloop = true;
cout << "Enter a statename or 'q' to quit\n";
getline(cin, input);
while (stayinloop == true)
{
if (input == "Alabama")
DataStruc[i].statename == "Alabama";
DataStruc[i].StatDataNumber[]
}
}
this code is not finished. Please let me know if you spot any other error. Thank you!

Your code is fine. However, certain points:
1. You just need to get rid of certain variables which are not required.
2. The "eof" function is used to identify if the end of file is reached. For which, you need to use while (!indata.eof()).
3. The "ReadData" method should appear before the main function, however, if you want to have your functions after the main function then first you need to define your function declaration before the main function (i.e. before main function, you can put "void ReadData (ifstream& indata , statData DataStruc[]);"), afterwards you can define your function.
Below is a working version of your requirements.
#include <iostream>
#include <string>
#include <fstream>
#include <stdlib.h>
using namespace std;
struct statData
{
string statename;
double StatDataNumber[3];
}DataStruc[2];
void ReadData (ifstream& indata , statData DataStruc[])
{
string input;
bool stayinloop = true;
while (stayinloop)
{
cout << "\nEnter a statename or 'q' to quit\n";
getline(cin, input);
for (int i = 0 ; i < 2; i++)
{
if (input == DataStruc[i].statename)
{
for(int j = 0 ; j < 3; j++)
{
cout << DataStruc[i].StatDataNumber[j] << ',';
}
}
else if(input == "q")
{
stayinloop = false;
}
}
}
}
int main()
{
ifstream indata;
string tempData = "";
string line;
string InvertValueBefore = "";
double InvertValueAfter = 0.0;
char comma = ',';
indata.open("test.csv"); //opening file
if (indata.fail()) //fail safe
{
cout << "Fail to open file";
}
getline(indata, line); //skipping the first line of the csv file
while (!indata.eof()) // before file reach the end
{
for (int NLoop = 0; NLoop < 2; NLoop++) // struct array loop
{
{
getline(indata, DataStruc[NLoop].statename, comma);// getting statename
for (int i = 0; i < 2; i++) // each group of data, except last
{
getline(indata, tempData, comma);
DataStruc[NLoop].StatDataNumber[i] = atof(tempData.c_str());
}
getline(indata, InvertValueBefore); // store last value as string
InvertValueAfter = atof(InvertValueBefore.c_str()); // convert it into double
DataStruc[NLoop].StatDataNumber[2] = InvertValueAfter;
}
}
}
ReadData(indata, DataStruc);
return 0;
}

Related

Encrypting a String in C++

I am in desperate need of help with my C++ program that is supposed to encrypt a string that the user inputs (source) and saves the encrypted string to another string (destination).
Before the string is encrypted, it runs through the lowerCaseString() function where it converts source to all lowercase. This function works perfectly fine.
Can you help my make my program properly display the encrypted message? I am new to C++.
My error:
terminate called after throwing an instance of 'std::out_of_range'
what(): basic_string::at: __n (which is 0) >= this->size() (which is 0)
#include <iostream>
#include <string>
#include <ostream>
#include <fstream>
#include <sstream>
#include <cctype>
#include <vector>
using namespace std;
string lowerCaseString(string &source);
bool substitution(string &source, string cipherKey, string &destination);
int main()
{
string source;
string cipherKey = "qwertyuiopasdfghjklzxcvbnm";
string destination;
ifstream inFile;
cout << "Please enter a string: " << endl;
cin >> source;
//eventually has to write to a file, but I want to get the cipher part working first
//cin >> cipherKey;
// inFile.open("C:/Users/ellio/OneDrive/Desktop/Freshman Semester 2/ECE 1080C/ECE Labs/otherlabfiles/small-file.txt"); /*make necessary change for
// file access path*/
// if (!inFile){
// cout << "Input file cannot be opened" << endl;
// return 0;
// }
// stringstream buffer;
// buffer << inFile.rdbuf();
// //change to file_string
// source = buffer.str();
lowerCaseString(source);
substitution(source, cipherKey, destination);
cout << destination << endl;
return 0;
}
//converts all letters that are upper case to lower case in source
string lowerCaseString(string &source)
{
unsigned i;
for(i = 0; i < source.size(); ++i)
{
if(isupper(source.at(i)))
{
source.at(i) = tolower(source.at(i));
}
}
return source;
}
//encrypts the source string based on the cipher key, then writes the encrypted string to string destination
bool substitution(string & source, string cipherKey, string &destination)
{
//the boolean function type is irrelevant to my error (I tried to run it with void type), I just have to return true or false if the
//string source is empty
//alphabet is used to compare to each value in source
string alphabet = "abcdefghijklmnopqrstuvwxyz";
unsigned i;
unsigned j;
//this for loop is probably unnecessary but I did it for the purpose of potential debugging
for(i = 0; i < source.size(); ++i)
{
destination.at(i) = source.at(i);
}
//if the string is empty
if(source.size() == 0)
{
return 0;
}
//if the string isn't empty
else
{
for(i = 0; i < source.size(); ++i)
{
for(j = 0; alphabet.at(j) == 'z'; ++j)
{
//if the current character in source is equal to a certain letter in the
//alphabet, write the corresponding value from the cipher key into destination
if(source.at(i) == alphabet.at(j))
{
destination.at(i) = cipherKey.at(j);
}
}
}
//changed this maybe change back
return 1;
}
}
Here is your substitution method working. The destination string was empty, causing the error :
bool substitution(string & source, string cipherKey, string &destination)
{
string alphabet = "abcdefghijklmnopqrstuvwxyz";
destination = source; // To make sure the size of destination is the same as source
if(source.size() == 0)
{
return false;
}
else
{
for(unsigned int i = 0; i < source.size(); ++i) // You can declare i and j in the loop if you want (in c++ not in c)
{
for(unsigned int j = 0; j < alphabet.size(); ++j) // way easier to use size instead of finding 'z'
{
if(source.at(i) == alphabet.at(j))
{
destination.at(i) = cipherKey.at(j);
}
}
}
return true;
}
}
Note that the character finding bit can be reduced to :
bool substitution(string & source, string cipherKey, string &destination)
{
string alphabet = "abcdefghijklmnopqrstuvwxyz";
destination = source; // To make sure the size of destination is the same as source
if(source.size() == 0)
return false;
else
{
for(unsigned int i = 0; i < source.size(); ++i)
destination.at(i) = cipherKey.at(alphabet.find(source.at(i)));
return true;
}
}
You were trying to access destination but it was empty. Try to avoid operating on particular indexes. It could be done like this:
void substituteCharacters(const std::string& source,
const std::string& cipherKey,
std::string& destination)
{
destination.reserve(source.size());//allocate memory once, so no allocation during push_backs
for(auto c : source)
destination.push_back(cipherKey[c-'a']);
}

Using a vector function on a node member

I'm writing a program in C++ where I take in a line from a txt file and stick it into a vector<string> data that is within a struct (I'm making a linked list of each individual line). Technically I have a loop set up that will break up the words from the sentence I'm taking in, and pushing them into the vector one by one.
The issue I've ran into is when I try getting the vector size via
int size;
size = current->data.size();
Current being a node. I get both an implicit conversion warning and a "Thread 1: EXC_BAD_ACCESS (code=EXC_I386_GPFLT)".
Can anyone explain where I am going wrong? Is it just not possible to code something like that? Should I just create a counter variable to keep track of how many words are being placed into the vector? And what would be the best programming practice to go about achieving this?
Here is my main() file
#include <iostream>
#include <fstream>
#include "SkipGram.hpp"
using namespace std;
int main() {
string file;
ifstream inFile;
vector<string> sentence;
string line;
SkipGram control;
int skip;
int gram;
cout << "Please enter file name:\n";
cin >> file;
inFile.open(file);
while(!inFile.is_open()){ //makes sure we get a working file
cout << "Error reading in file. Please try again.";
cin >> file;
inFile.open(file);
}
cout << "Please enter how many words you want skipped and the amount of grams:";
cin >> skip >> gram;
while(!inFile.eof()){
getline(inFile, line);
control.convert(line);
}
control.skipGramFunc(skip, gram);
control.printSkipGram();
return 0;
}
Here is my .hpp file
#include <stdio.h>
#include <iostream>
#include <vector>
#include <string>
using namespace std;
class SkipGram{
public:
SkipGram();
void convert(string line);
void skipGramFunc(int skip, int gram);
void printSkipGram();
private:
typedef struct sentence{
vector<string> data;
vector<string> result;
int position;
sentence* next;
}* sentencePtr;
sentencePtr first;
sentencePtr current;
int amount;
};
Here is my .cpp file
#include "SkipGram.hpp"
using namespace std;
SkipGram::SkipGram(){
first = NULL;
current = NULL;
amount = 0;
}
void SkipGram::convert(string line){
// go word by word through sentence and create a vector out of it
// add into the sentence list
sentencePtr newSentence = new struct sentence;
if(first == NULL){
current = newSentence;
first = newSentence;
amount++;
newSentence->position = amount;
}else {
current = newSentence;
amount++;
newSentence->position = amount;
}
string word;
int length = line.length();
int i = 0;
int front = 0;
int temp;
while( i <= length){
temp = line.find(" ");
if( temp == -1){
break; //catches when sentence is done with
}
word = line.substr(front, temp);
newSentence->data.push_back(word);
temp++;
line = line.erase(front, temp);
} //END OF WHILE
}
void SkipGram::skipGramFunc(int skip, int gram){
// goes through word vector and rearranges them
if(gram == 1){
cout << "Need more than one gram!" << endl;
return;
}
if(skip == 0 || gram == 0){
cout << "Input cannot be 0!";
}
int size;
int temp;
int tempAmount = amount;
current = first;
skip++;
while( tempAmount != 0){ // while loop goes through all the sentences
size = current->data.size();
size = size - skip; // size here essentially becomes a marker to find out where to stop the loop
for(int i = 0; i < size; i++){ // for loop goes through all the words
for(int j = 0; j < gram; j++){ // this loop checks to see if we got the right number of grams
if(j == 0){ // are we on the first gram
current->result.push_back(current->data.at(i));
}else { // we want skipped gram
temp = i + skip;
current->result.push_back(current->data.at(temp));
} // END OF IF
}// END OF GRAM IF
current->result.push_back(",");
}//END OF WORD FOR
current = current->next;
tempAmount--;
}//END OF WHILE
}// END OF FUNCTION
void SkipGram::printSkipGram(){
int tempAmount = amount;
current = first;
while(tempAmount != 0){
int size = current->data.size();
for(int i = 0; i <= size; i++){
cout << current->data.at(i);
};
}//END OF WHILE
}
You never assign to next, but you do read it. Whereupon your program exhibits undefined behavior by way of accessing a value of uninitialized object.

Shifting an array of structs C++

I am quite new to c++ programming and data structures and really need some help. I am working on an assignment where I have a text file with 100 lines and on each line there is an item, a status(for sale or wanted), and a price. I need to go through the text file and add lines to an array of structs and as I add lines I need to compare the new information with the previously submitted information. If there is a line that is wanted and has a price higher than a previously input item that is for sale then the item would be removed from the struct and the array of structs shifted.
The place that I am having trouble is in actually shifting all the structs once a line that satisfies the condition is found.
My issue is that when I try to shift the array of structs using the second for loop nothing happens and I just get null structs and nothing seems to move.
Please if you guys can offer any help it would be greatly appreciated.
Below is the code of the text file and my current code.
#include<iostream>
#include<fstream>
#include <string>
#include <algorithm>
#include <sstream>
using namespace std;
struct items
{
string type;
int status;
int price;
} itemArray [100];
int main(int argc, char *argv[]) {
int x = -1;
//int chickenCount = 0;
int counter = 0;
int itemsSold = 0;
int itemsRemoved = 0;
int itemsForSale = 0;
int itemsWanted = 0;
string itemType;
int itemStatus = 0;
int itemPrice = 0;
int match = 0;
ifstream myReadFile( "messageBoard.txt" ) ;
std::string line;
//char output[100];
if (myReadFile.is_open()) {
while (!myReadFile.eof()) {
getline(myReadFile,line); // Saves the line in STRING.
line.erase(std::remove(line.begin(), line.end(), ' '), line.end());
//cout<<line<<endl; // Prints our STRING.
x++;
std::string input = line;
std::istringstream ss(input);
std::string token;
while(std::getline(ss, token, ',')) {
counter++;
//std::cout << token << '\n';
if (counter>3){
counter =1;
}
//cout << x << endl;
if (counter == 1){
itemType = token;
//cout<< itemType<<endl;
}
if (counter == 2){
if (token == "forsale"){
itemStatus = 1;
//itemsForSale++;
}
if (token == "wanted"){
itemStatus = 0;
//itemsWanted++;
}
//cout<< itemStatus<<endl;
}
if (counter == 3){
itemPrice = atoi(token.c_str());
//cout<< itemPrice<<endl;
}
//cout<<"yo"<<endl;
}
if (x >= 0){
for (int i = 0; i<100;i++){
if (itemArray[i].type == itemType){
//cout<<itemType<<endl;
if(itemArray[i].status != itemStatus){
if (itemArray[i].status == 1){
if(itemPrice>=itemArray[i].price){
itemsSold++;
match =1;
//itemArray[i].type = "sold";
for (int j=i; j<100-1;j++){
//cout<<j<<endl;
itemArray[j].type = itemArray[j+1].type;
itemArray[j].status = itemArray[j+1].status;
itemArray[j].price = itemArray[j+1].price;
}
i =i-1;
break;
}
}
if (itemArray[i].status == 0){
if(itemArray[i].price>=itemPrice){
itemsSold++;
match = 1;
//itemArray[i].type = "sold";
for (int j=i; j<100-1;j++){
//cout<<j<<endl;
itemArray[j].type = itemArray[j+1].type;
itemArray[j].status = itemArray[j+1].status;
itemArray[j].price = itemArray[j+1].price;
}
i=i-1;
break;
}
}
}
}
}
}
if (counter == 3 && match == 0){
itemArray[(x)].type = itemType;
itemArray[(x)].status = itemStatus;
itemArray[(x)].price = itemPrice;
}
match = 0;
// cout << itemArray[x].type << " " << itemArray[x].status<<" "<<itemArray[x].price<<endl;
}
for(int i=0;i<100;i++){
cout<<itemArray[i].type<< " "<<itemArray[i].status<<" "<<itemArray[i].price<<endl;
}
//cout<<itemArray[1].price<<endl;
cout << itemsSold<<endl;
}
myReadFile.close();
return 0;
}
text file: https://drive.google.com/file/d/0B8O3izVcHJBzem0wMzA3VHoxNk0/view?usp=sharing
Thanks for the help
I see several issues in the code, but without being able to test it, I think the main problem is that you always insert new elements at position 'x' which correspond to the currently line read from the file, without taking into account any shift of elements done. You should insert the new element at the first empty slot (or just overwrite the old element instead of shifting everything).
An other issue is that you do not initialize the status and price in your array.
The best way would be to rewrite the code by using more standard C++ features, for example:
replace the items structure by a class with a constructor defining default values
use object copy (there is no need to copy a struct element by element)
use standard C++ containers like a list (see http://www.cplusplus.com/reference/list/list/) which has insert and erase methods

How to search for words in a string in a text file?

I am trying to match words from user input with a string from a text file.
When this code runs, it crashes after the file is opened. (marked by ****)
How can I change it to properly match the strings from user input with strings from the text file.
Any help would be appreciated, thank you.
const int Size = 81; // 80 characters for the line + 1 for the '\0'
const int MaxNumberOfWords = 10;
int main() {
char input[81], temp[81], fin[81];
printf("Input a string\n");
fgets(input, 81, stdin);
int len = strlen(input);
char *div;
div = strtok(input, " ");
while (div != NULL) {
printf("%s\n",div);
div = strtok(NULL, " ");
ifstream inStream; // declare an input stream for my use
char theWords[ MaxNumberOfWords][ Size]; // Array to store words from input line
int wordRow = 0; // Row for the current word
char wordToLookup[ Size]; // word to lookup
bool wordWasFound = false; // flag to track whether or not word is found
char c; // stores return character after input
inStream.open( "C:\\Users\\dqiao4\\Desktop\\Dev-Cpp\\dictionaryMax6.txt");
assert( ! inStream.fail() ); // make sure file open was OK
//*****this is where the code crashes
while ( inStream >> theWords[ wordRow]) {
wordRow++;
}
for (int i=0; i<wordRow; i++) {
// See if this word matches
if ( strcmp( div, theWords[ i]) == 0 ){
wordWasFound = true;
break; // quit looking
}
}
}
}
int main() {
char input[81];int i=0,j=0,k=0;
cout<<"Input a string ";
while(i<=80){
input[i]=getch();
cout<<input[i];
if(input[i]=='.')
break;
i++;
}
ifstream File("C:\\User\\New.txt");
string line;
if(File)
{
while(getline(File, line))
{
char buff[1024];
strcpy(buff, line.c_str());
while(j<35){
k=0;
while(k<i){
if(buff[j]==input[k])
{
int j1=j,k1=k;
while(true){
if(buff[j1]==input[k1])
{
if(input[j1]=='.'){
cout<<"match";
return 0;
}
j1++;k1++;
}
else
break;
}
}k++;
}j++;
cout<<endl;
}
}
}
}
#inlude <sstream>
#include <string>
in your source and read the text file in string stream buffer, convert it to string and do
auto pos = file_in_str.find("word_to_find");
That pos is the the starting index of word in file

C++ Storing Items in Array and Setting each Token

My name is Faith and I am a beginner programmer in C++. I am working on a project where I have to read in two file and be able to separate the items in each file to its own variable. The first file has two pieces of information separated by "," and the second has three pieces of information. So far, I think I've done well with reading the files and getting each line in the file. Also I've separated each item by "," now I am trying to store those items in its on variable. Please Help! I've tried starting this project over multiple times and this is the only method I know how to implement to do this.
#include <stdio.h>
#include <iostream>
#include <fstream>
#include <sstream>
#include <stdlib.h>
using namespace std;
class Manufactuer{
string upcode;
string company_name;
public:
void setupcode(string value){
upcode= value; }
void setcompany_name(string value){
company_name= value; }
string getupcode(){ return upcode;}
string getcompany_name(){return company_name;}
};
class Products{
string product_num;
string quantity;
string product_name;
public:
void setproduct_num(string value){
product_num= value; }
void setproduct_name(string value){
product_name= value; }
void setquantity(string value){
quantity = value;}
string getproduct_num(){ return product_num;}
string getquantity(){return quantity;}
string getproduct_name(){return product_name;}
};
int main(int argc, const char * argv[]) {
//opens the csv file
std::ifstream mccodesfile;
std::ifstream salesfile;
mccodesfile.open("mccodes.csv");
if(!mccodesfile){// file couldn't be opened
cout<<"Failed: file could not be opened"<<endl<<"Press Enter to Close:";
cin.get();
return 0;
}else
cout<<"Successfully opened file!"<<endl;
salesfile.open("sales.csv");
if(!salesfile){// file couldn't be opened
cout<<"Failed: file could not be opened"<<endl<<"Press Enter to Close:";
cin.get();
return 0;
}else
cout<<"Successfully opened file!"<<endl;
Manufactuer* upccodes;
int count; //how many elements in the array
int size; //how large the array
count = 0;
size = 2;
upccodes= (Manufactuer*)malloc(size*sizeof(Manufactuer)); //Malloc dynamatically reserve memory for variable pointer
string line;
while (getline(mccodesfile,line)) {// Taking every line from the file and putting in the variable line
Manufactuer newcode = Manufactuer(); //creating a upcode object
istringstream ss(line);
string token; //setting up split values
bool haveReadUPCode = false;
while (getline(ss,token,',')){// Separated values by comma
if(!haveReadUPCode){
newcode.setupcode(token);
haveReadUPCode = true;
}else{
newcode.setcompany_name(token);
}
}
if (count == size){
size = size * 2;
upccodes= (Manufactuer*)realloc(upccodes,size*sizeof(Manufactuer)); //Double the size while keeping the same elements
}
upccodes[count++]= newcode;
// cout<<line<<endl;
}
for (int i = 0; i<count; i++){
// cout<<upccodes[i].getcompany_name()<<endl; //Prints Manufactuers name--Works!
}
for (int i=0; i<count; i++) {
// cout<<upccodes[i].getupcode()<<endl; //Prints UPCcodes--Works
}
Products* product;
product= (Products*)malloc(size*sizeof(Products)); //Malloc dynamatically reserve memory for variable pointer
while(getline(salesfile, line)){{// Taking every line from the file and putting in the variable line
Products newProduct = Products(); //creating a product object
istringstream ss(line);
string token; //setting up split values
bool haveReadProduct = false;
while (getline(ss,token,',')){// Separated values by comma
if(!haveReadProduct){
newProduct.setproduct_num(token);
haveReadProduct = true;
} else{
newProduct.setproduct_name(token);
newProduct.setquantity(token);
}
}
if (count == size){
size = size * 2;
product= (Products*)realloc(product,size*sizeof(Products)); //Double the size while keeping the same elements
}
product[count++]= newProduct;
//cout<<line<<endl; //LINES ARE Printing!
}
}
for (int i = 0; i<count; i++){
// cout<<product[i].getproduct_name()<<endl; //Prints Product name--Works
}
for (int i = 0; i<count; i++){
//cout<<product[i].getproduct_num()<<endl; //Prints Product number--Works
}
}