ASCII Characters Messed Up in simple C Program [duplicate] - c

This question already has an answer here:
C program printing weird characters
(1 answer)
Closed 8 years ago.
I have written this simple program for an assignment, but when I input my text, the output gives me symbols instead of chars. any help would be appreciated. I do not know why my output appears that way, but the program seems to compile fine. Maybe it is working and I need to just do a base test with the math to see if it is functioning properly. In any event if anyone sees errors in this, feedback is much appreciated.
#include <stdio.h>
#include <cs50.h>
#include <stdlib.h>
#include <ctype.h>
string Crypto(string, int); // rotation
int main(int argc, string argv[])
{
int k = 0;
// error checing
if (argc == 0 || argc == 1 || argc > 2)
{
// get mad
printf("Enter 1 integer as an argument. Stop messing around!\n Try Again: ");
return 1;
}
else
{
//create command line arguments to be stored into k
k = atoi(argv[1]);
k = k * 1;
}
// Get text to be encrypted
printf("Enter the text you want to encrypt: \n");
string a = GetString();
string b = Crypto(a, k);
printf("%s\n", b);
return 0;
}
//Now let's get cryptic
string
Crypto(string a, int k)
{
int c = 0;
for (int i = 0, n = strlen(a); i < n; i++)
{
if(a[i] >= 65 && a[i] <= 90)
{
c = ((26 - (91 - a[i] + k) % 26));
a[i] = c + 'A';
}
else
{
c = ((26 - (123 - a[i] + k % 26)));
a[i] = c + 'a';
}
}
return a;
}

In function Crypto, you need to attach a \0 (null) character to signify the end of the string. Just before return a;, write a a[i+1] = '\0'; statement.

Related

Output in C not as expected on winows in regards to characters [duplicate]

This question already has answers here:
scanf() leaves the newline character in the buffer
(7 answers)
Closed 4 months ago.
I have written a program in C and it is not outputting how I expected. Im used to linux and so I am confused why for this basic program the output is not as I expected. I am using c std 99. I am also relativley new to C so if it is a issue in my code also please let me know
for input: A B C D E F G H I J K L M N O
I get output: -A-- --B-- --C-- --D-- --E-- --F-- --G-- --H-- --I-- --J-- --K-- --L-- --M-- --N-- --O-- -
expected output -A--B--C--D--E--F--G--H--I--J--K--L--M--N--O_
int main() {
char *arr = safeMalloc(sizeof(char) * 32);
int sizeArr = 32;
int cou = 0;
while (scanf("%c", &arr[cou]) != EOF || cou == 10) {
cou++;
if(cou == sizeArr-2) {
arr = realloc(arr, 2*sizeArr);
sizeArr*2;
}
}
for (int i = 0; i < cou; ++i) {
printf("-%c-", arr[i]);
}
printf("\n");
}
The program is considering the spaces as input characters. Changing the for loop to this should fix it:
for (int i = 0; i < cou; ++i) {
if(arr[i] == ' ') continue;
printf("-%c-", arr[i]);
}

Why does my C array remember old data from a previous function call?

When I run the following C code I get the values:
222222222
312222222
102222222
I was expecting the values:
222222222
31
10
Why does the char number[] defined in my intToStr function remember previous values? I thought once the function call ended all local data was more or less destroyed.
#include <stdio.h>
void intToStr(int n);
int main(void)
{
intToStr(222222222);
intToStr(31);
intToStr(10);
return 0;
}
void intToStr(int n)
{
char number[10];
int l = 0;
if (n < 0)
{
l++;
number[0] = '-';
n *= -1;
}
int nCopy = n;
while (nCopy > 9)
{
nCopy /= 10;
l++;
}
int r;
while (n > 9)
{
r = n % 10;
n /= 10;
number[l--] = r + '0';
}
number[l] = n + '0';
printf("%s\n", number);
}
the array should not remember the old data
For each program, the C standard either:
specifies what the program should do
says that it is not specified what the program should do
It hardly ever says that the program should not do something in particular.
In this case, the standard says that it is not specified what characters should be in the array at the start of the function. They can be anything at all. Characters from the previous call is one particular case of "anything at all".
That's undefined behavior. If only the first 3 character are set, it may print 312222222 or it may print 312???????????????????
The last characters in char number[10] are not initialized, that means the compiler may decide to leave it alone and the old values stay, or something else happens.
Otherwise printf doesn't know where the string end, it keeps printing until it randomly hits a zero.
If there is buffer overrun printf finds a different set of characters in memory (which we are not supposed to be accessing) and the program keeps printing those same characters until it randomly hits a zero and finally stops.
To fix it, simply make sure there is '\0' at the end. You can also add additional check to make sure the length does not exceed the buffer size
Working example:
char number[10];
int l = 0;
if (n < 0)
{
l++;
number[0] = '-';
n *= -1;
}
if (n < 0) return;
int nCopy = n;
while (nCopy > 9)
{
nCopy /= 10;
l++;
}
int len = l;
if (len + 1 > sizeof(number))
return;
number[len + 1] = '\0';
int r;
while (n > 9)
{
r = n % 10;
n /= 10;
number[l--] = r + '0';
}
number[l] = n + '0';
printf("%s\n", number);

Taking the crypt of a password is adding some weird foobar thing so that it doesn't equal

#include <stdio.h>
#include <cs50.h>
#include <string.h>
#include <ctype.h>
#include <crypt.h>
int main(int argc, string argv[])
{
if(argc > 2){ printf("too many arguments\n"); return 51; }
if(argc < 2){ printf("too few arguments\n"); return 50; }
//if(strlen(argv[1]) > 4){ printf("Password is greater than 4 characters\n"); return 52; }
if(argc == 2) //make sure there are enough args
{
char hash_guess[] = "rofk";
//long long counter = 0;
//while(guess != argv[1]) //crypt(hash_guess, "50") != argv[1]) //while answer not correct
//{
for(int a = 65; a < 91; a++)
{
for(int b = 65; b < 91; b++)
{
for(int c = 65; c < 91; c++)
{
for(int d = 65; d < 91; d++)
{
for(int A = 0; A < 9; A = A + 5) //control if first is caps or not
{
for(int B = 1 ; B < 9 ; B = B + 5)//control if second is caps or not
{
for(int C = 2; C < 9; C = C + 5) //control if third is caps or not
{
for(int D = 3; D < 9; D = D + 5) //control if fourth is caps or not
{
hash_guess[0] = a;
hash_guess[1] = b;
hash_guess[2] = c;
hash_guess[3] = d;
hash_guess[A] = tolower(hash_guess[A]);
hash_guess[B] = tolower(hash_guess[B]);
hash_guess[C] = tolower(hash_guess[C]);
hash_guess[D] = tolower(hash_guess[D]);
printf("%s\n", hash_guess);
string cryptoguess = (crypt(hash_guess, "50"));
string input = argv[1];
if( cryptoguess == input ) { return 0; }
}
}
}
}
}
}
}
//}
//}
//string guess = crypt(hash_guess, "50");
//printf("%lli", counter);
}
}
}
I'm trying to make a program that goes through every 4 letter word, starting on aaaa and going to ZZZZ. I got that part done.
Part of the assignment is to encrypt that, and if the encryption matches an encrypted password, then you know you "hacked" their password. When I compare the encrypted password that I manually enter and the one that comes up by using the crypt function, they are the same, but in the debugger I see this for when it is encrypted by the computer:
"0x7ffff7dd9200 <_ufc_foobar+131200> "50k72iioeOiJU""
and the normal one that I enter shows
"0x7fffffffe34f "50k72iioeOiJU""
the same thing without the _ufc_foobar. Does anyone know why that is there and how I can get rid of it?
The weird junk you are seeing is visualization of offsets of memory addresses in your code which can be ignored.
In your code you are using string when GNU specifies char * is the result of the crypt function.
Therefore, you cannot compare the pointers to the char array using == but instead need to use strcmp C comparing pointers (with chars)
For crypt see: http://www.gnu.org/software/libc/manual/html_node/crypt.html
<_ufc_foobar+131200> isn't part of the string. It's your debugger attempting to figure out where the string came from, and assign a name to it. In this case, it's come up with a bogus result -- _ufc_foobar is the name of a function or variable somewhere else in the program, and your string happens to be stored 131,200 bytes (about 128 KB) after that in memory.
You can safely ignore this. Your strings are equal. They just happen to be stored in different parts of memory (which is normal).

What's wrong in my code ? (Vigenere cypher cs50, pset2)

My code for CS50 pset2 Vigenere cypher is as follows. I am new to C programming.
[ I edited the code once after I got some suggestions and this code(below) is my new edited code.]
When I run the code it produces infinite loop and also new encrypted text is not produced as it is supposed to be. Can I please get some suggestions and advice regarding the correction of my code ?
Thank you,
#include <stdio.h>
#include <cs50.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
int main(int argc, string argv[])
{
if (argc != 2) //if it is not rqual to 2, it gives an error message.
{
printf("Enter the valid input : \n");
return 1;
}
if (argc == 2) //if two commands are given then it proceeds to other step.
{
string k = argv[1];
string m = GetString();
int l = strlen(k);
int p = strlen(m);
for( int i = 0; i <= p ; i++ ) //it has to keep on rotating from 0 to len of string and back to zero and so on.
{
{
i = i % l;
}
if (isalpha(m[i]) && isalpha(k[i])) // it proceeds ahead only if the input given is an alphabet, if the input is sth other than alphabet it prints exactly as it is.
{
for(int t = 0; t <= p ; t++)
{
if(isupper(m[t])) // when is it capital letter.
{
printf("%c", ( m[t] - 65 + k[i]) % 26 + 65);
}
if(islower(m[t])) // when it is small letter.
{
printf("%c" , ( m[t] - 97 + k[i])% 26 + 97);
}
}
}
else //if it is not an alphabet it returns as it is.
{
printf("%c", m[i]);
}
}
}
printf("\n");
return 0;
}
Let's look at the error. It says that the parameter you gave there is not an array, while you are using it as an array. And that's right : p is an integer, and not an array :
int p = strlen(msg);
Using p[i] means that you want to access the element number i of your p array. But it is impossible to reach this value, because p is simply an integer variable, and not an array.
What you probably wanted to use as an array was one of your string parameters, key or msg. A string variable in CS50 is the equivalent of a char * variable in classic C, and is used as an array of characters.

Vigenere cipher in C wraparound

I'm having trouble writing the last part of my code for an assignment which involves writing a Vigenere cipher. The encryption part is working fine, but I'm having trouble figuring out how to repeat the encryption word/keyword. So it works fine if the message that needs to be encrypted is smaller or equal to the keyword and otherwise it puts out another couple of characters, that seem encrypted, but aren't.
This is the code so far:
#include <stdio.h>
#include <cs50.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
int main(int argc, string argv[])
{
if (argc != 2)
{
printf("YELL!\n");
return 1;
}
//check if the number of command line arguments is correct, if not, YELL!
string keyword = (argv[1]);
//get keyword
for (int j = 0, n = strlen(keyword); j < n; j++)
{
if(!isalpha(keyword[j]))
{
printf("YELL!\n");
return 1;
}
}
//check if the keyword is only alphabetical, if not, YELL!
string message = GetString();
//get plaintext
for (int j = 0, n = strlen(keyword); j < n; j++)
{
if (isupper(keyword[j]))
{
keyword[j] = (keyword[j] - 'A');
}
if (islower(keyword[j]))
{
keyword[j] = (keyword[j] - 'a');
}
}
//this is to get the numerical values from the ascii values of the keyword.
for (int i = 0, j = 0, n = strlen(message); i < n; i++, j++)
//counting through the message & the cypher
{
if (isalpha(message[i]))
{
if (isupper(message[i]))
{
message[i] = (((message[i] - 'A') + keyword[j]) % 26 + 'A');
}
if (islower(message[i]))
{
message[i] = (((message[i] - 'a') + keyword[j]) % 26 + 'a');
}
//adding a keyword value [j] to message [i] and converting back to ascii value,
//individually for upper and lowercase characters.
}
printf("%c", message[i]);
}
}
It's probably an easy solution, but I just can't figure it out. Any help would be vastly appreciated!
It's a miracle encryption is working for you. I think is is not, as your loop is clearly might get j past the keyword length and then keyword[j] will be out of bounds and exhibit undefined behavior. You need only to iterate on i over the message length and index the keyword with keyword[i % strlen(keyword)], such that the index will go cyclically from 0 to the length of the keyword minus one.

Resources