Write a function escape(s,t) that converts characters like newline and
tab into visible escape sequences like \n and \t as it copies the
string t to s. Use a switch. Write a function for the other direction
as well, converting escape sequences into the real characters.
This is the Exercise 3-2 from K&R book. So I tried to do it. My escape function works properly. But my inverseescape is giving me the same answer as the escape function is giving. Here is the code:
#include <stdio.h>
#define MCC 100
void espace(int* str,int* t);
void inverseescape(int * str,int *t);
void getline(int*);
int main(void){
int firstarr[MCC];
int secondarr[MCC];
int thirdarr[MCC];
getline(firstarr);
espace(firstarr,secondarr);
printf("-----------AFTER ESCAPE------------\n");
for(int g=0;secondarr[g];g++){
printf("%c",secondarr[g]);
}
inverseescape(secondarr,thirdarr);
printf("\n-----------AFTER INVERSEESCAPE------------\n");
for(int g=0;thirdarr[g];g++){
printf("%c",thirdarr[g]);
}
return 0;
}
void getline(int* arr){
int i=0;
int c=0;
while((c=getchar())!=EOF){
arr[i]=c;
arr[i+1]=0;
i++;
}
}
void espace(int* string,int* target){
int i = 0;
int j = 0;
while(string[i]){
switch(string[i]){
case '\a':
target[j]='\\';
target[++j]='a';
target[++j]=0;
break;
case '\b':
target[j]='\\';
target[++j]='b';
target[++j]=0;
break;
case '\t':
target[j]='\\';
target[++j]='t';
target[++j]=0;
break;
case '\n':
target[j]='\\';
target[++j]='n';
target[++j]=0;
break;
case '\v':
target[j]='\\';
target[++j]='v';
target[++j]=0;
break;
case '\f':
target[j]='\\';
target[++j]='f';
target[++j]=0;
break;
case '\r':
target[j]='\\';
target[++j]='r';
target[++j]=0;
break;
case '\"':
target[j]='\\';
target[++j]='\"';
target[++j]=0;
break;
case '\'':
target[j]='\\';
target[++j]='\'';
target[++j]=0;
break;
case '\?':
target[j]='\\';
target[++j]='\?';
target[++j]=0;
break;
case '\\':
target[j]='\\';
target[++j]='\\';
target[++j]=0;
break;
default:
target[j]=string[i];
target[++j]=0;
break;
}
i++;
}
}
void inverseescape(int* string,int* target){
int i = 0;
while(string[i]){
switch(string[i]){
case '\\':
switch(string[i+1]){
case 'a':
target[i]='\a';
case 'b':
target[i]='\b';
case 't':
target[i]='\t';
case 'n':
target[i]='\n';
case 'v':
target[i]='\v';
case 'f':
target[i]='\f';
case 'r':
target[i]='\r';
case '\"':
target[i]='\"';
case '\'':
target[i]='\'';
case '\?':
target[i]='\?';
case '\\':
target[i]='\\';
}
default:
target[i]=string[i];
}
target[++i]=0;
}
}
I am using switch statement first time (and probably last) so the code is not well-written (i guess).
Input:
shadow
of
the
beast
Output:
-----------AFTER ESCAPE------------
shadow\nof\nthe\nbeast
-----------AFTER INVERSEESCAPE------------
shadow\nof\nthe\nbeast
You're missing the break in the inverseescape case statement. case's behaviour has the curious property of falling through to the statement below unless you explicitly break out of the case. In this case it's falling through to your default case and setting the output to the input.
Related
I'm writing a program to 'encrypt' an inputted string of text by using a switch statement to correlate the given character with a symbol, and output that symbol in the place of the character. I put it in a while loop, the idea being that it would loop the full switch function each time until the received character is EOF. On a guess, I believe it is looping through just the first character, because I don't advance the getchar() statement, but I'm not sure how to do that so any help would be greatly appreciated. I say this because if I use return instead of break, it closes the while loop and only takes that first letter, if I use a break then it spams the first 'encrypted' char.
#include <stdlib.h>
#include <stdio.h>
/* C program to encrypt a given text message, assuming all lowercase */
int main() {
int Input, Encrypted;
printf("Please type your message\n");
Input = getchar();
while (Input != EOF) {
switch (Input) {
case 'a':printf("!"); break;
case 'b':printf("#"); break;
case 'c':printf("#"); break;
case 'd':printf("$"); break;
case 'e':printf("%"); break;
case 'f':printf("^"); break;
case 'g':printf("&"); break;
case 'h':printf("*"); break;
case 'i':printf("`"); break;
case 'j':printf("~"); break;
case 'k':printf("-"); break;
case 'l':printf("_"); break;
case 'm':printf("="); break;
case 'n':printf("+"); break;
case 'o':printf("["); break;
case 'p':printf("{"); break;
case 'q':printf("]"); break;
case 'r':printf("}"); break;
case 's':printf(";"); break;
case 't':printf(":"); break;
case 'u':printf("|"); break;
case 'v':printf(","); break;
case 'w':printf("<"); break;
case 'x':printf("."); break;
case 'y':printf(">"); break;
case 'z':printf("'");break;
return 0;
}
}
return 0;
}
The simplest solution would be to remove the line
Input = getchar();
and to replace the line
while (Input != EOF) {
with:
while ( (Input=getchar()) != EOF && Input != '\n' ) {
Alternatively, if you find this while condition too confusing, you could also use an infinite loop, instead, like this:
#include <stdlib.h>
#include <stdio.h>
int main( void )
{
printf("Please type your message\n");
for (;;) //infinite loop, equivalent to while(true)
{
int c;
c = getchar();
if ( c == EOF || c == '\n' )
break;
switch ( c )
{
case 'a':printf("!"); break;
case 'b':printf("#"); break;
case 'c':printf("#"); break;
case 'd':printf("$"); break;
case 'e':printf("%%"); break;
case 'f':printf("^"); break;
case 'g':printf("&"); break;
case 'h':printf("*"); break;
case 'i':printf("`"); break;
case 'j':printf("~"); break;
case 'k':printf("-"); break;
case 'l':printf("_"); break;
case 'm':printf("="); break;
case 'n':printf("+"); break;
case 'o':printf("["); break;
case 'p':printf("{"); break;
case 'q':printf("]"); break;
case 'r':printf("}"); break;
case 's':printf(";"); break;
case 't':printf(":"); break;
case 'u':printf("|"); break;
case 'v':printf(","); break;
case 'w':printf("<"); break;
case 'x':printf("."); break;
case 'y':printf(">"); break;
case 'z':printf("'"); break;
}
}
return 0;
}
Note that most character sets (such as ASCII) store the characters a to z consecutively. With these character sets, you don't need the long switch statement. Instead, you can simplify it to the following:
#include <stdlib.h>
#include <stdio.h>
int main( void )
{
printf("Please type your message\n");
for (;;) //infinite loop, equivalent to while(true)
{
const char map[] = "!##$%^&*`~-_=+[{]};:|,<.>'";
int c;
c = getchar();
if ( c == EOF || c == '\n' )
break;
if ( 'a' <= c && c <= 'z' )
putchar( map[c-'a'] );
}
return 0;
}
I have written a "Morse Encoder" program in C. I can execute the code, there are no errors but a logic error. It does not give what I want. User types something as a string then hits enter but output does not happen.
Here is my code. Have a look at it. Maybe you notice what I did wrong.
#include <stdio.h>
#include <string.h>
#define SIZE 100
const char* morseEncode(char x){
switch(x){
case 'A':
case 'a':
return ".-";
case 'B':
case 'b':
return "-...";
case 'C':
case 'c':
case 'Ç':
case 'ç':
return "-.-.";
case 'D':
case 'd':
return "-..";
case 'E':
case 'e':
return ".";
case 'F':
case 'f':
return "..-.";
case 'G':
case 'g':
case 'Ğ':
case 'ğ':
return "--.";
case 'H':
case 'h':
return "....";
case 'I':
case 'ı':
case 'İ':
case 'i':
return "..";
case 'J':
case 'j':
return ".---";
case 'K':
case 'k':
return "-.-";
case 'L':
case 'l':
return ".-..";
case 'M':
case 'm':
return "--";
case 'N':
case 'n':
return "-.";
case 'O':
case 'o':
return "---";
case 'Ö':
case 'ö':
return "---.";
case 'P':
case 'p':
return ".--.";
case 'Q':
case 'q':
return "--.-";
case 'R':
case 'r':
return ".-.";
case 'S':
case 's':
case 'Ş':
case 'ş':
return "...";
case 'T':
case 't':
return "-";
case 'U':
case 'u':
return "..-";
case 'Ü':
case 'ü':
return "..--";
case 'V':
case 'v':
return "...-";
case 'W':
case 'w':
return ".--";
case 'X':
case 'x':
return "-..-";
case 'Y':
case 'y':
return "-.--";
case 'Z':
case 'z':
return "--..";
default:
return NULL;
}
}
void morseCode (const char *p){
for(int i=0;p[i];i++){
printf("%s/",morseEncode(p[i]));
}
}
int main() {
char phrase[SIZE];
printf("Code is non-sensitive to letters.\nEnter phrase: ");
scanf("%c",phrase);
puts("");
morseCode(phrase);
}
I think I did something wrong in conversions such as const char* to char or vice-versa.
const char *phrase;
phrase is uninitialised, so when you do
scanf("%s",phrase);
you're writing into some random place in memory causing undefined behaviour.
You need to allocate space for your string first. Either as an array
char phrase[100];
or by allocating memory
char *phrase=malloc(100);
And also the const qualifier in the declaration makes little sense since you change the contents when you pass it to scanf. Having it on the function is fine as the functions don't change the value.
The problem is that I ask a character as an input.
scanf("%c",phrase);
So, eventhough user inputs a string, it only saves the first character. Changing it to ask for a string solved the logical error.
scanf("%s",phrase);
For C language, I know I'm close, but for for any character inputted, the printout is "Consonant". What is wrong with my switch case statement. Will I need if statements?
#include <stdio.h>
#include <stdlib.h>
int main()
{
char name;
printf("Enter a character: ");
scanf_s("%c", &name);
switch (name)
{
case 'a':
printf("Vowel");
break;
case 'e':
printf("Vowel");
break;
case 'i':
printf("Vowel");
break;
case 'o':
printf("Vowel");
break;
case'u':
printf("Vowel");
break;
case 'y':
printf("Sometimes");
break;
default:
printf("Consonant");
}
return 0;
}
Note that the Microsoft page for scanf_s() says:
In the case of characters, a single character may be read as follows:
char c;
scanf_s("%c", &c, 1);
Your scanf_s() call is failing, but you are not checking the result, so you don't know that.
ALWAYS check the result of input functions!
And make sure you've read the manual page for functions you're using.
It's probably also a good idea to use " %c" as the format string to skip white space. However, that's a refinement for later.
You don't have a break; after the code in the default: case label. That's not a good idea.
You can use:
if (scanf_s("%c", &name, 1) == 1)
{
switch (name)
{
case 'a':
case 'e':
case 'i':
case 'o':
case 'u':
printf("Vowel\n");
break;
case 'y':
printf("Sometimes\n");
break;
default:
printf("Consonant\n");
break;
}
}
else
fprintf(stderr, "Failed to read a character\n");
Note that all upper-case letters, punctuation, white space and control characters are deemed to be consonants. That's not entirely accurate.
Can someone please help me fix my code.I have a text file with hexadecimal values. Now I need to convert the hexadecimal value to binary and print it. This is my code so far:
#include <stdio.h>
#include <stdlib.h>
#define MAX 1000
int hex_to_binary(char *argv[])
int main(int argc,char *argv[])
{
FILE *file;
file = fopen(argv[1],"r");
char line[100];
while(!feof(file)){
fgets(line,100,file);
hex_to_binary(line);
}
fclose(file);
return 0;
}
int hex_to_binary(char *argv[]){
char binaryNumber[MAX],hexaDecimal[MAX];
long int i=0;
scanf(“%s”,argv[1]);
printf("\nEquivalent binary value: ");
while(hexaDecimal[i]){
switch(hexaDecimal[i]){
case '0': printf("0000"); break;
case '1': printf("0001"); break;
case '2': printf("0010"); break;
case '3': printf("0011"); break;
case '4': printf("0100"); break;
case '5': printf("0101"); break;
case '6': printf("0110"); break;
case '7': printf("0111"); break;
case '8': printf("1000"); break;
case '9': printf("1001"); break;
case 'A': printf("1010"); break;
case 'B': printf("1011"); break;
case 'C': printf("1100"); break;
case 'D': printf("1101"); break;
case 'E': printf("1110"); break;
case 'F': printf("1111"); break;
case 'a': printf("1010"); break;
case 'b': printf("1011"); break;
case 'c': printf("1100"); break;
case 'd': printf("1101"); break;
case 'e': printf("1110"); break;
case 'f': printf("1111"); break;
default: printf("\nInvalid hexadecimal digit %c ",hexaDecimal[i]); return 0;
}
i++;
}
return 0;
}
I keep getting errors such as:
part1_V2.c: In function ‘hex_to_binary’:
part1_V2.c:8: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘{’ token
part1_V2.c:22: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘{’ token
part1_V2.c:26: error: stray ‘\342’ in program
part1_V2.c:26: error: stray ‘\200’ in program
part1_V2.c:26: error: stray ‘\234’ in program
part1_V2.c:26: error: stray ‘\342’ in program
part1_V2.c:26: error: stray ‘\200’ in program
part1_V2.c:26: error: stray ‘\235’ in program
part1_V2.c:59: error: expected ‘{’ at end of input
Thanks in advance!
Ok guys thanks for your help I got my code working but now I'm have trouble with the output:
The textfile I pass to the main function contains:
"1283" (line1)
"5105" (next line)
These are the hex values on the file. So when I run the program I get output:
Equivalent binary value: 0001001010000011
nvalid hexadecimal digit
Invalid hexadecimal digit
Equivalent binary value: 0101000100000101
I'm wondering why I'm getting the invalid hexadecimal digit output? Is it because it is trying to convert "\n" or empty space to binary?
It seems like there are a couple of non-ascii characters in your code, e.g. “ and ”, which should be ".
What's left are syntax and type errors.
There are some syntax errors in your code. Try this modified code. If you are passing right parameters to main() than it should work:
#include <stdio.h>
int hex_to_binary(char*);
int main(int argc, char *argv[])
{
FILE *file;
file = fopen(argv[1],"r");
char line[100];
while(!feof(file)){
fgets(line,100,file);
hex_to_binary(line);
}
fclose(file);
getchar();
return 0;
}
int hex_to_binary(char* hex_string)
{
int i=0;
printf("\nEquivalent binary value: ");
while(hex_string[i])
{
switch(hex_string[i])
{
case '0': printf("0000"); break;
case '1': printf("0001"); break;
case '2': printf("0010"); break;
case '3': printf("0011"); break;
case '4': printf("0100"); break;
case '5': printf("0101"); break;
case '6': printf("0110"); break;
case '7': printf("0111"); break;
case '8': printf("1000"); break;
case '9': printf("1001"); break;
case 'A': printf("1010"); break;
case 'B': printf("1011"); break;
case 'C': printf("1100"); break;
case 'D': printf("1101"); break;
case 'E': printf("1110"); break;
case 'F': printf("1111"); break;
case 'a': printf("1010"); break;
case 'b': printf("1011"); break;
case 'c': printf("1100"); break;
case 'd': printf("1101"); break;
case 'e': printf("1110"); break;
case 'f': printf("1111"); break;
default: printf("\nInvalid hexadecimal digit %c ", hex_string[i]);
}
i++;
}
return 0;
}
you first minor error is at function definition at line 5. Add a semicolon on the end:
int hex_to_binary(char *argv[]);
Also there in no use for it, so delete the line:
scanf(“%s”,argv[1]);
And rewrite the while loop:
while(hexaDecimal[i]!='\n' && hexaDecimal[i]!='\0')
{
switch(hexaDecimal[i])
{
...
}
i++;
}
Note thet i++ is within the loop. Plus the return 0 statement on the end is outside any function. Move it in.
Hope this helps!
As mentioned in the comments you are missing a ; on line 5.
Missing a ; can cause a cascade of errors, due to the compiler looking for something to end the statement (which wasn't ended by the ;).
I'm going to go into teacher mode so I apologise in advance if I come across as condescending.
Bearing that in mind, attempt to fix each error in turn. The error messages always look really technical, but if you stop and read it it gives a lot of information.
So for your first error, on line 8, it's stating that it was expecting something be the {. Since this is the start of the main function, the contents of lines 7-8 are correct, so the error must be before these two lines.
Before your main function is a function prototype, which...aha...is missing the semicolon.
In regards to the errors saying stray \xxx in program, this is likely because you've copied the scanf("%s", argv[1]) line from a word document or website, and it's copied a formatted pair of quote marks.
To fix, just delete the quotes and type them by hand.
My code (below) takes a text file with hexadecimal values and converts the hexadecimal value to binary and prints it. How can I modify this so that my hex_to_binary function can initialise a string array and add the converted binary to the array and then return the array. Then I just want to print the output of the hex_to_binary function by adding a printf statement in my main function. Thanks in advance
#include <stdio.h>
int hex_to_binary(char*);
int main(int argc, char *argv[])
{
FILE *file;
file = fopen(argv[1],"r");
char line[100];
while(!feof(file)){
fgets(line,100,file);
hex_to_binary(line);
}
fclose(file);
getchar();
return 0;
}
int hex_to_binary(char* hex_string)
{
int i=0;
printf("\nEquivalent binary value: ");
while(hex_string[i])
{
switch(hex_string[i])
{
case '0': printf("0000"); break;
case '1': printf("0001"); break;
case '2': printf("0010"); break;
case '3': printf("0011"); break;
case '4': printf("0100"); break;
case '5': printf("0101"); break;
case '6': printf("0110"); break;
case '7': printf("0111"); break;
case '8': printf("1000"); break;
case '9': printf("1001"); break;
case 'A': printf("1010"); break;
case 'B': printf("1011"); break;
case 'C': printf("1100"); break;
case 'D': printf("1101"); break;
case 'E': printf("1110"); break;
case 'F': printf("1111"); break;
case 'a': printf("1010"); break;
case 'b': printf("1011"); break;
case 'c': printf("1100"); break;
case 'd': printf("1101"); break;
case 'e': printf("1110"); break;
case 'f': printf("1111"); break;
}
i++;
}
return 0;
}
There are several ways to do this.
The one thing you can't do is declare a character array in the function, use sprintf to print to it, and return it. You cannot be certain that the space it points to exists anymore after the function returns.
That is, DON'T do this:
int hex_to_binary(char *hex_string)
{
char binary_string[MAX_SIZE + 1];
<...>
return binary_string;
}
To do exactly what you state, you can call malloc to obtain the space inside the function, then return a pointer to it:
int hex_to_binary(char *hex_string)
{
char *binary_string;
if((binary_string = malloc(MAX_SIZE + 1)) == NULL)
return -1; /* Indicate failure */
binary_string[0] = '\0';
<etc>
switch(hex_string[i])
{
case '0' : strcat(binary_string, "0000"); break;
<etc>
return binary_string;
}
This is permitted, because malloc is allocating the memory, probably in the heap, and this memory will still exist afterwards. The issue is, the function that calls hex_to_binary needs to call free() to release this memory, otherwise every call steals a little bit of memory -- this is known as a memory leak.
That is, do:
char *binary_line;
while(!feof(file)){
fgets(line,100,file);
binary_line = hex_to_binary(line);
printf("%s", binary_line);
free(binary_line);
}
NOT
while(!feof(file)){
fgets(line,100,file);
printf("%s", hex_to_binary(line););
}
If you were to call the hex_to_binary in a loop, once per hex digit, you could change the case statements to return a pointer to a string, instead of printing:
switch(hex_digit)
{
case '0' : return "0000";
case '2' : return "0001";
<etc>
This returns a pointer to constant string that you could print and saves freeing the space afterwards.
Another option would be to pass hex_to_binary two parameters, one with the string to convert, and one a pointer to the space to write it to:
int hex_to_binary(char *hex_string, char *binary_line)
{
<etc>
switch(hex_string[i])
{
case '0' : strcat(binary_string, "0000"); break;
<etc>
return 0;
}
Call it like this:
char binary_line[MAX_SPACE + 1];
while(!feof(file)){
fgets(line,100,file);
hex_to_binary(line, binary_line);
printf("%s", binary_line);
}
strcat() function is what you want.
if I were you, for simplicity I do this one below :
Define Global Char array :
char buffer[1000]; // define a space to write our string
....
Change your hex function like this :
while(hex_string[i])
{
switch(hex_string[i])
{
case '0': strcat(buffer,"0000"); break;
case '1': strcat(buffer,"0001"); break;
case '2': strcat(buffer,"0010"); break;
....
}
}
In main use this to print your string :
printf("%s\n",buffer);
Note: Don't forget to clear buffer after your each hex_to_binary function call (otherwise it keeps the previous numbers inside)
change to like this :
#include <stdio.h>
#include <string.h>
#include <ctype.h>
char *hexstr_to_binstr(char *outbuff, const char *s);
int main(int argc, char *argv[]){
FILE *file = fopen(argv[1],"r");
char line[100];
char binstr[4*sizeof(line)];
while(fgets(line, sizeof(line), file)){
puts(hexstr_to_binstr(binstr, line));
}
fclose(file);
getchar();
return 0;
}
const char *xdigit_to_binstr(char x){
switch(x){
case '0': return("0000");
case '1': return("0001");
case '2': return("0010");
case '3': return("0011");
case '4': return("0100");
case '5': return("0101");
case '6': return("0110");
case '7': return("0111");
case '8': return("1000");
case '9': return("1001");
case 'a':
case 'A': return("1010");
case 'b':
case 'B': return("1011");
case 'c':
case 'C': return("1100");
case 'd':
case 'D': return("1101");
case 'e':
case 'E': return("1110");
case 'f':
case 'F': return("1111");
default : return "";
}
return NULL;//never reach this point
}
char *hexstr_to_binstr(char *outbuff, const char *s){
char *p = outbuff;
for(; *s ; ++s){
if(isxdigit(*s)){
memcpy(p, xdigit_to_binstr(*s), 4);
p += 4;
}
}
*p = 0;
return outbuff;
}