If function and scanf function not working together - c

so I have been trying to write a code that displays different messages if different keys are pressed
It should display "Your hair looks nice" if one of the characters of the string is pressed and display "You look like your mom" if any number of symbol is pessedd (anything other than the array's elements)
what is the issue here?
(Mind the messages in the code I'm trying to stay chill so I picked random messages)
the code:
#include<stdio.h>
int
main ()
{
char i,o;
char a[54] =
{ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'g', 'k', 'l', 'm', 'n',
'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C',
'D',
'E', 'F', 'G', 'H', 'I', 'G', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
'T',
'U', 'V', 'W', 'X', 'Y', 'Z'
};
if (scanf ("%c", &o) == a[i])
printf ("Your hair looks nice");
else
printf ("You look like your mom");
return 0;
}

C have a set of standard character classification functions, like for example isalpha to check if a character is a letter or not.
With this you can make your program much simpler, and don't need the array:
#include <stdio.h>
#include <ctype.h>
int main(void)
{
int ch = getc(); // Read one character
if (isalpha(c))
{
puts("Your hair looks nice.");
}
else
{
puts("You look like your mom!");
}
}
Note that I use the getc function to read a character instead. In most cases scanf shouldn't really be used for input, it's use is unfortunately more non-trivial than the beginners guides and tutorials make it seem.

You need to check all relevant values of i. Currently, you don't even assign a single value to i, but you need to assign 54 different values in turn.
And of course, you need to call scanf only once, not 54 times.

If you want to see whether the inputted character is in the array, then you must compare that character with all 54 characters in the array. However, in your posted code, you are only making one comparison. I suggest that you use a for loop for doing the 54 comparisons. You can do one comparison per loop iteration.
Here is an example:
#include <stdio.h>
#include <stdlib.h>
int main( void )
{
char a[54] = {
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'g', 'k', 'l', 'm',
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'G', 'K', 'L', 'M',
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'
};
char input;
//get input character
if ( scanf( "%c", &input ) != 1 )
{
fprintf( stderr, "Input error!\n" );
exit( EXIT_FAILURE );
}
//determine whether input character is in array
for ( int i = 0; i < 54; i++ )
{
if ( a[i] == input )
{
printf( "Found character in array.\n" );
return 0;
}
}
printf( "Did not find character in array.\n" );
return 0;
}
However, in order to determine whether a character is an alphabetical letter, there is a much simpler solution: You can simply call the function isalpha as demonstrated in one of the other answers.

From scanf's man page:
RETURN VALUE:
On success, these functions return the number of input items successfully matched and assigned; this can be fewer than provided for, or even zero, in the event of an early matching failure.
According to this, the statement
if (scanf ("%c", &o) == a[i])
compares the return value of scanf, which in this case would be one 1(if scanf succeeded) to a[i], where i is uninitialised and leads to undefined behaviour. As I remember #Fe203 once saying:
"Leaving variables uninitialised is asking Demon of Hard-To-Find Bugs to co-author your code."
So you ought to first initialise i, then iterate through the array, comparing o to all the 54 values of i.
Aside:
You shouldn't be using scanf for user-interactive stuff. It is not supposed to be used as such, and it's quite hard to get right. In this case, consider using getc or getchar which reads one character at a time.
Or at least, check the return value of scanf.

Related

Encrypt a string according to the table

I have a problem. For example there is a table like this: table
and want to enter a string for instance like str[] = "şğüö 1234?!" and the program will print the the code like 2422545376354555655666.
It is a encryption question. I created a two dimensional array like this:
char signs[7][6] = {{'A', 'G', 'L', 'S', 'Z', '6'},
{'B', 'Ğ', 'M', 'Ş', '0', '7'},
{'C', 'H', 'N', 'T', '1', '8'},
{'Ç', 'I', 'O', 'U', '2', '9'},
{'D', 'İ', 'Ö', 'Ü', '3', '?'},
{'E', 'J', 'P', 'V', '4', '!'},
{'F', 'K', 'R', 'Y', '5', ' '}};
And I thought that I could search the string's letters in this two-dimensional array. When the program find the letter, it can print the values of i and j. (Nested loops' elements)
Do you have another solution for that question? I really need your help. Because I cannot do that.
It appears you are using an 8bit "character code" table.
Rather than doing a "look-up" search through this table of yours, you could simply print the character translated to 2 hexadecimal values:
for( int i = 0; str[i]; i++ )
printf( "%02X", (unsigned char)str[i] );
If you think that 'hex' would be too obvious, you could go for 3 digit octal instead:
printf( "%03o", (unsigned char)str[i] );
There are myriad 'simple' encryption schemes that would defeat most casual observers.
Then, you must consider the 'decryption' complement to whatever scheme you choose.

Program to bubble sort a txt file in C

I'm writing a C program to be given a txt file containing names of player and how many wins they have (its for a bigger game project), and sort them from highest to lowest amount of wins. While the code compiles and successfully orders the wins im experiencing a problem with the names where they seem to be stacking on top each other.
#include<stdio.h>
#include<stdlib.h>
char name[20];
int wins[20];
void main()
{
FILE *fp;
int i=0,size,j,swap;
char ch;
fp=fopen("record.txt","r");
if(fp==NULL)
{
printf("\n Cannot open the file \n");
exit(0);
}
while(ch!=EOF)
{
fscanf(fp,"%s %d",&name[i],&wins[i]);
ch=fgetc(fp);
i++;
}
size=i-1;
for(i=1;i<size;++i)
for(j=0;j<size-i;j++)
if(wins[j+1]>wins[j])
{
swap = wins[j];
wins[j] = wins[j+1];
wins[j+1] = swap;
swap = name[j];
name[j] = name[j+1];
name[j+1] = swap;
}
fp=fopen("sortedRecord.txt","w");
for(i=0;i<size;i++){
fprintf(fp,"%s %d \n",&name[i],wins[i]);
printf ("%s %d \n", &name[i],wins[i]);
}
fclose(fp);
}
Here is the input file "record.txt"
Andrew 5
Billboy 10
Hill 7
Mill 1
And here is what i get when i run it.
BHAMill 10
HAMill 7
AMill 5
Mill 1
I'm new to code so i know mine sucks but for the life of me i cant see exactly where its going wrong. Any help or advice is appreciated.
As jwdonahue said the issue is with your definition of name. char name[20] creates an array of 20 chars, not 20 strings.
When you run the while(ch!=EOF) loop what's happening? First time through you find the address of the 0th element in name and write Andrew there so name has ['A', 'n', 'd', 'r', 'e', 'w', '\0', '\0', '\0', '\0'] (the \0 is the end of string character). Second time through you find the address of the 1st element in name and write Billboy, but the 0th element is still there and hasn't changed so you end up with the contents being ['A', 'B', 'i', 'l', 'l', 'b', 'o', 'y', '\0', '\0']. Adding Hill to the 2nd position results in ['A', 'B', 'H', 'i', 'l', 'l', '\0', 'y', '\0', '\0']. Then finally adding Mill gives the array ['A', 'B', 'H', 'M', 'i', 'l', 'l', '\0', '\0', '\0'].
When you then go to sort scores you are sorting the characters in this array which end up as ['B', 'H', 'A', 'M', 'i', 'l', 'l', '\0', '\0', '\0'] (only the first four characters will be affected by your sort). In your print statement you then print the character array starting at the 0th, 1st, 2nd and 3rd positions respectively so you get BHAMill, HAMill, AMill, and Mill.
Hopefully that should help you enough to get you unstuck. :)

Why is the printf specifiers, "%s", printing multiple variables at once?

I declared four string variables and initialized in four different ways. I then used the printf function four times, as the name implies, to print to the console the four string variables.
I already tried printing one at a time, but that didn't worked out. After the first attempt, I tried using the escape sequence but that didn't work. I then tried searching online of finding the proper ways to print out string, but all I've found came back to same using the printf function.
#include <stdio.h>
int main() {
char name1[] = "Ignacio";
char name2[8] = "Ignacio";
char name3[] = {'D', 'i', 'e', 'g', 'o'};
char name4[5] = {'D', 'i', 'e', 'g', 'o'};
printf("Name: %s\n", name1);
printf("Name: %s\n", name2);
printf("Name: %s\n", name3);
printf("Name: %s\n", name4);
return 0;
}
EXPECTED OUTPUT:
Name: Ignacio
Name: Ignacio
Name: Diego
Name: Diego
ACTUAL OUTPUT:
Name: Ignacio
Name: Ignacio
Name: DiegoIgnacio
Name: DiegoDiegoIgnacio
char name3[] = {'D', 'i', 'e', 'g', 'o'};
char name4[5] = {'D', 'i', 'e', 'g', 'o'};
These two are not strings, because they are not null-terminated.
Try:
char name3[] = {'D', 'i', 'e', 'g', 'o', '\0'};
char name4[6] = {'D', 'i', 'e', 'g', 'o', '\0'};
Whats happening is the a null terminating character is implicitly being added when you initialize a char[] like below:
char myStr[] ="Ignacio";
If you want to initialize a char[] with individual characters you must initialize it like the following because the null terminating character must be explicitly added:
char myStr[] ={'I', 'g', 'n', 'c', 'i','0','\0'}).
Explanation for the Behaviour in Your Case:
Memory Layout:
[0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [A] [B] [C] [D] [E] [F] [10] [11]
'D' 'i' 'e' 'g' 'o' 'D' 'i' 'e' 'g' 'o' 'I' 'g' 'n' 'a' 'c' 'i' 'o' '\0'
After you initialize your strings, the characters are arranged in memory like above. In the C language, all valid strings must have a null terminating character at there end to specificity the end of the string. The reason why is printf will just start at the address of the char* passed to it and will keep reading characters until a '\0' character is encountered. Because of this, if you pass printf an address to an array of characters that does not contain a '\0', then printf will keep marching past those characters into memory until a null terminating character is encountered. (This could result in a segmentation fault)
Explanation for Your Output: (Reference the memory layout above)
Name: DiegoIgnacio
printf will start at index [5] and will print all characters until the '\0' character, thus "DiegoIgnacio" ([5] - [11]) is the output.
Name: DiegoDiegoIgnacio
printf will start at index [0] and will print all characters until the '\0' character, thus "DiegoDiegoIgnacio" ([0] - [11]) is the output.

C: Base 64 to binary conversion

I've been working to implement a base64 decoder in C. I have been reading up on base64 conversion in places such as the Wikipedia page and also using online converters to check my work. It seems straight forward: just replace every base64 character with the corresponding 6-bit binary string!
My Base64-to-binary decoding is correct as long as the base64 string to decode is a multiple of 4. If the string length is not a multiple of 4, or there are equal signs present for padding, my code does not match the results from online converters.
I thought I understood the padding -- just replace the '=' character with zeros (6, for 6 bits). However, I still don't match the converter's result when this is employed.
Here is the code I've written:
int main(void){
printf("Testing b642bin ...\n\n");
printf("Case 1: Converting 'AA==' to bin:\n");
printf("Expected Result: 000000000000000000000000\n");
printf("Actual Result: %s\n\n", b642bin("AA=="));
printf("Case 2: Converting '+aHg' to bin:\n");
printf("Expected Result: 111110011010000111100000\n");
printf("Actual Result: %s\n\n", b642bin("+aHg"));
printf("Case 3: Converting 'kNSHd94m7d+=' to bin:\n");
printf("Expected Result: 1001000011010100100001110111011111011110001001101110110111011111\n");
printf("Actual Result: %s\n\n", b642bin("kNSHd94m7d+="));
return 0;
}
char bin6_table[65][7] = {"000000", "000001", "000010", "000011", "000100",
"000101","000110", "000111", "001000", "001001",
"001010", "001011", "001100", "001101", "001110",
"001111", "010000", "010001", "010010", "010011",
"010100", "010101", "010110", "010111", "011000",
"011001", "011010", "011011", "011100", "011101",
"011110", "011111", "100000", "100001", "100010",
"100011", "100100", "100101", "100110", "100111",
"101000", "101001", "101010", "101011", "101100",
"101101", "101110", "101111", "110000", "110001",
"110010", "110011", "110100", "110101", "110110",
"110111", "111000", "111001", "111010", "111011",
"111100", "111101", "111110", "111111", "000000"};
char base64_table[65] = {'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', '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', '0', '1', '2', '3',
'4', '5', '6', '7', '8', '9', '+', '/','='};
char* b64Char2bin(char b64){
int n = 64;
int k;
char *bin;
for(k=0;k<n;k++){
if (b64 == base64_table[k]) {
bin = bin6_table[k];
break;
}
}
return bin;
}
char* b642bin(char *b64_str) {
int i;
size_t len = strlen(b64_str);
char* bin_str = (char*)malloc(((len * 6) + 1) * sizeof(char));
for (i = 0; i < (int)len; i++) {
const char* binSextet = b64Char2bin(b64_str[i]);
memcpy(&bin_str[6*i], binSextet,7);
}
return bin_str;
}
The output looks like this:
Testing b642bin ...
Case 1: Converting 'AA==' to bin:
Expected Result: 000000000000000000000000
Actual Result: 000000000000000000000000
Case 2: Converting '+aHg' to bin:
Expected Result: 111110011010000111100000
Actual Result: 111110011010000111100000
Case 3: Converting 'kNSHd94m7d+=' to bin:
Expected Result: 1001000011010100100001110111011111011110001001101110110111011111
Actual Result: 100100001101010010000111011101111101111000100110111011011101111110000000
If the converter I provided is correct, I don't understand Base64. Clearly you do not simply replace each character with the corresponding 6 bits of binary. Why is Case 1 and 2 correct, but Case 3 is not?
Bytes (well, octets if you want to get all technical) are 8 bits long. Base64 encodes 6 bits at a time. Padding is used when the number of bytes that were encoded isn't a multiple of three, therefore the number of bits isn't a multiple of six. When decoding base64 with padding, you don't output more zero bits, you output less bits to produce the correct number of bytes.
As a concrete example:
Base64: ////
Binary: 11111111 11111111 11111111
Base64: //8=
Binary: 11111111 11111111
Base64: /w==
Binary: 11111111

A poker card game in C. Please explain suits[4][9], and faces[13][6]?

So I have a sample code to create a deck of card for a mini poker game in c. But I do not understand how the suits and faces are determined. Why do these arrays have 2 dimensions? I know that [9] and [6] are the columns of the array, but I do not understand the purpose of them.
char suits[4][9]= {"Hearts","Diamonds","Clubs","Spades"};
char faces[13][6]= {"Ace","2","3","4","5","6","7","8","9", "10","Jack",
"Queen","King"};
The first set of square brackets is the number of elements in the first array, the second square bracket is the maximum length of the char array (string).
The second bracket in char suits[4][9] has nine spaces to allow space for the null character \0 which is used to terminate the string.
So the array actually looks like this:
char suits[4][9] = {
{'H', 'e', 'a', 'r', 't', 's', '\0'},
{'D', 'i', 'a', 'm', 'o', 'n', 'd', 's', '\0'},
{'C', 'l', 'u', 'b', 's', '\0'},
{'S', 'p', 'a', 'd', 'e', 's', '\0'}
};
When you have :
char suits[4][9]
it means that your array has 4 rows and the string that will be placed in each row can have a maximum length 9 and subtracting the ending '\0' character, maximum length 8.
Similarly,
char faces[13][6]
means that your array has 13 rows and the string that will be placed in each row can have a maximum length 6 and subtracting the ending '\0' character, maximum length 5.

Resources