Why am I getting this error breaking my program? C++ - c++

I have a program for my c++ class that for some reason keeps breaking when I get to a certain point in my program.
Here is the header file of my
// This class has overloaded constructors.
#ifndef INVENTORYITEM_H
#define INVENTORYITEM_H
#include <string>
using namespace std;
class InventoryItem
{
private:
string description; // The item description
double cost; // The item cost
int units; // Number of units on hand
int inventoryItemNumber; //Used to sort items from first entered to last
public:
// Constructor #1
InventoryItem()
{ // Initialize description, cost, and units.
description = "";
cost = 0.0;
units = 0; }
// Constructor #2
InventoryItem(string desc)
{ // Assign the value to description.
description = desc;
// Initialize cost and units.
cost = 0.0;
units = 0; }
// Constructor #3
InventoryItem(string desc, double c, int u)
{ // Assign values to description, cost, and units.
description = desc;
cost = c;
units = u; }
// Mutator functions
void setDescription(string d)
{ description = d; }
void setCost(double c)
{ cost = c; }
void setUnits(int u)
{ units = u; }
// Accessor functions
string getDescription() const
{ return description; }
double getCost() const
{ return cost; }
int getUnits() const
{ return units; }
};
#endif
And this is my cpp file containing my main:
#include "InventoryItem.h"
#include <iostream>
#include <fstream>
#include <string>
#include <iomanip>
using namespace std;
int main(){
InventoryItem item[1000];
string parsingArray[1000];
char command;
ifstream inFile;
string inFileName;
//The typecasting variables from string to int,string,double,int
//other possible integers ROUND 2
int itemNumber;
string description;
double cost;
int units;
//possible variables:
int count = 0;
int jTracker = 0;
string parsingArray2[1000];
while(true){
cout << "Command: ";
cin >> command; cin.ignore(80, '\n');
if (command == 'a') {
//Add parts: increase the units value for an existing inventory item.
}
else if (command == 'h') {
//Prints Help Text
cout << "Supported commands: \n"
<< " a Add parts.\n"
<< " h print Help text.\n"
<< " i Input inventory data from a file.\n"
<< " p Print invetory list.\n"
<< " n New invetory Item.\n"
<< " o Output invetory data to a file.\n"
<< " q quit (end the program).\n"
<< " r Remove Parts.\n"
<< endl;
}
else if (command == 'i') {
//Input inventory data from a file.
do{
cout << "Enter name of input file: ";
getline(cin, inFileName);
inFile.open(inFileName);
if (inFile.fail())
{
cout << "Failed to open file: " << inFileName << "\n\n";
}
}while(inFile.fail());
//write each line to string
for (int i = 0; inFile; i++) {
getline(inFile, parsingArray[i], '\n');
count++;//count will be needed for counting iterations of for loop for InventoryItem object data field completion
}
for (int k = 0; k < count; k++)
{
int newLine = 0;
int num = 0;
int oldDelimiter = 0, newDelimiter = 0;
int variable = 0;
for (int j = jTracker; num < variable; j++) {//jTracker continues to grow through multiple outer "k" loops.
newDelimiter = parsingArray[k].find("|", oldDelimiter); //newDelimiter becomes the further pipe delimiter in the line.
parsingArray2[j] = parsingArray[k].substr(oldDelimiter, ((newDelimiter)-oldDelimiter));//the pipe delimited strings are isolated in input2[]
oldDelimiter = newDelimiter + 1;//oldDelimiter is set to the next pipe delimiter.
variable = parsingArray[k].length();
//The following alters variables as needed for the next loop
num = newDelimiter;
jTracker = (j + 1);
newLine = j;
}
}
for(int y = 0; y < count; y++)
{
int itemNumber = stoi(parsingArray2[0+(4*y)]);
string description = parsingArray2[1+(4*y)];
double costs = stof(parsingArray2[2+(4*y)]);
int unit = stoi(parsingArray2[3+(4*y)]);
item[itemNumber].setDescription(description);
item[itemNumber].setCost(costs);
item[itemNumber].setUnits(unit);
}
cout << count << " records loaded to array.\n";
}
else if (command == 'p') {
}
else if (command == 'j') {
}
else if (command == 'o') {
}
else if (command == 'q') {
// Quit.
cout << "Exit." << endl;
system("pause");
return 0;
}
else if (command == 'r') {
}
else {
// Invalid user input, re-prompted.
cout << "Invalid command.\n";
}
}
}
The assignment was to create a program that does all the actions described in the help menu. I started with "i" which is to input text files' information into an array of InventoryItem onjects, containing description of item, cost of item and total number of item units. Also, inventoryitem # should be included, but the array spot held by the object is the same as the item number, so a variable isn't needed.
I try running the program, it runs. I type in "i" as my command. It asks for a file to input, I use the file "plumbing.txt". Plumbing.txt contains the following pipe-delimited text:
0|Pump|39.00|20
1|Gasket|1.50|29
2|Water Level Gauge|12.99|30
3|Faucet Repair Kit|4.89|8
4|Teflon Thread Seal Tape (50 ft roll)|3.30|12
5|shutoff valve|6.50|10
Once i hit enter after typing in "plumbing.txt", the program programs.
It looks like this:
"command: i
Enter file name for input: plumbing.txt"
And then the program breaks.
I narrowed down the part of the code to what actually causes the program to break and its something in this part of the code:
for(int y = 0; y < count; y++)
{
int itemNumber = stoi(parsingArray2[0+(4*y)]);
string description = parsingArray2[1+(4*y)];
double costs = stof(parsingArray2[2+(4*y)]);
int unit = stoi(parsingArray2[3+(4*y)]);
item[itemNumber].setDescription(description);
item[itemNumber].setCost(costs);
item[itemNumber].setUnits(unit);
}
Please help me figure out why my program keeps breaking. I cannot figure it out. I'm trying to read the input as strings from the file, parse the strings into individual pieces of data. Convert from string to integer or double using stoi or stof and enter the info into the array of objects. Thank you for reading and any help you can offer.

There are two issues with your code involving the use of for loops when it is better to use while. The first issue involves the block of code:
for (int i = 0; inFile; i++) {
getline(inFile, parsingArray[i], '\n');
count++;//count will be needed for counting iterations of for loop for InventoryItem object data field completion
}
Here, count is incremented even after we have reached the end of the file. As a result, count will be one more than the number of lines in the file. We can use a while loop instead:
while (getline(inFile, parsingArray[count], '\n'))
++count;
Here, getline will set the end-of-file flag for the inFile ifstream when the last line is read so that the while loop exits. With count initialized to zero before this while loop, the resulting count will correctly reflect the number of lines in the file.
The second issue involves the block of code:
for (int j = jTracker; num < variable; j++) {//jTracker continues to grow through multiple outer "k" loops.
newDelimiter = parsingArray[k].find("|", oldDelimiter); //newDelimiter becomes the further pipe delimiter in the line.
parsingArray2[j] = parsingArray[k].substr(oldDelimiter, ((newDelimiter)-oldDelimiter));//the pipe delimited strings are isolated in input2[]
oldDelimiter = newDelimiter + 1;//oldDelimiter is set to the next pipe delimiter.
variable = parsingArray[k].length();
//The following alters variables as needed for the next loop
num = newDelimiter;
jTracker = (j + 1);
newLine = j;
}
As pointed out by others, num and variable are both set to zero before this for loop so that the condition num < variable is never met. Therefore, the code within the for loop is never executed. Again, a while loop here will do:
while ((newDelimiter = parsingArray[k].find("|", oldDelimiter)) != std::string::npos) {
parsingArray2[j] = parsingArray[k].substr(oldDelimiter, ((newDelimiter)-oldDelimiter)); //the pipe delimited strings are isolated in input2[]
oldDelimiter = newDelimiter + 1; //oldDelimiter is set to the next pipe delimiter.
++j; // increment j
}
// get the last token and increment j
parsingArray2[j] = parsingArray[k].substr(oldDelimiter, std::string::npos); //the pipe delimited strings are isolated in input2[]
++j;
Here, find will return std::string::npos if there are no more delimiters (i.e., "|") to find. With j initialized to zero before the outer k for loop, this while loop will parse all tokens delimited by "|" except for the last one. Therefore, after the while loop, we extract the last substring using std::string::npos to denote that we want all characters from oldDelimiter until the end of the string. Note that the variables newLine, num, variable, and jTracker are all not needed.
In fact, we can combine the two while loops to get:
std::string line; // don't need parsingArray any more
int j = 0; // initialize j before looping over file
while (std::getline(inFile, line, '\n')) {
int oldDelimiter = 0, newDelimiter = 0;
while ((newDelimiter = line.find("|", oldDelimiter)) != std::string::npos) {
parsingArray2[j] = line.substr(oldDelimiter, ((newDelimiter)-oldDelimiter)); //the pipe delimited strings are isolated in input2[]
oldDelimiter = newDelimiter + 1; //oldDelimiter is set to the next pipe delimiter.
++j; // increment j
}
// get the last token and increment j
parsingArray2[j] = line.substr(oldDelimiter, std::string::npos); //the pipe delimited strings are isolated in input2[]
++j;
// increment count
++count;
}
which eliminates the need for the outer k for loop. Note also that the array parsingArray is no longer needed as there is no longer a need to store intermediate results accumulated from one loop to be iterated over and used in a subsequent loop.
Additional notes to consider:
Use std::vector instead of fixed size arrays for std::string and InventoryItem.
Declare variables "locally" for reasons discussed in this link.
In the subsequent for loop that sets the items, there is an assumption that the file contains exactly four tokens for each line (and that the tokens are exactly the item number (integer number), description (character string), cost (real number), and unit (integer number) in that order). You should carefully consider what will happen if the file does not satisfy this requirement (i.e., input data error), and how your program should handle all error cases. Maybe the code within that loop can be incorporated within the nested while loops so that errors can be detected and properly handled as the file is being parsed?

Related

find the maximum number of words in a sentence from a paragraph with C++

I am trying to find out the maximum number of words in a sentence (Separated by a dot) from a paragraph. and I am completely stuck into how to sort and output to stdout.
Eg:
Given a string S: {"Program to split strings. By using custom split function. In C++"};
The expected output should be : 5
#define max 8 // define the max string
string strings[max]; // define max string
string words[max];
int count = 0;
void split (string str, char seperator) // custom split() function
{
int currIndex = 0, i = 0;
int startIndex = 0, endIndex = 0;
while (i <= str.size())
{
if (str[i] == seperator || i == str.size())
{
endIndex = i;
string subStr = "";
subStr.append(str, startIndex, endIndex - startIndex);
strings[currIndex] = subStr;
currIndex += 1;
startIndex = endIndex + 1;
}
i++;
}
}
void countWords(string str) // Count The words
{
int count = 0, i;
for (i = 0; str[i] != '\0';i++)
{
if (str[i] == ' ')
count++;
}
cout << "\n- Number of words in the string are: " << count +1 <<" -";
}
//Sort the array in descending order by the number of words
void sortByWordNumber(int num[30])
{
/* CODE str::sort? std::*/
}
int main()
{
string str = "Program to split strings. By using custom split function. In C++";
char seperator = '.'; // dot
int numberOfWords;
split(str, seperator);
cout <<" The split string is: ";
for (int i = 0; i < max; i++)
{
cout << "\n initial array index: " << i << " " << strings[i];
countWords(strings[i]);
}
return 0;
}
Count + 1 in countWords() is giving the numbers correctly only on the first result then it adds the " " whitespace to the word count.
Please take into consideration answering with the easiest solution to understand first. (std::sort, making a new function, lambda)
Your code does not make a sense. For example the meaning of this declaration
string strings[max];
is unclear.
And to find the maximum number of words in sentences of a paragraph there is no need to sort the sentences themselves by the number of words.
If I have understood correctly what you need is something like the following.
#include <iostream>
#include <sstream>
#include <iterator>
int main()
{
std::string s;
std::cout << "Enter a paragraph of sentences: ";
std::getline( std::cin, s );
size_t max_words = 0;
std::istringstream is( s );
std::string sentence;
while ( std::getline( is, sentence, '.' ) )
{
std::istringstream iss( sentence );
auto n = std::distance( std::istream_iterator<std::string>( iss ),
std::istream_iterator<std::string>() );
if ( max_words < n ) max_words = n;
}
std::cout << "The maximum number of words in sentences is "
<< max_words << '\n';
return 0;
}
If to enter the paragraph
Here is a paragraph. It contains several sentences. For example, how to use string streams.
then the output will be
The maximum number of words in sentences is 7
If you are not yet familiar with string streams then you could use member functions find, find_first_of, find_first_not_of with objects of the type std::string to split a string into sentences and to count words in a sentence.
Your use case sounds like a reduction. Essentially you can have a state machine (parser) that goes through the string and updates some state (e.g. counters) when it encounters the word and sentence delimiters. Special care should be given for corner cases, e.g. when having continuous multiple white-spaces or >1 continous full stops (.). A reduction handling these cases is shown below:
int max_words_in(std::string const& str)
{
// p is the current and max word count.
auto parser = [in_space = false] (std::pair<int, int> p, char c) mutable {
switch (c) {
case '.': // Sentence ends.
if (!in_space && p.second <= p.first) p.second = p.first + 1;
p.first = 0;
in_space = true;
break;
case ' ': // Word ends.
if (!in_space) ++p.first;
in_space = true;
break;
default: // Other character encountered.
in_space = false;
}
return p; // Return the updated accumulation value.
};
return std::accumulate(
str.begin(), str.end(), std::make_pair(0, 0), parser).second;
}
Demo
The tricky part is deciding how to handle degenerate cases, e.g. what should the output be for "This is a , ,tricky .. .. string to count" where different types of delimiters alternate in arbitrary ways. Having a state machine implementation of the parsing logic allows you to easily adjust your solution (e.g. you can pass an "ignore list" to the parser and update the default case to not reset the in_space variable when c belongs to that list).
vector<string> split(string str, char seperator) // custom split() function
{
size_t i = 0;
size_t seperator_pos = 0;
vector<string> sentences;
int word_count = 0;
for (; i < str.size(); i++)
{
if (str[i] == seperator)
{
i++;
sentences.push_back(str.substr(seperator_pos, i - seperator_pos));
seperator_pos = i;
}
}
if (str[str.size() - 1] != seperator)
{
sentences.push_back(str.substr(seperator_pos + 1, str.size() - seperator_pos));
}
return sentences;
}

No Instance of overloaded function vector of structs

I creating a project from college where I have to recreate the Scrabble Junior game to a console Game, but I've got a problem and i question in my code.
Firstly, I've got an error in my code saying :
"no instance of overloaded function "std::vector<_Ty, _Alloc>::push_back [with _Ty=Board::Word, _Alloc=std::allocator<Board::Word>]" matches the argument list
argument types are: (Board::Word)
object type is: std::vector<Board::Word, std::allocator<Board::Word>>
The struct Word is this one:
struct Word {
int row;
int column;
char orientation;
int tilesadded = 0; //starts at 0
int wordlength;
bool completed = false;
int currentletterpositiontoAdd[2]; //array to hold the coordenates of the next tile to be added
std::string name;
};
This struct basically stores every word and it's position in the board
And then I have also a vector storing every word struct: std::vector <Word> words;
The code that builds this struct is the following (because I get from a file every word and position to the board):
void Board::GetBoard()
{
std::ifstream file;
std::string filename, input;
std::cout << "----------------------------------------------------------------------------------------" << std::endl << std::endl;
std::cout << "What is the directory of the board file? (.txt is added for you) -> ";
while (std::getline(std::cin, filename))
{
file.open(filename + ".txt");
if (!file.is_open())
{
std::cin.clear();
file.clear();
RED;
std::cerr << "Error reading file." << std::endl;
WHITE;
std::cout << "What is the directory of the board file? (.txt is added for you) -> ";
}
else
break;
}
while (std::getline(file, input))
{
if ((int)input[0] == 49 || (int)input[0] == 50)
{ //this means that its the first line of the file and the first character is either 1 or 2
boardSize = stoi(input.substr(0, 2));
}
else
{
std::string nametoCat;
Word word;
word.row = input[0] - 'A' + 1; //calculation of the position on the board using ascii code ex: input[0] = C so: 'C' -'A' + 1 = 3 row -> 3
word.column = input[1] - 'a' + 1; //calculation of the position on the board using ascii code ex: input[1] = e so: 'e' -'a' + 1 = 5 column -> 5
word.orientation = input[3];
word.currentletterpositiontoAdd[0] = word.row;
word.currentletterpositiontoAdd[1] = word.column;
for (int x = 5; x < 1000000000; x++)
{ //for loop to check the name ending and build a string with the name
if (input[x] == '\0')
break;
else
nametoCat += input[x];
}
word.name = nametoCat;
word.wordlength = word.name.size(); //storing the word length to use later to check if word is completed in board
words.push_back(word);
}
}
}
The file looks like this:
15 x 15
Ak H EGGS
Bg H BUZZ
Ca H MUSIC
Cm H ARM
...
And secondly, I would like to make the code look more "clean" and understandable and remove that 1000000000 from: for (int x = 5; x < 1000000000; x++) and do it another way, but i can't find a solution. Because this 1000000000 looks like a magic number and not a number that would always work, for example, wouldn't work with a word of size 1000000001 (unlikely but possible).
Thank you.

Checking if items from a particular txt file agree to constraints in c++ - Name That Number USACO

I have got some doubts while solving - Name That Number.
It goes like this -
Among the large Wisconsin cattle ranchers, it is customary to brand cows with serial numbers to please the Accounting Department. The cowhands don't appreciate the advantage of this filing system, though, and wish to call the members of their herd by a pleasing name rather than saying, "C'mon, #4734, get along."
Help the poor cowhands out by writing a program that will translate the brand serial number of a cow into possible names uniquely associated with that serial number. Since the cowhands all have cellular saddle phones these days, use the standard Touch-Tone(R) telephone keypad mapping to get from numbers to letters (except for "Q" and "Z"):
2: A,B,C 5: J,K,L 8: T,U,V
3: D,E,F 6: M,N,O 9: W,X,Y
4: G,H,I 7: P,R,S
Acceptable names for cattle are provided to you in a file named "dict.txt", which contains a list of fewer than 5,000 acceptable cattle names (all letters capitalized). Take a cow's brand number and report which of all the possible words to which that number maps are in the given dictionary which is supplied as dict.txt in the grading environment (and is sorted into ascending order).
For instance, brand number 4734 produces all the following names:
GPDG GPDH GPDI GPEG GPEH GPEI GPFG GPFH GPFI GRDG GRDH GRDI
GREG GREH GREI GRFG GRFH GRFI GSDG GSDH GSDI GSEG GSEH GSEI
GSFG GSFH GSFI HPDG HPDH HPDI HPEG HPEH HPEI HPFG HPFH HPFI
HRDG HRDH HRDI HREG HREH HREI HRFG HRFH HRFI HSDG HSDH HSDI
HSEG HSEH HSEI HSFG HSFH HSFI IPDG IPDH IPDI IPEG IPEH IPEI
IPFG IPFH IPFI IRDG IRDH IRDI IREG IREH IREI IRFG IRFH IRFI
ISDG ISDH ISDI ISEG ISEH ISEI ISFG ISFH ISFI
As it happens, the only one of these 81 names that is in the list of valid names is "GREG".
Write a program that is given the brand number of a cow and prints all the valid names that can be generated from that brand number or ``NONE'' if there are no valid names. Serial numbers can be as many as a dozen digits long.
Here is what I tried to solve this problem. Just go through all the names in the list and check which is satisfying the constraints given.
int numForChar(char c){
if (c=='A'||c=='B'||c=='C') return 2;
else if(c=='D'||c=='E'||c=='F') return 3;
else if(c=='G'||c=='H'||c=='I') return 4;
else if(c=='J'||c=='K'||c=='L') return 5;
else if(c=='M'||c=='N'||c=='O') return 6;
else if(c=='P'||c=='R'||c=='S') return 7;
else if(c=='T'||c=='U'||c=='V') return 8;
else if(c=='W'||c=='X'||c=='Y') return 9;
else return 0;
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
freopen("namenum.in","r",stdin);
freopen("namenum.out","w",stdout);
string S; cin >> S;
int len = S.length();
freopen("dict.txt","r",stdin);
string x;
while(cin >> x){
string currName = x;
if(currName.length() != S.length()) continue;
string newString = x;
for(int i=0;i<len;i++){
//now encode the name as a number according to the rules
int num = numForChar(currName[i]);
currName[i] = (char)num;
}
if(currName == S){
cout << newString << "\n";
}
}
return 0;
}
Unfortunately, when I submit it to the judge, for some reason, it says no output produced that is my program created an empty output file. What's possibly going wrong?
Any help would be much appreciated. Thank You.
UPDATE: I tried what Some Programmer Dude suggested by adding a statement else return 0; at the end of the numOfChar function in case of a different alphabet. Unfortunately, it didn't work.
So after looking further at the question and exploring the information for Name That Number. I realized that it is not a current contest, and just a practice challenge. Thus, I updated my answer and also giving you my version of a successful submission. Nonetheless, that is a spoiler and will be posted after why your code was not working.
First, you forgot a } after the declaration of your number function. Secondary, you did not implement anything to check whether if the input fail to yield a valid name. Third, when you use numForChar() on the character of currName, the function yielded an integer value. That is not a problem, the problem is that it is not the ASCII code but is a raw number. You then compare that against a character of the input string. Of which, is an ASCII's value of a digit. Thus, your code can't never find a match. To fix that you can just add 48 to the return value of the numForChar() function or xor the numForChar() return's value to 48.
You are on the right track with your method. But there is a few hints. If you are bored you can always skip to the spoiler. You don't need to use the numForChar() function to actually get a digit value from a character. You can just use a constant array. A constant array is faster than that many if loop.
For example, you know that A, B, C will yield two and A's ASCII code is 65, B's is 66, and C's equal to 67. For that 3, you can have an array of 3 indexes, 0, 1, 2 and all of them stores a 2. Thus, if you get B, you subtract B's ASCII code 65 will yield 1. That that is the index to get the value from.
For getting a number to a character you can have a matrix array of char instead. Skip the first 2 index, 0 and 1. Each first level index, contain 3 arrays of 3 characters that are appropriate to their position.
For dictionary comparing, it is right that we don't need to actually look at the word if the length are unequal. However, besides that, since their dictionary words are sorted, if the word's first letter is lower than the range of the input first letter, we can skip that. On the other hand, if words' first letter are now higher than the highest of the input first letter, there isn't a point in continue searching. Take note that my English for code commenting are almost always bad unless I extensively document it.
Your Code(fixed):
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int numForChar(char c){
if (c=='A'||c=='B'||c=='C') return 2;
else if(c=='D'||c=='E'||c=='F') return 3;
else if(c=='G'||c=='H'||c=='I') return 4;
else if(c=='J'||c=='K'||c=='L') return 5;
else if(c=='M'||c=='N'||c=='O') return 6;
else if(c=='P'||c=='R'||c=='S') return 7;
else if(c=='T'||c=='U'||c=='V') return 8;
else if(c=='W'||c=='X'||c=='Y') return 9;
else return 0;
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
ifstream fin("namenum.in");
ifstream dict("dict.txt");
ofstream fout("namenum.out");
string S;
fin >> S;
int len = S.length();
bool match = false;
string x;
while(dict >> x){
string currName = x;
if(currName.length() != S.length()) continue;
string newString = x;
for(int i=0;i<len;i++){
//now encode the name as a number according to the rules
int num = numForChar(currName[i]) ^ 48;
currName[i] = (char)num;
}
if(currName == S){
fout << newString << "\n";
match = true;
}
}
if ( match == false ){
fout << "NONE" << endl;
}
return 0;
}
Spoiler Code(Improved):
#include <fstream>
#include <string>
using namespace std;
// A = 65
// 65 - 0 = 65
const char wToN[] = {
// A ,B ,C ,D ,E ,F ,G ,H ,I ,
'2','2','2','3','3','3','4','4','4',
// J ,K ,L ,M ,N ,O ,P ,Q ,R ,S
'5','5','5','6','6','6','7','7','7','7',
// T ,U ,V ,W ,X ,Y ,Z
'8','8','8','9','9','9','9'
};
// 2 = {A, B, C} = 2[0] = A, 2[1] = B, 2[2] C
const char nToW[10][3] = {
{}, // 0 skip
{}, // 1
{'A','B','C'},
{'D','E','F'},
{'G','H','I'},
{'J','K','L'},
{'M','N','O'},
{'P','R','S'},
{'T','U','V'},
{'W','X','Y'}
};
int main(){
ifstream fin("namenum.in");
ifstream dict("dict.txt");
ofstream fout("namenum.out");
string S;
fin >> S;
// Since this will not change
// make this a const to make it
// run faster.
const int len = S.length();
// lastlen is last Index of length
// We calculate this value here,
// So we do not have to calculate
// it for every loop.
const int lastLen = len - 1;
int i = 0;
unsigned char digits[len];
unsigned char firstLetter[3];
// If not match print None
bool match = false;
for ( ; i < len; i++ ){
// No need to check upper bound
// constrain did not call for check.
if ( S[i] < '2' ) {
fout << "NONE" << endl;
return 0;
}
}
const char digit1 = S[0] ^ 48;
// There are 3 set of first letter.
// We get them by converting digits[0]'s
// value using the nToW array.
firstLetter[0] = nToW[digit1][0];
firstLetter[1] = nToW[digit1][1];
firstLetter[2] = nToW[digit1][2];
string dictStr;
while(dict >> dictStr){
// For some reason, when keeping the i = 0 here
// it seem to work faster. That could be because of compiler xor.
i = 0;
// If it is higher than our range
// then there is no point contineuing.
if ( dictStr[0] > firstLetter[2] ) break;
// Skip if first character is lower
// than our range. or If they are not equal in length
if ( dictStr[0] < firstLetter[0] || dictStr.length() != len ) continue;
// If we are in the letter range
// we always check the second letter
// not the first, since we skip the first
i = 1;
for ( int j = 1; j < len; j++ ){
// We convert each letter in the word
// to the corresponding int value
// by subtracting the word ASCII value
// to 65 and use it again our wToN array.
// if it does not match the digits at
// this current position we end the loop.
if ( wToN[dictStr[i] - 65] != S[j] ) break;
// if we get here and there isn't an unmatch then it is a match.
if ( j == lastLen ) {
match = true;
fout << dictStr << endl;
break;
}
i++;
}
}
// No match print none.
if ( match == false ){
fout << "NONE" << endl;
}
return 0;
}
I suggest you use c++ file handling. Overwriting stdin and stdout doesn't seem appropriate.
Add these,
std::ifstream dict ("dict.txt");
std::ofstream fout ("namenum.out");
std::ifstream fin ("namenum.in");
Accordingly change,
cin >> S --to--> fin >> S;
cin >> x --to--> dict >> x
cout << newString --to--> fout << newString

extraction of letters at even positions in strings?

string extract(string scrambeledword){
unsigned int index;
string output;
string input= " ";
for (index=0; index <= scrambeledword.length() ; index++);
{
if (index%2==0)
{
output+=input ;
cout << output;
}
}
return output;}
I want to extract the even numbered indexed letters from the 40 letter long word inputted by users. does this make sense? i have not taken arrays yet and do not want to include them.
Problems:
1. You have a ; after your for loop, the loop body is never run.
2. <= is wrong here since scrambeledword.length() is out of range. Use != or < instead.
3. You need to either assign something to input before adding it to output or get rid of it altogether.
4. As #Aconcagua pointed out, it is worth noting that I removed your declaration of index from the function scope and added it only to the for loop scope. If you also considered doing so, compiler would throw an error (since it'd be undeclared outside of the scope of for) and you'd be noted about the ; problem.
Fixed version:
string extract(const string &scrambeledword){ // copying strings is expensive
// unsigned int index; // obsolete
string output;
// string input= " "; // obsolete
for (size_t index = 0; index != scrambeledword.length(); ++index) // `<=` would be wrong since scrambeledword.length() is out of range
{
if (index % 2 == 0)
{
output += scrambeledword[index];
// cout << output; // obsolete. If you just want the characters, print scrambeledword[index]
cout << scrambeledword[index];
}
}
cout << endl; // break the line for better readability
return output;
}
Your code won't run the block under the for because there is a ; at the end of the line. That means the for runs without block. Basically it will count to the length of the given word.
In the for index <= scrambeledword.length() can cause an out of bound exception because you can index out of the string-array. Use index < scrambeledword.length() instead.
This can be a good solution for the problem:
string extract(const string& scrambeledword)
{
string output;
for (unsigned int index = 0; index < scrambeledword.length(); index++)
{
if (index % 2 == 0)
{
output += scrambeledword[index];
}
}
return output;
}
auto str = "HelloWorld"s;
int i = 0;
for_each(str.cbegin(), str.cend(), [&i](char const & c) { if (i++ % 2 == 0) cout << c; });
output: Hlool
You could go with something like this:
for(int i = 0; i < scrambleword.length(); i+=2){
output += scrambleword.at(i);
}

[number]-F appearing at the end of String?

I am a new to c++ and was butchering together a palindrome program at 1am on a Sunday just, because! and I have come across this problem:
Input: test
Reverse: tset3-F
Where has the 3-F come from? Sometimes it's just -F or another number-F. Where is this coming from?
Here is my code:
#include <iostream>
#include <string>
using namespace std;
int main() {
string eString;
int length;
int counter = 0;
cout << "Enter String: ";
cin >> eString;
length = eString.length();
char reverseChar[length];
for(int x = eString.length() -1; x > -1; x--) {
reverseChar[counter] = eString[x];
counter++;
}
cout << "Reverse: " << reverseChar;
}
Many thanks for your time.
You aren't adding a null terminator to the end of your strings. It's random data that happens to be in memory.
reverseChar should be length + 1 in size
The final char should be set to '\0'
reverseChar[length] = '\0';
See: http://en.wikipedia.org/wiki/Null-terminated_string
You need to add a null terminator to the reverseChar string. There is a 0 just after the last character of all strings in C, which tells string manipulation functions where the string ends in memory. The 0 is never included in the length, so you have to remember to add room for it when allocating space for a string.
char reverseChar[length + 1];
for(int x = eString.length() -1; x > -1; x--) {
reverseChar[counter] = eString[x];
counter++;
}
reverseChar[length] = 0;
I think: char reverseChar[length+1] because you need to leave space for the end of string delimiter reverseChar[length]='\0'