Finding a string element in an array C++ - c++

I have found other topics like this, but none of them are working, it keeps returning -1 regardless what I type. Idk why, thanks!
#include <iostream>
#include <string>
using namespace std;
int find(string arr[], int len, string seek)
{
for (int i = 0; i < len; ++i)
{
if (arr[i].find(seek) != string::npos) {
return i;
}
return -1;
}
}
int main() {
string info[] = { "Becky Warren, 678-1223","Joe Looney, 586-0097","Geri Palmer , 223-887","Lynn Presnell, 887-1212","Holly Gaddis, 223-8878","Bob Kain, 586-8712","Tim Haynes, 586-7676","Warren Gaddis, 223-9037", "Jean James , 678-4939","Ron Palmer, 486-2783" };
cout<<"Please enter a name and you will be returned a phone number"<<endl;
string name;
cin>>name;
//for (int i = 0; i<sizeof(info)/sizeof(info[i]);i++) {
int x = find(info,10,name);
cout<<x;
//cout<<info[x]<<endl;
//}
system("pause");
}

Your problem is that your return - 1 should be after for loop. When you check whether your string is somewhere in your array you do it only one time, because of the fact that after an if statement the program sees return - 1 which means "oh I should exit the function now and return -1".
for (int i = 0; i < len; ++i)
{
if (arr[i].find(seek) != string::npos)return i;
}
return -1;
When you got such a simple problems I recommend you to use debugger which will tell you exactly what you are doing in your program.

You can use the function std::string::find available in the standard C++. See this link for an example on how to use it.
In particular it is needed to develop two main steps:
in the function find that you have written you find the index of the array (or vector as in the following example) containing that name;
Then you need to find inside the string found the position of the comma (through find function of standard library) and then extract the substring containing the number which is located two positions after the comma. You can do this using substr function.
Below a sample code using vector instead of array.
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int find(vector<string> arr, string seek)
{
for (int i = 0; i < arr.size(); ++i)
{
if (arr.at(i).find(seek) != string::npos) {
return i;
}
return -1;
}
}
int main()
{
vector<string> info;
info.push_back("Becky Warren, 678-1223");
info.push_back("Joe Looney, 586-0097");
info.push_back("Geri Palmer , 223-887");
info.push_back("Lynn Presnell, 887-1212");
info.push_back("Holly Gaddis, 223-8878");
info.push_back("Bob Kain, 586-8712");
info.push_back("Tim Haynes, 586-7676");
info.push_back("Warren Gaddis, 223-9037");
info.push_back("Jean James , 678-4939");
info.push_back("Ron Palmer, 486-2783" );
cout<<"Please enter a name and you will be returned a phone number"<<endl;
string name;
cin>>name;
// x is the string in the array containing the name written by the user
int x = find(info, name);
// Check if at least one was found
if(x == -1)
{
cout << "Name " << name << " not found." << endl;
return -1;
}
// extract number from the found string (find comma position and then take a substring starting from that position until the end
int commaPosition = info.at(x).find(",");
string phoneNumber = info.at(x).substr(commaPosition+2);
cout<<"Phone number found: " << phoneNumber<< endl;
system("pause");
return 0;
}

Related

C File Handling - Trouble using Strings with Char

Good day, I'm having some trouble with my code. I just started with file handling last week and I'm currently stuck with adding Strings to the program. I would like to add the names in the main program from the file, but I've tried pretty much everything. Any help would be highly appreciated. Also, this is my first time on Stack Overflow, so sorry if I missed posting any information.
The picture includes the Input.txt file as well as the current output. I added console output to test the problem and it seems to have something to do with the characters. I've tried using String itself, but that was still a fail. Also, I'm not allowed to use the C++ way of file handling (if that makes sense). [I am allowed to use C++ though] - Doing this whole program for practice for my upcoming exams.
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string>
using namespace std;
int ReadFile(char*,int*,double*);
int main()
{
char names[128];
int ages[128];
double salaries[128];
int size = ReadFile(names, ages, salaries);
for(int i = 0; i < size; i++)
{
printf("My name is %s, and I am %d years old. My salary is $%.2lf\n", *(names+i), *(ages+i), *(salaries+i));
}
return 0;
}
int ReadFile(char *namesArr, int *ageArr, double *salaryArr)
{
FILE *IN = fopen("Input.txt", "r");
int i = 0;
if(IN == NULL)
{
cout << "Error! Can't open file.";
exit(1);
}
else
{
char name[20];
int age = 0;
double salary = 0.00;
while(fscanf(IN, " %c,%d,%lf", &name, &age, &salary) != EOF)
{
*(namesArr + i) = *name;
*(ageArr + i) = age;
*(salaryArr + i) = salary;
cout << *(namesArr+i) << " ";
i++;
}
}
fclose(IN);
return i;
}
Input.txt:
Kazu,21,2250.00 Anonymous,34,3500.25 John,31,2750.00 Paul,25,3125.25
Jin,19,1750.00
Save time, enable all compiler warnings
My name is %s --> My name is %c
If you want to read in the name, and not just the first letter, many more changes needed too such as:
char name[20];
int age = 0;
double salary = 0.00;
while(fscanf(IN, " %19[A-Za-z'] ,%d ,%lf", &name, &age, &salary) == 3)
{
*(namesArr + i) = *name; // This only copies the first `char`
strcpy(TBD, name); // Need something like this.
// TBD is a pointer to an `char` array
*(ageArr + i) = age;
*(salaryArr + i) = salary;
cout << TBD << " ";
i++;
}

I'm getting this warning sign Array index 4001 is past the end of the array (which contains 4001 elements)

I have two questions
First: When i try to run the code it gives me a warning where it says "Array index 4001 is past the end of the array (which contains 4001 elements)"
Second: I want to read the words from the file and then pass them through the function so i can
add the words to the hash table and index them accordingly and print the count of the unique words from the text file. the size function does that. can someone please help me with this
#include <iostream>
#include <string>
#include <fstream>
#define HASHSIZE 4001
using namespace std;
class entry {
public:
string word;
int frequency;
entry() { frequency = 0; }
};
class Hashtable {
private:
entry entryArr[HASHSIZE];
int updateArr[HASHSIZE];
int costArr[HASHSIZE];
int sizeUnique = 0;
int probeCount;
int updateCount;
public:
int HashKey(string key)
{
int totalsum = 0;
// this function is to assign every word a key value to be stored against.
for (int i = 0; i < key.length(); i++) totalsum += int(key[i]);
return (totalsum % HASHSIZE);
}
void update(string key) {
int k = HashKey(key);
if (entryArr[k].frequency == 0) {
entryArr[k].frequency++;
updateCount++;
probeCount++;
sizeUnique++;
}
// function to enter the unique words in the array
else if (entryArr[k].word == key) {
entryArr[k].frequency++;
probeCount++;
}
while (entryArr[k].frequency != 0 && entryArr[k].word != key) {
k++;
}
if (entryArr[k].word == key) {
entryArr[k].frequency++;
} else {
entryArr[k].word = key;
}
sizeUnique++;
updateCount++;
probeCount++;
}
int probes() {
costArr[HASHSIZE] = probeCount;
return probeCount;
}
int size() // function to count the total number of unique words occuring
{
int count = 0;
updateArr[HASHSIZE] = updateCount;
for (int i = 0; i < HASHSIZE; i++)
if (updateArr[HASHSIZE] != 0) {
count = costArr[i] / updateArr[i];
}
cout << count;
return count;
}
};
int main() {
entry e;
Hashtable h;
ifstream thisfile("RomeoAndJuliet.txt");
if (thisfile.is_open()) {
while (!thisfile.eof) {
h.update(e.word);
}
thisfile.close();
cout << "The total number of unique words are: " << h.size();
}
return 0;
}
An array with 4001 elements has valid indexes 0,1,...,3999,4000 as C++ is indexing from 0.
When i try to run the code it gives me a warning where it says "Array index 4001 is past the end of the array (which contains 4001 elements)"
This is because array index starts with 0 instead of 1. And so an array of size 4001 can be safely indexed(accessed) upto 4000 and not 4001.
I want to read the words from the file and then pass them through the function so i can add the words to the hash table and index them accordingly and print the count of the unique words from the text file
The below program shows how to do this. The program shown below counts how many times a given word occurred in a given input.txt file and then print that count infront of the word.
#include <iostream>
#include <map>
#include <sstream>
#include<fstream>
int main() {
std::string line, word;
//this map maps the std::string to their respective count
std::map<std::string, int> wordCount;
std::ifstream inFile("input.txt");
if(inFile)
{
while(getline(inFile, line, '\n'))
{
std::istringstream ss(line);
while(ss >> word)
{
//std::cout<<"word:"<<word<<std::endl;
wordCount[word]++;
}
}
}
else
{
std::cout<<"file cannot be opened"<<std::endl;
}
inFile.close();
std::cout<<"Total unique words are: "<<wordCount.size()<<std::endl;
for(std::pair<std::string, int> pairElement: wordCount)
{
std::cout << pairElement.first <<"-" << pairElement.second<<std::endl;
}
return 0;
}
The output of this program can be seen here.
Note that(as shown in above example) there is no need to create a separate class for the purpose given in your second question. We can do this(as shown above) literally using 4 to 6 lines(excluding opening and closing the file) of code.

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

Replacing words in a sentence?

I'm trying to replace multiple words with their "pirate pair", for example:
Normal: "Hello sir, where is the hotel?"
Pirate: "Ahoy matey, whar be th' fleagbag inn?"
This is what I tried before:
#include<iostream>
#include<string>
#include<conio.h>
using namespace std;
void speakPirate(string s);
int main()
{
string phrase;
cout << "Enter the phrase to Pirate-Ize: ";
getline(cin, phrase);
speakPirate(phrase);
_getch();
return 0;
}
void speakPirate(string s)
{
int found;
// list of pirate words
string pirate[12] = { "ahoy", "matey", "proud beauty", "foul blaggart", "scurvy dog", "whar", "be", "th'", "me", "yer", "galley", "fleabag inn" };
// list of normal words
string normal[12] = { "hello", "sir", "madam", "officer", "stranger", "where", "is", "the", "my", "your", "restaurant", "hotel" };
for (int i = 0; i < s.length(); i++)
{
found = s.find(normal[i]);
if (found > -1)
{
string left = s.substr(0, found - 1); // get left of the string
string right = s.substr(found + pirate[i].length(), s.length()); // get right of string
s = left + " " + pirate[i] + " " + right; // add pirate word in place of normal word
}
}
cout << s;
}
But it didn't really work and was very buggy, so I tried using the replace() function instead:
#include<iostream>
#include<string>
#include<conio.h>
using namespace std;
void speakPirate(string s);
int main()
{
string phrase;
cout << "Enter the phrase to Pirate-Ize: ";
getline(cin, phrase);
speakPirate(phrase);
_getch();
return 0;
}
void speakPirate(string s)
{
int found;
// list of pirate words
string pirate[12] = { "ahoy", "matey", "proud beauty", "foul blaggart", "scurvy dog", "whar", "be", "th'", "me", "yer", "galley", "fleabag inn" };
// list of normal words
string normal[12] = { "hello", "sir", "madam", "officer", "stranger", "where", "is", "the", "my", "your", "restaurant", "hotel" };
for (int i = 0; i < s.length(); i++)
{
found = s.find(normal[i]);
if (found > -1)
{
s.replace(found, found + pirate[i].length(), pirate[i]);
}
}
cout << s;
}
I'm not sure why, but this doesn't really work either. I also notice that when I try changing a larger word into a smaller word, some of the original word is leftover, for example:
Enter the phrase to Pirate-Ize: hello
ahoyo
And I just noticed that it sometimes might not even change the word at all, for example:
Enter the phrase to Pirate-Ize: where
where
How come? Could someone please tell me what I need to do or a more effective solution that I could implement? Thanks a lot.
Here you iterate over the length of the text:
for (int i = 0; i < s.length(); i++)
It should be the length of the array of texts, something like
for (int i = 0; i < 12; i++)
However, you should use a std::map to model the mapping between the normal words and their pirate version.
std::map<std::string, std::string> words = {
{"hello", "ahoy"},
// .. and so on
};
for(auto const & kvp : words)
{
// replace kvp.first with kvp.second
}
Marius is correct that the major error is that you need to iterate over the length of the arrays. A different way than mapping would be to use erase() and insert() where you used replace(). replace() does not account for the lengths of the strings being different, but removing a substring and then adding in a new substring will. This can be done as follows
for (int i = 0; i < 12; i++)
{
found = s.find(normal[i]);
// Locate the substring to replace
int pos = s.find( normal[i], found );
if( pos == string::npos ) break;
// Replace by erasing and inserting
s.erase( pos, normal[i].length() );
s.insert( pos, pirate[i] );
}

Read two words into one char array element

I am trying to read in two words from text file into one char array element. I CANNOT USE std::string. I get a seg fault because my loop is looping in a way that goes out of bounds. I cannot copy in the two words. please help me do this!! My loop for card struct works perfectly. I cannot get the "first last" into the people[].name
// deck of cards
// below are initializations
#include
#include
#include
#include
#include
using namespace std;
//globals
const int maxCards = 52;
//Structs
struct card {
char suit[8];
char rank[6];
int cvalue;
char location;
};
struct player {
char name[100];
int total;
card hand[4];
};
//program
int main()
{
//constants
char tempfName[100];
char templName[100];
//create struct array(s)
card deck[52];
card shuffledDeck[52];
player people[4];
//create pointers
card * deckPointer =NULL;
deckPointer = deck;
card * shuffledDeckPointer=NULL;
shuffledDeckPointer = shuffledDeck;
for(int i=0;i<4;i++)
{
strcopy(people[i].name,"first last");
}
//open player names file
ifstream fin2;
string fin2Name;
//get file name from user
cout << "Enter player file name...(Players.txt)" << endl;
getline(cin, fin2Name);
//open file
fin2.open(fin2Name.c_str());
//check if Players.txt opens correctly
if(!fin2.good())
{
cout << "Error with player file!" << endl;
return 0;
}
else
{
int j =0;
fin2 >> people[j].name; //prime file
while(fin2.good())
{
//find the length
int index =0, length=0;
while(tempfName[length] != '\0')
{
length++;
}
//now add space after first name
tempfName[length] = ' ';
length++;
while(templName[index] != '\0')
{
tempfName[length] = templName[index];
length++;
index++;
}
tempfName[length]='\0';
int counter =0;
while(templName[counter] != '\0')
{
people[0].name[counter] = templName[counter];
counter++;
}
}
}
it seems your tempfName is not pointing to a correct object in your while loop in else statement
else
{
int j =0;
fin2 >> people[j].name; //prime file
while(fin2.good())
{
//find the length
int index =0, length=0;
while(tempfName[length] != '\0')
{
length++;
}
You could do some cheating:
char full_name[256]; // Binary quantities are better.
snprintf(full_name, sizeof(full_name),
"%s %s",
first_name, last_name);
You should do more research regarding C-style string functions, like check a good reference book. It should have a chapter about the C-style string functions.
Here are some helpful ones:
strcpy, strcat, strchr, sprintf, strlen