Why does 'a' prematurely end this loop? - c

Pointers rather than straight answers if you will please.
This loop does some manipulation on chars and outputs a ciphertext c based on a key k and some plaintext p.
When 'a' or 'A' comes up in the plaintext, the program will output that letter as expected but then end the loop prematurely.
p suddenly becomes just one character long, this character being 1.
while (i < strlen(p))
{
char stdp = p[i];
char stdk = k[j];
if (isalpha(stdp))
{
if (islower(stdp))
{
p[i] = stdp - 'a';
Aa = 0;
}
else
{
p[i] = stdp - 'A';
Aa = 1;
}
if (islower(k[j]))
{
k[j] = stdk - 'a';
}
else
{
k[j] = stdk - 'A';
}
}
if (isalpha(stdp))
{
c[i] = ((p[i] + k[j]) % 26);
}
else
{
c[i] = p[i];
}
if (isalpha(stdp))
{
if (Aa == 1)
{
c[i] = c[i] + 'A';
}
else if (Aa == 0)
{
c[i] = c[i] + 'a';
}
}
if (isalpha(stdp))
{
if (j + 1 == kk)
{
j = (j + 1) % kk;
strcpy(k, argv[1]);
}
else
{
j++;
}
}
i++;
}

I have now solved the issues I was facing with the program terminating early.
Most of the issues seem to have been solved by stopping the constant refs to strlen(p) and just assigning that to a static variable. I have tried to tidy up the code as suggested.
int main(int argc, char *argv[])
{
if (argc != 2 || argv[1] == NULL)//no more than 1 arg and not empty
{
printf("Command requires one argument to run.\n");
return 1;
}
char *k = malloc(100);
strcpy(k, argv[1]);
int kInt = strlen(k);
for (int i = 0, n = kInt; i < n ; i++)// iterating though the key to check it is alphabetic
{
if (isalpha(k[i]) == false)
{
printf("Make sure key is alphabetic!\n");
return 1;
}
}
printf ("plaintext: ");
char *p = malloc(100);
strcpy(p, get_string());
int pInt = strlen(p);
int i = 0;
int j = 0;
int Aa = 0;
char *c = malloc(100);
while (j < kInt)
{
if (islower(k[j]))
{
k[j] = k[j] - 'a';
}
else
{
k[j] = k[j] - 'A';
}
j++;
}
j = 0;
while (i < pInt)
{
if (isalpha(p[i]))
{
if (islower(p[i]))
{
p[i] = p[i] - 'a';
Aa = 0;
}
else
{
p[i] = p[i] - 'A';
Aa = 1;
}
c[i] = ((p[i] + k[j]) % 26);
if (Aa == 1)
{
c[i] = c[i] + 'A';
}
else if (Aa == 0)
{
c[i] = c[i] + 'a';
}
if (j + 1 == kInt)
{
j = (j+1) % kInt;
}
else
{
j++;
}
}
else if (isalpha(p[i]) != true)
{
c[i] = p[i];
}
i++;
}
printf("ciphertext: %s\n", c);
free(c);
free(k);
free(p);
}

Related

Checking NULL pointer segmentation fault in C

I have to split an initial char and create a list of said char which has to end with a NULL so i can iterate over in the main without knowing list size. The problem is that i get a seg fault whenever i try to check if last element is NULL. i am sorry i am still trying to learn both C and english. Thank you all
#include <stdlib.h>
#include <stdio.h>
char **split(const char *s) {
char **split;
unsigned m_size = 0, c_size, i, j, k;
// get s size
for (i = 0; s[i] != '\0'; i++) {
if (s[i] == ' ') {
m_size++;
}
}
m_size++;
split = (char**) malloc(sizeof(char) * (m_size + 1));
int sizes[m_size];
c_size = 0;
// get s words size
for (i = 0, j = 0; s[i] != '\0'; i++) {
if (s[i] == ' ') {
c_size++;
sizes[j] = c_size;
c_size = 0;
j++;
} else {
c_size++;
}
}
sizes[j] = c_size;
for (i = 0; i < m_size; i++) {
split[i] = (char *) malloc(sizeof(char) * sizes[i]);
}
split[i] = NULL;
for (i = 0, j = 0, k = 0; s[i] != '\0'; i++) {
if (s[i] != ' ') {
split[j][k] = s[i];
k++;
} else {
split[j][k] = '\0';
j++;
k = 0;
}
}
return split;
}
int main() {
char s[19] = "hello how are you?";
char **splitted;
unsigned i;
splitted = split(s);
if (splitted == NULL) {
return 1;
}
for (i = 0; splitted[i]!=NULL; i++) {
printf("%s\n", splitted[i]);
}
return 0;
}
EDIT
#include <stdlib.h>
#include <stdio.h>
char **split(const char *s) {
char **r;
unsigned word_size = 0;
unsigned list_size = 0, i, j, k;
// get s size
for (i = 0; s[i] != '\0'; i++) {
if (s[i] != ' ') {
word_size++;
} else {
if (word_size > 0) {
list_size++;
word_size = 0;
}
}
}
list_size++;
r = malloc(sizeof(*r) * (list_size + 1));
int char_sizes[list_size];
for (i = 0; i < list_size; char_sizes[i] = 0, i++);
// get s words size
for (i = 0, j = 0; s[i] != '\0'; i++) {
if (s[i] != ' ') {
char_sizes[j]++;
} else {
if (char_sizes[j] > 0) {
j++;
}
}
}
for (i = 0; i < list_size; i++) {
r[i] = malloc(sizeof(char) * char_sizes[i]);
}
r[i] = NULL;
for (i = 0, j = 0, k = 0; s[i] != '\0'; i++) {
if (s[i] != ' ') {
r[j][k] = s[i];
k++;
} else {
if (k > 0) {
r[j][k] = '\0';
j++;
k = 0;
}
}
}
return r;
}
void destroy(char **list) {
unsigned i;
for (i = 0; list[i] != NULL; i++) {
free(list[i]);
}
free(list);
}
int main() {
char s[100] = " hello guys how are? you,d 31 3 ";
char **splitted;
unsigned i;
splitted = split(s);
if (splitted == NULL) {
return 1;
}
for (i = 0; splitted[i]!=NULL; i++) {
printf("%s", splitted[i]);
}
destroy(splitted);
return 0;
}
ok guys i followed your tips and i edited my code. leaving this here if someone wants to point out other errors i will appreciate. now it should work even with multiple spaces. thanks to all
Your are requesting an "array" of pointers to char, but you are allocating an "array" of chars:
split = (char**) malloc(sizeof(char) * (m_size + 1));
should become
split = malloc(sizeof(char*) * (m_size + 1));
Note the sizeof(char*). BTW: Note that in C, you should not cast the result of malloc as explained in this SO post.

Adding two really large numbers in C

I am trying to add two really large numbers (say 30 digit long) in C. Here is my code:
#include <stdio.h>
#include <string.h>
int main()
{
char a[30] =
{
'1','1','1','1','1','1','1','1','1','1','1','1','1','1','1',
'1','1','1','1','1','1','1','1','1','1','1','1','1','1','1'
. };
b[30] =
{
'8','8','8','8','8','8','8','8','8','8','8','8','8','8','8',
'8','8','8','8','8','8','8','8','8','8','8','8','8','8','8'
};
int i, j, k, carry = 0, sum[1001];
if(strlen(a) >= strlen(b))
{
k = strlen(a);
}
else
{
k = strlen(b);
}
for(i = strlen(a); i > 0; i--)
{
for(j = strlen(b); j > 0; j--)
{
sum[k] = (a[i]-'0') + (b[j]-'0') + carry;
carry = sum[k]/10;
k--;
}
}
for(i = 0; i < k; i++)
{
printf("%d", sum[i]);
}
printf("\n");
return 0;
}
but it gives me no answer at all. What is wrong with it?
Small change to the code above to take care of the last trailing carry value if it > 0:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(){
int temp = 0;
char *fp ;
char *sp ;
char bigger = '\n';
char a[10] =
{
'1','2','3','4','5','6','7','8','9','1'
};
char b[10] =
{
'9','8','9','8','9','8','9','8','9','8'
};
int i, c, j, k, carry = 0, sum[1001] = {0};
if(sizeof(a) > sizeof(b))
{
k = sizeof(a);
j = sizeof(b);
bigger = 'a';
}
else
{
k = sizeof(b);
j = sizeof(a);
bigger = 'b';
}
c = k;
fp = malloc(k);
sp = malloc(j);
if (bigger == 'a')
{
strncpy(fp, a, k);
strncpy(sp, b, j);
}
else
{
strncpy(fp, b, k);
strncpy(sp, a, j);
}
for(i = strlen(fp); i > 0; i--,j--)
{
if(j>0 )
{
temp = *(fp+i-1)-'0' + *(sp+j-1)-'0' + carry;
if(temp < 10)
{
sum[k] += temp;
carry = 0;
}
else
{
sum[k] += temp%10;
carry = temp/10;
}
}
else
{
temp = *(fp+i-1)-'0' + carry;
if(temp < 10)
{
sum[k] += temp;
carry = 0;
}
else
{
sum[k] += temp%10;
carry = temp/10;
}
}
k--;
}
if(carry > 0)
printf("%d", carry);
for(i = 1; i <= c; i++)
{
printf("%d", sum[i]);
}
printf("\n");
return 0;
}
This should work. I changed the way your loops should work and also added some checks to ensure alignment and consistency in case the length of the large numbers change.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int temp = 0;
char *fp ;
char *sp ;
char bigger = '\n';
char a[30] =
{'1','1','1','1','1','1',
'1','1','1','1','1','1',
'1','1','1','1','1','1','1','1','1','1','1','1','1',
'1','1','1','1','1'
};
char b[30] =
{
'8','8','8','8','8','8','8','8','8','8','8','8','8','8',
'8','8','8','8','8','8','8','8','8','8','8','8','8','8',
'8','8'
};
int i, c, j, k, carry = 0, sum[1001] = {0};
if(sizeof(a) > sizeof(b))
{
k = sizeof(a);
j = sizeof(b);
bigger = 'a';
}
else
{
k = sizeof(b);
j = sizeof(a);
bigger = 'b';
}
c = k;
fp = malloc(k);
sp = malloc(j);
if (bigger == 'a')
{
strncpy(fp, a, k);
strncpy(sp, b, j);
}
else
{
strncpy(fp, b, k);
strncpy(sp, a, j);
}
for(i = strlen(fp); i > 0; i--,j--)
{
if(j>0 )
{
temp = *(fp+i-1)-'0' + *(sp+j-1)-'0' + carry;
if(temp < 10)
{
sum[k] += temp;
carry = 0;
}
else
{
sum[k] += temp%10;
carry = temp/10;
}
}
else
{
temp = *(fp+i-1)-'0' + carry;
if(temp < 10)
{
sum[k] += temp;
carry = 0;
}
else
{
sum[k] += temp%10;
carry = temp/10;
}
}
k--;
}
if(carry > 0)
printf("%d", carry);
for(i = 1; i <= c; i++)
{
printf("%d", sum[i]);
}
printf("\n");
return 0;
}

CS50 Vigenere's Cipher: Can't fix the problem with the spaces in the plaintext

I'm having a problem with my code, which is supposed to be the
Vigenere's cipher from Harvard's CS50 program. I have met all the
requirements, except when the key is "baz" and the plaintext is "hello,
world!". Because there is a comma and a space, my code accepts that, and
shifts from z to a to b, etc. I want it to ignore the spaces and
punctuation so that the "b" "a" "z" only change for the characters.
You should only have to look at the first "else if" line, as that is
when the plaintext is longer than the key, and the key will have to
alternate.
Please help! I've been on this problem for hours, and I can't figure out
the solution.
https://gyazo.com/3a7b3e692d210262ae15f580b10f296d
https://gyazo.com/0b25bfc010d937840f09ff4294d0dd41
https://gyazo.com/c1b85208ecae1b9ad57d48d5b5af59b5
This is my code:
#include <stdio.h>
#include <cs50.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
int main(int argc, string argv[])
{
if (argc == 2)
{
string key = argv[1];
int key_length = strlen(key);
for (int i = 0; i < key_length; i++)
{
key[i] = toupper(key[i]);
}
for (int k = 0; k < key_length; k++)
{
if (key[k] < 'A' || key[k] > 'Z')
{
printf("Not a valid key!\n");
return 1;
}
}
for (int i = 0; i < key_length; i++)
{
key[i] = key[i] - 'A';
}
string plain = get_string("Plaintext: ");
int plain_length = strlen(plain);
if (key_length == plain_length)
{
for (int i = 0; i < key_length; i++)
{
if (islower(plain[i]))
{
for (int q = 0; q < key[i]; q++)
{
plain[i]++;
if (plain[i] > 'z')
{
plain[i] = 'a';
}
}
}
if (isupper(plain[i]))
{
for (int q = 0; q < key[i]; q++)
{
plain[i]++;
if (plain[i] > 'Z')
{
plain[i] = 'A';
}
}
}
}
printf("ciphertext: %s\n", plain);
}
else if (key_length < plain_length)
{
float truncate_not = plain_length / key_length;
int truncate = trunc(truncate_not);
int mod = strlen(plain) % key_length;
for (int i = 0; i < truncate; i++)
{
for (int k = 0; k < key_length; k++)
{
int pos = k + (i * key_length);
if (islower(plain[pos]))
{
for (int q = 0; q < key[k]; q++)
{
plain[pos]++;
if (plain[pos] > 'z')
{
plain[pos] = 'a';
}
}
printf("%c\n", plain[pos]);
}
else if (isupper(plain[pos]))
{
for (int q = 0; q < key[k]; q++)
{
plain[pos]++;
if (plain[pos] > 'Z')
{
plain[pos] = 'A';
}
}
printf("%c\n", plain[pos]);
}
else
{
printf("error\n");
}
}
}
for (int j = 0; j < mod; j++)
{
int pos = j + (truncate * key_length);
if (islower(plain[pos]))
{
for (int q = 0; q < key[j]; q++)
{
plain[pos]++;
if (plain[pos] > 'z')
{
plain[pos] = 'a';
}
}
}
else if (isupper(plain[pos]))
{
for (int q = 0; q < key[j]; q++)
{
plain[pos]++;
if (plain[pos] > 'Z')
{
plain[pos] = 'A';
}
}
}
else
{
plain[j] = plain[j];
}
}
printf("ciphertext: %s\n", plain);
}
else
{
int mod = plain_length % key_length;
for (int i = 0; i < mod; i++)
{
if (islower(plain[i]))
{
for (int q = 0; q < key[i]; q++)
{
plain[i]++;
if (plain[i] > 'z')
{
plain[i] = 'a';
}
}
}
if (isupper(plain[i]))
{
for (int q = 0; q < key[i]; q++)
{
plain[i]++;
if (plain[i] > 'Z')
{
plain[i] = 'A';
}
}
}
}
printf("ciphertext: %s\n", plain);
}
}
else
{
printf("Incorrect number of arguments!\n");
return 1;
}
}
Actual results: iekmo, wnslc!
Expected results: iekmo, vprke!
As you can see, my code shifted the "baz", when it shouldn't have in the
space and comma places.
The overriding problem in this program is tying key_length to plain_length. They are discrete and must be treated separately; they "move" at different rates and should use separate and distinct indices.
First I suggest you rewatch the walkthrough. You probably want to write out (yes, pencil and paper) the "baz" example using the same format that Zamyla does with the "panda" example. And then write pseudo-code.
You will probably have to abandon much of the code you have written; generally this pset can be done with one loop that cycles through the plaintext by index, and then manages the keyword index independently within that loop.

Heap-corruption when freeing allocated memory

I am writing small school project, and I got stuck with error that I can't fix. When I try to free allocated memory, I get this error:
Here is the code that involves my char pointer temp:
1. Allocation of memory and setting starting value:
char *temprijec(int rng, RIJEC *B, int *len) {
int i;
char *temp=(char*)calloc(*len + 1, sizeof(char));
*len = strlen((B + rng)->rijec);
for (i = 0; i < *len; i++) {
if (i == 0) {
temp[i] = (B + rng)->rijec[i];
}
else if (i == (*len)) {
temp[i] = '\0';
}
else {
temp[i] = '_';
}
}
return temp;
}
2. Working with char pointer temp:
void tijek_igre(char*temp,RIJEC *B,int rng,int len,int*br2pok,int *pokpogreska,int *pokbr,char*pokch) {
int i;
printf("\nPogodi slovo ili rijec!");
*pokch = _getch();
for (i = 0; (B + rng)->rijec[i] != '\0'; i++) {
if (*pokch == (B + rng)->rijec[i]) {
temp[i] = *pokch;
}
}
for (i = 0; (B + rng)->rijec[i] != '\0'; i++) {
if (*pokch != (B + rng)->rijec[i]) {
(*br2pok)++;
if (*br2pok == len) {
(*pokpogreska)++;
}
}
}
for (i = 0; temp[i] != '\0'; i++) {
if (temp[i] != '_') {
(*pokbr)++;
}
}
}
Everything is fine until I try to free it with free(temp);
I fixed the error by changing the way I am passing variables to function,structure instead of pointers and now it works idk why but it works :).Tnx everyone for help.
Changed code:
VARIJABLE temprijec(VARIJABLE V, RIJEC *B) {
int i;
V.len = strlen((B + V.rng)->rijec);
V.temp = (char*)calloc(V.len + 1, sizeof(char));
for (i = 0; i < V.len + 1; i++) {
if (i == 0) {
V.temp[i] = (B + V.rng)->rijec[i];
}
else if (i == (V.len)) {
V.temp[i] = '\0';
}
else {
V.temp[i] = '_';
}
}
return V;
}
and
VARIJABLE tijek_igre(RIJEC *B, VARIJABLE V) {
int i;
printf("\nPogodi slovo ili rijec!");
V.ch = _getch();
for (i = 0; (B + V.rng)->rijec[i] != '\0'; i++) {
if (V.ch == (B + V.rng)->rijec[i]) {
V.temp[i] = V.ch;
}
}
for (i = 0; (B + V.rng)->rijec[i] != '\0'; i++) {
if (V.ch != (B + V.rng)->rijec[i]) {
(V.pogresno_slovo)++;
if (V.pogresno_slovo == V.len) {
(V.pogreska)++;
}
}
}
for (i = 0; V.temp[i] != '\0'; i++) {
if (V.temp[i] != '_') {
(V.tocno_slovo)++;
}
}
return V;
}

Removing Garbage value in array in C

I have a garbage problem in my array in C, that I can't solve and I have used the memset function for this but this is not useful to me. how can I solve this problem. If I run this code in Code Block or other PC then this is not run completely.
Here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <string.h>
int main() {
clrscr();
int a, b, len = 0, x, i = 0, j, match, misMatch, gapPenalty, sim, m1, m2, m3;
char ch;
char *seq1 = (char *)malloc(100 * sizeof(char));
char *seq2 = (char *)malloc(100 * sizeof(char));
char *s1 = (char *)malloc(100 * sizeof(char));
char *s2 = (char *)malloc(100 * sizeof(char));
/*memset(seq1, 0, strlen(seq1) - 1);
memset(seq2, 0, strlen(seq2) - 1);
memset(s1, 0, strlen(s1) - 1);
memset(s2, 0, strlen(s2) - 1);*/
int **matrix;
int **back;
FILE *inputFile;
inputFile = fopen("in.txt", "r");
printf("Enter Match Point : ");
scanf("%d", &match);
printf("Enter Mismatch Point : ");
scanf("%d", &misMatch);
printf("Enter Gap Point : ");
scanf("%d", &gapPenalty);
while (fscanf(inputFile,"%s\n%s", seq1, seq2) != EOF);
a = strlen(seq1);
b = strlen(seq2);
for (j = 0; j <= strlen(seq2); j++) {
for (i = 0; i <= strlen(seq1); i++) {
if (i == 0 || j == 0) {
if (i == 0) {
matrix[j][i] = j * gapPenalty;
back[j][i] = 0;
}
if (j == 0) {
matrix[j][i] = i * gapPenalty;
back[j][i] = 0;
}
} else {
if (seq1[i - 1] == seq2[j - 1]) {
sim = match;
} else {
sim = misMatch;
}
m1 = matrix[j - 1][i - 1] + sim;
m2 = matrix[j - 1][i] + gapPenalty;
m3 = matrix[j][i - 1] + gapPenalty;
if (m1 > m2) {
if (m1 > m3) {
matrix[j][i] = m1;
back[j][i] = 1;
} else {
matrix[j][i] = m3;
back[j][i] = 3;
}
} else {
if (m2 > m3) {
matrix[j][i] = m2;
back[j][i] = 2;
} else {
matrix[j][i] = m3;
back[j][i] = 3;
}
}
}
}
}
printf("%s", seq1);
printf("\n");
printf("%s", seq2);
printf("\n");
if (a > b) {
len = a;
} else {
len = b;
}
for (x = 0; x < len; x++) {
if (back[b][a] == 1) {
s1[x] = seq1[a - 1];
s2[x] = seq2[b - 1];
a = a - 1;
b = b - 1;
} else if(back[b][a] == 2) {
s1[x] = seq1[a - 1];
s2[x] = '-';
a = a - 1;
} else {
s1[x] = '-';
s2[x] = seq2[b - 1];
b = b - 1;
}
}
for (j = 0; j <= strlen(seq2); j++) {
for (i = 0; i <= strlen(seq1); i++) {
printf("%d ", matrix[j][i]);
}
printf("\n");
}
printf("\n");
for (j = 0; j <= strlen(seq2); j++) {
for (i = 0; i <= strlen(seq1); i++) {
printf("%d ", back[j][i]);
}
printf("\n");
}
printf("\n");
printf("%s", s1);
printf("\n");
printf("%s", s2);
printf("\n");
free(s1);
free(s2);
free(matrix);
free(back);
getch();
return 0;
}
Use calloc(). calloc() initializes all the allocated memory to 0.
// sizeof (char), by definition, is 1
char *seq1 = calloc(100, 1);
char *seq2 = calloc(100, 1);
char *s1 = calloc(100, 1);
char *s2 = calloc(100, 1);
The immediate problem with your commented code is that you cannot apply strlen() to an uninitialized array. You should be using the correct size (which you just used a few statements before) instead
/*memset(seq1, 0, 100);
memset(seq2, 0, 100);
memset(s1, 0, 100);
memset(s2, 0, 100);*/

Resources