Why do "f" and "g" ASCII characters turn negative in this code? - c

#include <stdio.h>
/*************** CAESAR CYPHER *****************
-Take a charater array input
-Loop through 26 character shifts
-Print all possibilities
************************************************/
void Brute_Force(char *message)// Character array pointer
{
char *i;// Copy message for iteration: Stop at '/0'
int j;// Iterate through the alphabet
char t;//Temp variable for current letter
for(j = 0; j < 26; j++)
{
printf("\n----------Shift %i----------\n", j);//Aesthetics
for(i = message; *i != '\0'; i++)
{
//Multiple of 26 to start at original message
unsigned char t = ((*i + j)%26) + 104;
// Only loop 97 to 122. ASCII 'a'-'z'
if(t > 122){t = t - 26;}
printf("%c", t);
}
}
}
int main()
{
char mess[26] = "ynkooejcpdanqxeykjrbdofgkq";
Brute_Force(mess);
return 0;
}
Before changing t to an unsigned char instead of a regular char, every time 'f'(102) or 'g'(103) would come up, it would output t = -127/-128 instead of 127/128. I'm just wondering what would have caused it to change to negative. It was only for 'f' and 'g', every other letter was correct.
a sample output would be:
ynkooejcpdanqxeykjrbdo��kq

Related

Why I am getting a space character in my program in the place of third last character?

Why I am getting a space character in my program in the place of third last character?
Even if I change the string str variable I get the same result.
#include <stdio.h>
#include <string.h>
void parser(char array[])
{
int a, b;
for (int i = 0; i < strlen(array); i++) {
if (array[i] == '>') {
a = i;
break;
}
}
for (int j = a; j < strlen(array); j++) {
if (array[j] == '<') {
b = j;
}
}
for (int p = 0, q = a + 1; p < b - a - 1, q < b; p++, q++) {
array[p] = array[q];
array[b - a] = '\0';
printf("%c", array[p]);
}
}
int main()
{
char str[] = "<h1>hello there i am programmer.</h1>";
parser(str);
return 0;
}
There are many things that could be written better in the code but they do not affect the result.
The line that produces the unexpected outcome is:
array[b-a]='\0';
When this for loop starts...
for(int p=0,q=a+1;p<b-a-1,q<b;p++,q++){
array[p]=array[q];
array[b-a]='\0';
printf("%c",array[p]);
}
... the values of a and b are 3 and 32.
The statement array[b-a]='\0'; puts the NUL terminator character at position 29 in array.
The loop starts with p=0, q=4 (a+1) and repeats until p reaches 28 and q reaches 31 (q<b)*.
When p is 25, q is 29 and array[29] has been repeatedly set to '\0' on the previous iterations, therefore '\0' is copied at position 25 and printed on screen.
You should set the NUL terminator only once, after the loop. And the right position for it is b-a-1, not b-a; you expressed this correctly in the for initialization (p=0) and exit condition (p<b-a-1).
All in all, the code around the last for loop should be like this:
for(int p=0, q=a+1;q<b;p++,q++){
array[p]=array[q];
printf("%c",array[p]);
}
array[b-a-1]='\0';
*The condition p<b-a-1 is ignore because of the comma character. You probably want & between the conditions but they are equivalent, one of them is enough.

How to check first letter of one string with last letter of another string inside of same char array

How can I complete the function canArrangeWords() ?
Question : Given a set of words check if we can arrange them in a list such that the last letter of any word and first letter of another word are same. The input function canArrangeWords shall contain an integer num and array of words arr. num denotes the number of word in the list (1<=num<=100). arr shall contain words consisting of lower case letters between 'a' - 'z' only . return 1 if words can be arranged in that fashion and -1 if cannot.
Input : 4 pot ten nice eye
output : 1
input : 3 fox owl pond
output: -1
Please help me complete this program .
**
#include<stdio.h>
#include<string.h>
int canArrangewords(int,char [100][100]);
void main(){
int n ,count=0 , i ;
char arrayS[100][100];
scanf("%d",&n);
for (i = 0; i < n; ++i)
{
scanf("%s",arrayS[i]);
}
for(i=0;i<n;i++)
{
printf("%s",arrayS[i]);
printf("\n");
}
printf("%c\n",arrayS[2][4]);
canArrangewords(n , arrayS);
}
int canArrangewords(int n,char arrayS[100][100]){
int i , j ;
for ( i = 0; i < n; i++)
{
for ( j = i+1 ; j < strlen(arrayS[j+1]); i++)
{
int flag = strlen(arrayS[j+1]) - 1;
int temp = strcmp(arrayS[i][0],arrayS[j][flag]);
}
}
}
}
Well, first of all think of the way you can reach that answer.
If you only need to know if they can or can not be arranged and you do not have to do so your self you can use an empty array of int array[26] for each letter a-z.
The rule is that from all the first and last letters for all the words only two MAY appear an odd amount of times - the first letter of first word in list and the last letter in the last word in the list, the rest MUST appear an even amount of times. I would add a check to make sure the letters are lowercase as well. good luck!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MINASCII 97
#define LETTERS 26
void UpdateArray(char letter, int* arr)
{
if(arr[letter - MINASCII] == 0)
{
++arr[letter - MINASCII];
}
else
{
--arr[letter - MINASCII];/*for each second time same letter is seen reduce back to zero */
}
}
int canArrangewords(int wordNum, char* wordArr[])
{
int arr[LETTERS] = {0};
int i = 0;
int count = 0 ;
char first;
char last;
char* string;
for (i= 0; i< wordNum; ++i)
{
string = wordArr[i];
first = string[0];
last = string[strlen(string)-1];
UpdateArray(first, &arr[0]);
UpdateArray(last, &arr[0]);
}
for(i = 0; i< LETTERS; ++i)
{
count+=arr[i];
}
if(count == 2 || count == 0)/*either once each or twice -see word1 example in main*/
{
return 1;
}
return -1;
}
int main()
{
int i = 0;
char* words[] = {"pot", "ten", "nice", "eye"};
char* words1[] = {"pot", "ten", "nip"};
char* words2[] = {"fox", "owl", "pond"};
i = canArrangewords(4,words);
printf("%d\n", i);
i = canArrangewords(3,words1);
printf("%d\n", i);
i = canArrangewords(3,words2);
printf("%d\n", i);
return 0;
}
Change your array of words into an array of pointers to words. Then you can simply exchange the pointers.
To speed things up, instead of a pointer to a word, have it point to a structure:
struct WORD {
char *firstchar; // begin of word
char *lastchar; // last char of word
} *words[100]; // array of 100 pointers to words
To read the words:
char buf[100];
for (i = 0; i < n; ++i)
{
scanf("%s",buf);
int len= strlen(buf);
words[i]= malloc(sizeof(struct WORDS));
words[i]->firstchar= malloc(len+1);
strcpy(words[i]->firstchar, buf);
words[i]->lastchar= words[i]->firstchar + len-1;
}
Now compare and sort:
if (*words[i]->lastchar == *words[j]->firstchar) {
struct WORDS *tmp= words[i+1];
words[i+1]= words[j];
words[j]= tmp;
}
Do this in a loop, a kind of bubble sort. I leave that to you.

How to save a char to an array in the position of its ascii num In c

I am working on a Caesar cipher and I am trying to save the characters of my cipher key in an array based on the ascii of the letter is supposed to represent. So if my cipher char key[] = "codezyxwvutsrqpnmlkjihgfba"
The first char in the array (c) is supposed to represent the letter a, whose ascii num is 97. So I want to store c in the array in the 97th spot. Everytime I try to this the array turns out empty.
char key[] = {"codezyxwvutsrqpnmlkjihgfba"};
char alphabet[] = {"abcdefghijklmnopqrstuvwxyz"};
char answerKey[200] = "";
for (int i = 0; key[i] != '\0'; i++) {
answerKey[(int) alphabet[i]] = key[i];
}
for (int i = 0; answerKey[i] != '\0'; i++) {
printf("%c", answerKey[i]);
}
Since the answerkey array has values only in the range of 97 - 122 assuming you are only using lower alphabet the other elements of the arrays are garbage.
Just change the print for loop to iterate from 97 to 122 and you get what you want.
char key[] = {"codezyxwvutsrqpnmlkjihgfba"};
char alphabet[] = {"abcdefghijklmnopqrstuvwxyz"};
char answerKey[200]="";
for (int i = 0; key[i] != '\0'; i++) {
printf("%c",alphabet[i]);
answerKey[(int) alphabet[i]] = key[i];
printf("%c",answerKey[(int)alphabet[i]]);
}
printf("\n");
int i=0;
for (i = 97;i<=122; i++)
{
printf("%c", answerKey[i]);
}
You are starting your printing of the answerKey[] array at the first element and telling it to stop as soon as it hits '\0'. I don't believe answerKey[0] should ever not be '\0' since none of the printable ascii characters are 0. I would expect your answerKey[] array to be empty except between elements 97-122, so if your cipher will be used only for lowercase alphabetical characters, perhaps only look in that part of the array.
Alternatively, you could make your answerKey[] array only hold enough space to fit your cipher by subtracting 'a' from the element address as you're placing it. Something like this might do the trick:
char answerKey[27] = "";
for (int i = 0; key[i] !='\0'; i++) {
answerKey[(int) alphabet[i] - 'a'] = key[i];
}
In C, you can convert a char to an int by simply preforming a cast.
In the memory, when you have a char 'a', the value 97 is saved. When you use a char, it is just the way you understand what is written in the memory. you can just treat this memory as an int, and get the value which is stored over there.
For example:
char c = 'a';
printf("char is %c, int is %d", c, (int)(c));
// Output would be:
// char is a, int is 97
For further information, read: How are different types stored in memory

Remove vowels from a character string, Stack smashing error

#include <stdio.h>
#include <stdlib.h>
int main() {
char str[] = "my name is khan. and i am not a terrorist\n";
char arr[80];
char wolf[] = { 'a', 'e', 'i', 'o', 'u', '\0' };
int i, j, k, len;
len = strlen(str);
for (i = 0, j = 0; i < len; i++) {
for (k = 0; k <= 4; k++) {
if (wolf[k] != str[i]) {
arr[j] = str[i];
j++;
}
}
}
return 0;
}
Here, I have to remove vowels from string str. I am storing the resulting string in arr. But stack smashing error comes whenever I execute it. why?
What will happen when the char m is processed?
you will write it 5 times to arr. In general all chars will be written 4 or 5 times.
Don't write to arr in the inner-loop. Instead use a flag to remember whether you had a match. Test the flag after the loop to see if the char is to be written or not.
You have error in the check, you are copying the same characheter 5 times if the characheters is not vowel. you should make your check in this way
for(i=0,j=0;i<len;i++)
{
unsigned char isvowel = 0;
for(k=0;k<=4;k++)
{
if(wolf[k]==str[i])
{
isvowel = 1;
break;
}
}
if (!isvowel) {
arr[j]=str[i];
j++;
}
}
or you can develop a separate function to check if charachter is vowel:
unsigned char isvowel(char c)
{
char wolf[]={'a','e','i','o','u','\0'};
int k;
for(k=0;k<=4;k++)
{
if(wolf[k]==c)
{
return 1;
}
}
return 0;
}
And you can use it in your for loop in this way:
for(i=0,j=0;i<len;i++)
{
if (!isvowel(str[i]) {
arr[j]=str[i];
j++;
}
}
By the way, you have to add null charachter at the end of your arr string. After the for loop add the follwing line:
arr[j] = '\0';
You are getting a buffer overflow(probably) due to large number of comparisons being done. This part of your code:
if(wolf[k]!=str[i]){
arr[j]=str[i];
j++;
}
seems to change the value of j, every time there is a mismatch. For example lets say the first character 'm', will end up being copied more than once in your 'arr' array.
I modified your code a little change with a flag and at the end you missed arr[j]='\0';
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char str[]="my name is khan. and i am not a terrorist";
char arr[80]={0};
char wolf[]={'a','e','i','o','u','\0'};
int i,j,k,len,flag=0;
len=strlen(str);
for(i=0,j=0;i<len;i++)
{
for(k=0;k<=4;k++)
{
if(wolf[k]==str[i])
{
flag = 1;
break;
}
}
if(0==flag)
{
arr[j]=str[i];
j++;
}
flag=0;
}
arr[j]='\0';
printf("str:%s\n",str);
printf("arr:%s\n",arr);
return 0;
}
This may be the same idea of previous answers.
Stack smashing means you are using stack (a part of computer memory) illegally. This illegal use of stack memory can be done in many ways. One way do this is to add more elements to an array than its capacity. For example if you try to add 15 elements to an array with capacity of 10 elements then you will have stack smashing.
Here in your case, the array char arr[80]; has the capacity for 80 chars, but you are adding more than 80 chars in this array. This is why you are getting stack smashing error.
There are two issues in your code. First, you are adding elements from str[] more than one times to arr[].
/* Issue 1 */
for(k=0;k<=4;k++)
{
if(wolf[k]!=str[i])
{
/* You are adding str[i] to
arr[] multiple times
*/
arr[j]=str[i];
j++;
}
}
Here you are comparing str[i] with each vowel character and adding that character to arr[] everytime. This way each character is added 5 times (non-vowel characer), or 4 times (a vowel character).
To solve this issue, you need to compare str[i] with all vowels, and add it to arr[] only if it does NOT match to any vowel. There are many ways to do it. For example you can use an additional variable as a flag.
Second, you are not checking if there is any space left in arr[] to add any new character. In this part of your code:
/* Issue 2: You are not checking if space left in arr[] */
for(i=0,j=0;i<len;i++)
{
Here in your for loop condition you need to make sure that there is space left in arr[]. So, you need to add one more condition in your for loop.
This is one (among many) solutions:
/* Check if space left in arr, i.e. j < 80 */
for(i=0,j=0;i<len && j < 80;i++)
{
/* Add a flag:
1 means vowel
0 means not a vowel
*/
int v_flag = 0;
for(k=0;k<=4;k++)
{
if(wolf[k] == str[i])
{
v_flag = 1; /* Indicate that this is vowel */
break;
}
}
/* Add to arr[] only if not a vowel */
if (v_flag == 0)
{
arr[j] = str[i];
j++;
}
}
/* Null terminate the string */
arr[j] = '\0';
There are some string functions in the standard library that may help you, strchr() is one of them (you can get rid of the inner loop!) :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char str[] = "my name is khan. and i am not a terrorist\n";
char arr[80];
char *wolf = "aeiouy";
int i,j;
for(i=j=0; arr[j] = str[i]; i++)
{
if ( !strchr (wolf, str[i]) ) j++;
}
printf("%s\n", arr);
return 0;
}
You are actually duplicating the characters from str for each failed comparison to a vowel. The resulting string is between 4 and 5 times longer than the original, much longer than the destination array arr. Writing beyond the end of the array invokes undefined behavior: an early program termination in your case.
Here is how to fix your problem:
#include <stdio.h>
#include <stdlib.h>
int main() {
char str[] = "my name is khan. and i am not a terrorist\n";
char arr[80];
char wolf[] = { 'a', 'e', 'i', 'o', 'u', '\0' };
int i, j, k, len;
len = strlen(str);
for (i = 0, j = 0; i < len; i++) {
for (k = 0; k < 5; k++) {
if (str[i] == wolf[k])
break;
}
if (k == 5) { // not a vowel
arr[j] = str[i];
j++;
}
}
arr[j] = '\0'; // remember to put the final null byte to close the C string
printf("result: %s\n", arr);
return 0;
}

Getting a value from a char array

I have written a function below to take a char array and manipulate its values (namely, convert the char to an int if it is a number). However, I have a question with how the char array is managed. When I look at input[i], it is the correct value (the value that was placed in the array. However, &input[i] gives a capital letter, and I don't know why it does that. For example, if I enter "11" and trace the variables, I might get the following result:
input[0] is 1
&input[0] is D
input[1] is 1
&input[1] is E
On to my code, if I try to use input[i], I get the error of "passing argument makes pointer from integer without cast". If I use &input[i], the code compiles but I get the wrong result. What's going on with this, and how do I access the value I'm trying to get?
Below is my code:
void myFunction(char *input) {
Queue* numberQueue = queue_new();
Queue* opQueue = queue_new();
int i = 0;
int j;
for (j = 0; j < strlen(input); j++) {
printf("input[%d] is %c\n", i, input[i]);
printf("&input[%d] is %c\n", i, &input[i]);
int number = (int)input[i];
/* queue_push_tail(queue, data) */
queue_push_tail(numQueue, number); /* ERROR */
/* rest of code omitted */
i++;
}
}
If I understand that you want to push each digit in the input character string into queue_push_tail, as an integer value then you want your loop to do something like this:
for (j = 0; j < strlen(input); j++) {
if ( input[j] >= '0' && input[j] <= '9')
{
number = input[j] - '0';
/* queue_push_tail(queue, data) */
queue_push_tail(numQueue, number); /* ERROR - FIXED*/
/* rest of code omitted */
}
}
Recall, ASCII characters are themselves unsigned integers. You simply need to adjust the value for each character by subtracting the value of ASCII '0'. If you need to collect all numbers from the string into a single number (e.g. ac7f9gh3 => 793) then simply store the values unadjusted in a temp string, and then call atoi (temp).

Resources