Keep getting undeclared identifier I error caesar - c++

I'm working on pset2 from the cs50 course, but I don't understand why I keep getting this error that I didn't declare I, because I think I did.. First I ask for a number to use as a key for the encrypting, than I ask for plain text, which should be encrypted by the number given, and printed out later.
Here's my code:
int main(int argc, string argv[])
{
// get key from command line argument, return 1 if wrong
if (argc < 2)
{
printf("No value entered!\n");
return 1;
}
//store key in integer
int k = atoi(argv[1]);
if (k < 0)
{
printf("No right variable detected\n");
return 1;
}
else
{
printf("Plain text: \n");
string s = get_string();
// iterate over strings in argv
for (int i = 0; n = strlen(s); i < n; i++);
{
if (isalpha(s[i]))
{
// for capitalized letters
if (isupper(s[i]))
{
int a = s[i] - 65;
int b = (a + k) % 26;
int c = b + 65;
printf("%c", c);
}
//for lowercase
else
{
int d = s[i] - 97;
int e = (d + k) % 26;
int f = e + 97;
printf("%c", f);
}
}
else
{
//for non alphabetical characters
printf("%c", s[i]);
}
}
}
// print new line
printf("\n");
return 0;
}

You have a ; at the end of for loop
for (int i = 0; n = strlen(s); i < n; i++);
^
Change it to
for (int i = 0, n = strlen(s); i < n; i++)
Moreover, as you can see init must be placed before the first semicolon ,(comma) separated.
Side notes
You should avoid to use "magic numbers" in code. In your case you can simply use
You should use variable names that can make your code more readable
You can do your ashing with a single variable, not 6
if (isalpha(s[i]))
{
int ashed;
// for capitalized letters
if (isupper(s[i]))
{
ashed = s[i] - 'A';
ashed = (ashed + k) % 26;
ashed += 'A';
}
//for lowercase
else
{
ashed = s[i] - 'a';
ashed = (ashed + k) % 26;
ashed += 'a';
}
printf("%c", ashed);
}

For loop is wrong, it accepts 3 parameters, you set it 4.
Also, notice semicolon after your for loop.
This line:
for (int i = 0; n = strlen(s); i < n; i++);
should be:
for (int i = 0, n = strlen(s); i < n; i++)
Notice comma and no semi-colon at the end

Related

I'm looking for a way to make a function ignore a substring that was already analyzed

Basically, I have this function:
int countFreq(string pat, string txt)
{
int M = pat.length();
int N = txt.length();
int res = 0;
for (int i = 0; i <= N - M; i++)
{
int j;
for (j = 0; j < M; j++)
if (txt[i + j] != pat[j])
break;
if (j == M)
{
res++;
}
}
return res;
}
Which basically checks the number of times a pattern appears in a string. Now, the problem is that if the pattern is "121", and the string is "12121212", it will find 3 "121" substrings ("12121212" and the one in the middle), but I don't want it to do that, it shouldn't take in consideration the one in the middle, so it should only find 2 substrings, not 3.
How should I do something like that?
You can just make the index skip the length of the pattern (minus 1, because it automatically increments by 1) to skip the rest of the string and prevent additional matches.
for (int i = 0; i <= N - M; i++)
{
int j;
for (j = 0; j < M; j++)
if (txt[i + j] != pat[j])
break;
if (j == M)
{
res++;
i += M - 1; // Skip the rest of the string
}
}

Rabin-Karp algorithm in c++

I am trying to understand the implementation of the Rabin-Karp algorithm. d is the number of characters in the input alphabet, but if I replace 0 or any other value instead of 20, it won't affect anything. Why is this happening like this ?
// Rabin-Karp algorithm in C++
#include <string.h>
#include <iostream>
using namespace std;
#define d 20
void rabinKarp(char pattern[], char text[], int q) {
int m = strlen(pattern);
int n = strlen(text);
int i, j;
int p = 0;
int t = 0;
int h = 1;
for (i = 0; i < m - 1; i++)
h = (h * d) % q;
// Calculate hash value for pattern and text
for (i = 0; i < m; i++) {
p = (d * p + pattern[i]) % q;
t = (d * t + text[i]) % q;
}
// Find the match
for (i = 0; i <= n - m; i++) {
if (p == t) {
for (j = 0; j < m; j++) {
if (text[i + j] != pattern[j])
break;
}
if (j == m)
cout << "Pattern is found at position: " << i + 1 << endl;
}
if (i < n - m) {
t = (d * (t - text[i] * h) + text[i + m]) % q;
if (t < 0)
t = (t + q);
}
}
}
int main() {
// char text[] = "ABCCDXAEFGX";
char text[] = "QWERTYUIOPASDFGHJKLXQWERTYUIOPASDFGHJKLX";
char pattern[] = "KLXQW";
int q = 13;
rabinKarp(pattern, text, q);
}
I believe the short answer is that the lower d is the more hash collisions you will have, but you go about verifying the match anyway so it does not affect anything.
A bit more verbose:
First let me modify your code to be have more expressive variables:
// Rabin-Karp algorithm in C++
#include <string.h>
#include <iostream>
using namespace std;
#define HASH_BASE 0
void rabinKarp(char pattern[], char text[], int inputBase) {
int patternLen = strlen(pattern);
int textLen = strlen(text);
int i, j; //predefined iterators
int patternHash = 0;
int textHash = 0;
int patternLenOut = 1;
for (i = 0; i < patternLen - 1; i++)
patternLenOut = (patternLenOut * HASH_BASE) % inputBase; // hash of pattern len
// Calculate hash value for pattern and text
for (i = 0; i < patternLen; i++) {
patternHash = (HASH_BASE * patternHash + pattern[i]) % inputBase;
textHash = (HASH_BASE * textHash + text[i]) % inputBase;
}
// Find the match
for (i = 0; i <= textLen - patternLen; i++) {
if (patternHash == textHash) {
for (j = 0; j < patternLen; j++) {
if (text[i + j] != pattern[j])
break;
}
if (j == patternLen)
cout << "Pattern is found at position: " << i + 1 << endl;
}
if (i < textLen - patternLen) {
textHash = (HASH_BASE * (textHash - text[i] * patternLenOut) + text[i + patternLen]) % inputBase;
if (textHash < 0)
textHash = (textHash + inputBase);
}
}
}
int main() {
// char text[] = "ABCCDXAEFGX";
char text[] = "QWEEERTYUIOPASDFGHJKLXQWERTYUIOPASDFGHJKLX";
char pattern[] = "EE";
int q = 13;
rabinKarp(pattern, text, q);
}
The easiest way to attack it is to set HASH_BASE (previously d) to zero and see where we can simplify. The rabinKarp function can then be reduced to:
void rabinKarp(char pattern[], char text[], int inputBase) {
int patternLen = strlen(pattern);
int textLen = strlen(text);
int i, j; //predefined iterators
int patternHash = 0;
int textHash = 0;
int patternLenOut = 0;
// Calculate hash value for pattern and text
for (i = 0; i < patternLen; i++) {
patternHash = (pattern[i]) % inputBase;
textHash = (text[i]) % inputBase;
}
// Find the match
for (i = 0; i <= textLen - patternLen; i++) {
if (patternHash == textHash) {
for (j = 0; j < patternLen; j++) {
if (text[i + j] != pattern[j])
break;
}
if (j == patternLen)
cout << "Pattern is found at position: " << i + 1 << endl;
}
if (i < textLen - patternLen) {
textHash = (text[i + patternLen]) % inputBase;
if (textHash < 0)
textHash = (textHash + inputBase);
}
}
}
now you'll notice that all the hashes becomes is the sum of the letters mod some number (in your case 13, in my case 2). This is a bad hash, meaning many things will sum to the same number. However, in this portion of the code:
if (patternHash == textHash) {
for (j = 0; j < patternLen; j++) {
if (text[i + j] != pattern[j])
break;
}
if (j == patternLen)
cout << "Pattern is found at position: " << i + 1 << endl;
}
you explicitly check the match, letter by letter, if the hashes match. The worse your hash function is, the more often you will have false positives (which will mean a longer runtime for your function). There are more details, but I believe that directly answers your question. What might be interesting is to record false positives and see how the false positive rate increases as d and q decrease.

Why this function not printing all substrings of string s?

I am trying to print all substring of string but this function not printing all substring can you explain whats wrong?
require o/p= >
a
ab
abc
b
bc
c
curr o/p=>
a
ab
abc
b
void subString(string s, int n)
{
for (int i = 0; i < n; i++) {
for (int len = 1; len <= n - i; len++) {
string str;
for (int k = i; k < len; k++) {
str += s[k];
}
if (str != "")
cout << str << endl;
}
}
}
k is initialized with i (trying to use index in overall string), but the loop condition is compared to len (trying to use index in current substring). This is contradiction. Use either one index.
Use index in overall string:
for (int k = i; k < i + len; k++) {
str += s[k];
}
Use index in current substring:
for (int k = 0; k < len; k++) {
str += s[i + k];
}
Another way is to use the standard substr() (assuming string here is std::string):
str = s.substr(i, len);

Optimizing a program C++

I have to create a program, which counts bursted baloons, like from ZUMA. If I have a line with 3 or more baloons with the same color this sequence will burst. So in input, I have number of ballons (3 <= N <= 10^5) , and line with numbers (line with baloons color (1 <= сi <= 100) ), with 1 sequence for sure. I have to output number of bursted baloons. I have a programm, but it is working longer than 4000msv sometimes. How can I make it working faster?
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int Fmax(int n, const string& f){
int max;
vector<int> k(n);
int i, j, p = 0;
for (i = 0; i <= n; i++)
{
k[i] = 0;
}
for (i = 0; i <= n; i++)
{
for (j = i; j <= n; j++)
{
if (f[i] == f[j])
{
k[p]++;
}
else break;
}
p++;
}
max = k[0];
for (i = 0; i <= p; i++){ if (max <= k[i]){ max = k[i]; } }
return max;
}
string pog(int n){
int d;
string doa;
for (int i = 1; i <= n; i++){
cin >> d;
doa += (char)d;
}
return doa;
}
void main(){
int i, sc = 1, bf = 1;
string f;
int len;
cin >> i;
f = pog(i);
len = i;
while (Fmax(f.length(), f) >= 3){
for (int c = 1; c <= f.length(); c++){
if (f[c] == f[c - 1]){
if (sc == 1){ bf = c - 1; }
sc++;
}
else{
if (sc >= 3){ f.erase(bf, sc); sc = 1; break; }
sc = 1;
}
}
}
cout << len - f.length() << endl;
}
Any help is warmly welcome.
You are leaking memory. Use vectors to avoid that.
Why do you need to create array? Why not use the string directly?
Pass strings which aren't modified by const reference to avoid copies.
Use constant variables for the lengths:
const unsigned int f_length = f.length();
while (Fmax(f_length, f) >= 3){
for (int c = 1; c <= f_length ; c++){
This helps the compiler reduce the number of calls to the length method.

unable to understand why adding zero in end after adding digits

http://www.spoj.com/problems/JULKA/help me solve this question please .explain why we are adding zero in end after addition of bits.as commented in code below
#include <stdio.h>
#include <string.h>
#define MAX 111
char klaudia[MAX], natalia[MAX], total[MAX], diff[MAX];
void calc()
{
int len1 = strlen(total);
int len2 = strlen(diff);
int a, b, c, i, j, k, f;
char temp[MAX];
for(i=len1-1, j=len2-1, k=c=0; i>=0 || j>=0 || c; i--, j--, k++)
{
a = i>=0? total[i]-'0' : 0;
b = j>=0? diff[j]-'0' : 0;
temp[k] = (a+b+c)%10 + '0';
c = (a+b+c)/10;
}
temp[k] = 0;//explain
strcpy(klaudia,"0");
//explain below for loop what is actually being done in this loop//
for(i=k-1, j=a=f=0; i>=0; i--)
{
b = (a*10 + temp[i]-'0') / 2;
a = (a*10 + temp[i]-'0') % 2;
if(b) f = 1;
if(f) klaudia[j++] = b+'0';
}
if(!j) j++;
klaudia[j] = 0;
for(i=len1-1, j=len2-1, k=c=0; i>=0; i--, j--, k++)
{
a = total[i]-'0';
b = j>=0? diff[j]-'0' : 0;
if(a < b+c)
{
temp[k] = (10+a-b-c) + '0';
c = 1;
}
else
{
temp[k] = a-b-c + '0';
c = 0;
}
}
temp[k] = 0;
strcpy(natalia,"0");
for(i=k-1, j=a=f=0; i>=0; i--)
{
b = (a*10 + temp[i]-'0') / 2;
a = (a*10 + temp[i]-'0') % 2;
if(b) f = 1;
if(f) natalia[j++] = b+'0';
}
if(!j) j++;
natalia[j] = 0;
}
int main()
{
while(scanf("%s %s", total, diff)==2)
{
calc();
printf("%s\n%s\n", klaudia, natalia);
}
return 0;
}
why are we adding zeo in array temp after we have added all the digits
You are not computing with number but with character string. In C, character string are terminated by a Nul character whose code is zero.