Converting call from a .txt into a string c++ - c++

I'm trying to read from a text file and then count the number of occurences of each word and then export the results to a different text file. I'm only allowed to use loops and arrays for this assignment. I'm just looking for a slight push in the right direction, primarily in the beginning of the code. It's not compiling correctly!
using namespace std;
#include <iostream>
#include <iomanip>
#include <string>
#include <fstream>
void put(string word, string words[], int counts[], int & size)
{
int w;
for (w = 0; w < size && word >= words[w]; w++);
if (w >= size) {
words[w] = word;
counts[w] = 1;
++size;
}
else if (word < words[w]) {
for (int i = size - 1; i >= w; i--) {
words[i + 1] = words[i];
counts[i + 1] = counts[i];
}
words[w] = word;
counts[w] = 1;
++size;
}
else {
counts[w] = counts[w] + 1;
}
}
int main()
{
int word;
ifstream input("input.txt");
ofstream chout("charcount.txt");
ofstream wout("wordscounts.txt");
int inputSize = sizeof(input) / sizeof(string);
int counts[100];
const int MAX = 100;
string words[MAX];
int wordsSize = 0;
while (input >> word) {
put(input[word], words, counts, wordsSize);
}
wout << " Word Frequency" << endl;
for (word = 0; word < inputSize; ++word) {
wout << setw(10) << words[word] << setw(4) << counts[word] << endl;
}
chout.close();
wout.close();
system("pause");
return 0;
}

This line:
put(input[word], words, counts, wordsSize);
You are trying to index into an ifstream. This is simply not allowed. The compiler (g++ 4.8.4) said:
no match for ‘operator[]’ (operand types are ‘std::ifstream {aka std::basic_ifstream<char>}’ and ‘int’)

Related

I am trying to add large numbers using arrays without using bigint or anything like that. C++

I am trying to add large numbers using arrays without using bigint or anything like that. I can get my program to add the two arrays. However, I need to take the addition of the arrays and output the correct answer like a regular number. I cannot seem to make an algorithm to take the sum of my arrays and ouptut the answer. Does anybody have any tips or suggestions?
#include <iostream>
#include <string>
#include <iomanip>
#include <algorithm>
#include <iterator>
using namespace std;
const int DIGITS = 20;
void readNum(int list[], int& length, string input1);
void reverseArray(int arr[], int start, int end);
void sumNum(int list1[], int numOfElementsList1,
int list2[], int numOfElementsList2);
int main()
{
// Write your main here
string input1;
string input2;
int list[DIGITS];
int list2[DIGITS];
int total[DIGITS];
int input1Length;
int input2Length;
cout << "Please enter your 1st number: " << endl;
cin >> input1;
cout << "Please enter your 2nd number: " << endl;
cin >> input2;
input1Length = input1.length();
input2Length = input2.length();
readNum(list, input1Length, input1);
readNum(list2, input2Length, input2);
reverseArray(list, 0, input1Length);
reverseArray(list2, 0, input2Length);
sumNum(list, input1Length, list2, input2Length);
}
void readNum(int list[], int& length, string input1)
{
int array[DIGITS];
for (int i = 0; i < length; i++)
{
array[i] = input1[i] - '0';
list[i] = array[i];
}
}
void reverseArray(int arr[], int start, int length)
{
int end;
end = length - 1;
while (start < end)
{
int temp = arr[start];
arr[start] = arr[end];
arr[end] = temp;
start++;
end--;
}
}
void sumNum(int list1[], int numOfElementsList1,
int list2[], int numOfElementsList2)
{
int length;
int sum = 0;
int carry = 0;
int total[DIGITS];
if (numOfElementsList1 > numOfElementsList2)
{
length = numOfElementsList1;
}
else
{
length = numOfElementsList2;
}
for (int i = 0; i < length; i++)
{
sum = list1[i] + list2[i] + carry;
if (sum >= 10)
{
sum = sum % 10;
carry = 1;
}
else
{
carry = 0;
}
total[i] = sum;
cout << total[i];
}
}
Strings are arrays of characters, you could just use them as-is. The advantage being... they're just strings, and you can output them as a string just as easily. Not a new technique, it's called a binary coded decimal which in this case is a zoned BCD (where the zone is 0x30 in ASCII, or zone 0xF0 in EBCDIC).
#include <iostream>
#include <string>
#include <stdexcept>
using std::string;
using std::cout;
using std::cin;
using std::runtime_error;
static string sumNum(string, string);
int main() {
string input1;
string input2;
cout << "Please enter your 1st number: ";
cin >> input1;
cout << "Please enter your 2nd number: ";
cin >> input2;
auto sum = sumNum(input1, input2);
cout << "Sum is: " << sum << "\n";
}
string sumNum(string a, string b) {
//a = string(a.rbegin(), a.rend());
//b = string(b.rbegin(), b.rend());
string sum;
auto digit = [carry = 0](int value) mutable {
value += carry;
if (value > 9) {
carry = 1;
value -= 10;
} else {
carry = 0;
}
return static_cast<char>(value + '0');
};
auto num = [](char c) {
if (c < '0' || c > '9') {
throw runtime_error("not a digit");
}
return c - '0';
};
auto aa = a.rbegin();
auto bb = b.rbegin();
while(aa != a.rend() && bb != b.rend()) {
sum.push_back(digit((num(*aa)) + (num(*bb))));
++aa;
++bb;
}
while (aa != a.rend()) {
sum.push_back(digit(num(*aa)));
++aa;
}
while (bb != b.rend()) {
sum.push_back(digit(num(*bb)));
++bb;
}
char last = digit(0);
if (last != '0')
sum.push_back(last);
return string(sum.rbegin(), sum.rend());
}

Parallel vectors in C++

I need some help with the use of parallel vectors. What I want to do is have 2 vectors, 1 containing the alphabet, and the other containing the alphabet the other way around. When someone types in a word, it prints out the word using the inverted alphabet.
This is what I've done up until now and I'm not too sure if I'm on the right track or not:
#include <iostream>
#include <ctype.h>
using namespace std;
void search(char alfab[], char cripto[], int code){
cout << "Introduce your message: " << endl;
cin >> code;
for(int i = 0; i < code; i++)
{
if(code == 0){
cout << "Your code is:" << cripto[i] << endl;
}
}
}
int main(){
char alfab[26] = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};
char cripto[26] = {'z','y','x','w','v','u','t','s','r','q','p','o','n','m','l','k','j','i','h','g','f','e','d','c','b','a'};
char code;
}
Think about how you would do this by hand. Then try to translate those steps to code.
Get user input
for each letter:
decide which letter of your reversed alphabet it is
write that new letter down in the same position as the original
output new string
Try something more like this instead:
#include <iostream>
#include <string>
static const char alfab[26] = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};
static const char cripto[26] = {'z','y','x','w','v','u','t','s','r','q','p','o','n','m','l','k','j','i','h','g','f','e','d','c','b','a'};
std::string invert(const std::string &word){
std::string inverted = word;
for(std::string::size_type i = 0; i < inverted.size(); ++i)
{
char ch = inverted[i];
for(int j = 0; j < 26; ++j)
{
if (alfab[j] == ch)
{
inverted[i] = cripto[j];
break;
}
}
}
return inverted;
}
int main(){
std::string word;
std::cout << "Enter a word: " << std::endl;
std::cin >> word;
std::cout << "Your code is: " << invert(word) << std::endl;
}
You could try using one array:
std::string invert(const std::string& original)
{
static const char cripto[26] =
{
'z','y','x','w',
'v','u','t','s','r',
'q','p','o','n','m',
'l','k','j','i','h',
'g','f','e','d','c',
'b','a'
};
const size_t length = original.length();
std::string inverted_text;
for (unsigned int i = 0; i < length)
{
char c = original[i];
inverted_text += cripto[c - 'a'];
}
return inverted_text;
}
Edit 1: Using some math
You could simplify the encryption (inversion) by using some math.
std::string invert(const std::string& original)
{
const size_t length = original.length();
std::string inverted_text;
for (unsigned int i = 0; i < length)
{
char c = original[i];
inverted_text += (25 - (c - 'a')) + 'a';
}
return inverted_text;
}
Using transform
You could use std::transform:
char invert_char(char c)
{
return (25 - (c - 'a')) + 'a':
}
//...
std::transform(original_word.begin(), original_word.end(),
original_word.begin(), invert_char);

My Boyer-Moore algorithm only searches the first 3000ish characters in my text file

I'm trying to implement a Boyer-Moore string search algorithm. The search algorithm itself seems to work fine, up until a point. It prints out all occurrences until it reaches around the 3300 character area, then it does not search any further.
I am unsure if this is to do with the text file being too big to fit into my string or something entirely different. When I try and print the string holding the text file, it cuts off the first 185122 characters as well. For reference, the text file is Lord of the Rings: Fellowship of the Ring - it is 1016844 characters long.
Here is my code for reference:
#include <fstream>
#include <iostream>
#include <algorithm>
#include <vector>
#include <chrono>
using namespace std;
# define number_chars 256
typedef std::chrono::steady_clock clocktime;
void boyer_moore(string text, string pattern, int textlength, int patlength) {
clocktime::time_point start = clocktime::now();
vector<int> indexes;
int chars[number_chars];
for (int i = 0; i < number_chars; i++) {
chars[i] = -1;
}
for (int i = 0; i < patlength; i++) {
chars[(int)pattern[i]] = i;
}
int shift = 0;
while (shift <= (textlength - patlength)) {
int j = patlength - 1;
while (j >= 0 && pattern[j] == text[shift + j]) {
j--;
}
if (j < 0) {
indexes.push_back(shift);
if (shift + patlength < textlength) {
shift += patlength - chars[text[shift + patlength]];
}
else {
shift += 1;
}
}
else {
shift += max(1, j - chars[text[shift + j]]);
}
}
clocktime::time_point end = clocktime::now();
auto time_taken = chrono::duration_cast<chrono::milliseconds>(end - start).count();
for (int in : indexes) {
cout << in << endl;
}
}
int main() {
ifstream myFile;
//https://www.kaggle.com/ashishsinhaiitr/lord-of-the-rings-text/version/1#01%20-%20The%20Fellowship%20Of%20The%20Ring.txt
myFile.open("lotr.txt");
if (!myFile) {
cout << "no text file found";
}
string text((istreambuf_iterator<char>(myFile)), (istreambuf_iterator<char>()));
cout << text;
string pattern;
cin >> pattern;
int n = text.size();
int m = pattern.size();
boyer_moore(text, pattern, n, m);
}
I have tried to do some researching about what could be the cause but couldn't find anyone with this particular issue. Would appreciate any nudges in the right direction.

Simple binary search doesn't work for me. I am trying to search for a word from text file

I built a program in C++ that takes words from txt file and inputs into program. Program then stores these words into array. Now, I want to search a specific word among the array using binary search.
My txt file has the following words:
hello
world
hi
how
are
you
i
am
fine
thank
welcome
#include <iostream>
#include <fstream>
#include <string>
#include <cstring>
using namespace std;
int binarySearch(string words[], const string& x,int n)
{
int l = 0 ;
int r = n - 1;
while (l <= r)
{
int m = l + (r - l) / 2;
int res;
if (x == (words[m]))
res = 0;
// Check if x is present at mid
if (res == 0)
return m;
// If x greater, ignore left half
if (x > (words[m]))
l = m + 1;
// If x is smaller, ignore right half
else
r = m - 1;
}
return -1;
}
int main () {
ifstream inFile;
inFile.open("test.txt");
if(inFile.fail()){
cerr << "Error opening file"<< endl ;
exit(1);
}
string x1;
string words[100];
int count=0,i=0;
string str;
while( !inFile.eof()) {
inFile >> x1;
words[i]=x1;
count++;
i++;
}
for (i=0;i<100;i++){
cout<< words[i]<<endl;
}
string x;
x = "how";
int n = 14;
int result = binarySearch(words , x,n);
if (result == -1)
cout << ("\nElement not present");
else
cout << ("Element found at index ") << result;
return 0;
}
I can't find the words except Hello which is the first word. So please help me.
hopefully this work
#include <iostream>
#include <fstream>
#include <string>
#include <cstring>
using namespace std;
int binarySearch(string words[], const string& x, int n)
{
int l = 0;
int r = n - 1;
while (l <= r)
{
int m = l + (r - l) / 2;
int res = 0;
if (x == (words[m]))
res = 0;
// Check if x is present at mid
if (res == 0)
return m;
// If x greater, ignore left half
if (x > (words[m]))
l = m + 1;
// If x is smaller, ignore right half
else
r = m - 1;
}
return -1;
}
int main() {
ifstream inFile;
inFile.open("test.txt");
if (inFile.fail()) {
cerr << "Error opening file" << endl;
exit(1);
}
string x1;
string words[100];
int count = 0, i = 0;
string str;
while (!inFile.eof()) {
inFile >> x1;
words[i] = x1;
count++;
i++;
}
for (i = 0; i < 100; i++) {
cout << words[i] << endl;
}
string x;
x = "fine";
int n = 11;
int result = binarySearch(words, x, n);
if (result == -1)
cout << ("\nElement not present");
else
cout << ("Element found at index ") << result;
return 0;
}

Splitting char array into other arrays for using it later and ignoring numbers c++

So I have this assignment where you have to reposition letters in a char array by given number of repositions. The last letter must become first. For example:
Input: Hello 3
Output: lloHe
But if you have a sentence, you have to do it for each word seperately and, what is more, if there are numbers, you must ignore them. So I have trouble dealing with the check for numbers and dealing with seperate words(I use strtok to split them). This is what I have so far:
#include <iostream>
#include <cstring>
using namespace std;
void Reposition(char text[10000], int n, char result[10000])
{
int startIndex = strlen(text)-1;
int k = n-1;
int currentIndex = 0;
for(int i = 0; i < n; i++)
{
result[k] = text[startIndex];
k--;
startIndex--;
currentIndex++;
}
for(int i = 0; i <= startIndex; i++)
{
result[currentIndex] = text[i];
currentIndex++;
}
}
int main()
{
char text[10000];
cin.getline(text,10000);
int n;
cin >> n;
char result[10000];
char *words;
words = strtok(text, " .,");
while(words != NULL)
{
Reposition(text, n, result);
words = strtok(NULL, " .,");
}
for(unsigned i = 0; i <= strlen(result); i++)
cout << result[i];
return 0;
}
Use std::string instead of C-style string
To remove numbers from a string, use std::remove_if from <algorithm>:
std::string s;
. . .
s.erase(std::remove_if(s.begin(), s.end(), ::isdigit), s.end());
To reposition characters in a string, use std::rotate:
std::rotate(s.begin(), s.begin() + 1, s.end());
I did your homework.
Don't know if you are familiar with all this code.
I Also rewrote your reposition code. It looked very messy.....
One time favour from me. Try to learn something from this.
#include <iostream>
#include <cstring>
#include <ctype.h>
using namespace std;
void Reposition(char * text, int len, int n, char * result)
{
int k = n - 1;
for(int i = 0; i < len; i++)
{
result[i] = text[k++];
if(k == len) k = 0;
}
}
int main()
{
char text[10000];
cin.getline(text,10000);
int n;
cin >> n;
char result[10000];
char * word;
char * beginOfWord = text;
char * resultPointer = result;
int wordLen;
while(* beginOfWord)
{
// copy up to somthing from the alphabet
if(!isalpha(* beginOfWord))
{
*resultPointer++ = * beginOfWord++;
continue;
}
// Find the end of this word
word = strpbrk(beginOfWord, " .,0123456789");
if(word != NULL)
{
// len is distance between end of word and begin of word
wordLen = word - beginOfWord;
}
else
{
// Maybe it is the end of the string
wordLen = strlen(beginOfWord);
}
//reposition the word
Reposition(beginOfWord, wordLen, n, resultPointer);
// Move the pointers beyond the word
beginOfWord += wordLen;
resultPointer += wordLen;
}
//Always terminate
*resultPointer ='\x0';
cout << result;
return 0;
}
//reverse will reverse the string starting at position xn and ending at position (yn-1)
void reverse(char *str, int xn, int yn)
{
//positioning the pointers appropriately
char *start = str + xn;
char *end = str + yn - 1;
char temp;
while(start < end)
{
temp = *start;
*start = *end;
*end = temp;
++start;
--end;
}
}
//one of the logic to reposition
void reposition(char *str, int n)
{
int length = strlen(str);
n = (length > n) ? n : (n % length);
reverse(str, 0, n);
reverse(str, n, length);
reverse(str, 0, length);
}
int main()
{
char text[10000];
cin.getline(text,10000);
int n;
cin >> n;
char result[10000];
strcpy(result, text);
cout << "before: " << result << endl;
char *word;
word = strtok(text, " .,");
while(word != NULL)
{
//check if it is not a number
if(isdigit(word[0]) == 0)
{
reposition(word, n);
//find the word postion in text
int word_position = word - text;
//copy the repositioned word in result at its corresponding position.
int i = 0;
while(word[i])
{
result[word_position + i] = word[i];
++i;
}
}
word = strtok(NULL, " .,");
}
cout << "after : " << result << endl;
return 0;
}
Output:
abcd 345 pqrst 321
3
before: abcd 345 pqrst 321
after : dabc 345 stpqr 321