The C Programming Language, 2nd Edition, by Kernighan and Ritchie
Exercise 3.02 on page 60
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.
Solution by Vidhan Gupta
/* 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 esacpe sequences into the real characters. */ #include <stdio.h> #define MAXIMUM 1000 int main() { int c, i = 0; char s[MAXIMUM]; while ((c = getchar()) != EOF) { switch (c) { case '\n': printf("\\n"); break; case '\t': printf("\\t"); break; default: putchar(c); break; } s[i] = c; i++; } printf("\n%s\n", s); return 0; }
Solution by Paul Griffiths
/* EX3_2.C ======= Suggested solution to Exercise 3-2 */ #include <stdio.h> void escape(char * s, char * t); void unescape(char * s, char * t); int main(void) { char text1[50] = "\aHello,\n\tWorld! Mistakee\b was \"Extra 'e'\"!\n"; char text2[51]; printf("Original string:\n%s\n", text1); escape(text2, text1); printf("Escaped string:\n%s\n", text2); unescape(text1, text2); printf("Unescaped string:\n%s\n", text1); return 0; } /* Copies string t to string s, converting special characters into their appropriate escape sequences. The "complete set of escape sequences" found in K&R Chapter 2 is used, with the exception of: \? \' \ooo \xhh as these can be typed directly into the source code, (i.e. without using the escape sequences themselves) and translating them is therefore ambiguous. */ void escape(char * s, char * t) { int i, j; i = j = 0; while ( t[i] ) { /* Translate the special character, if we have one */ switch( t[i] ) { case '\n': s[j++] = '\\'; s[j] = 'n'; break; case '\t': s[j++] = '\\'; s[j] = 't'; break; case '\a': s[j++] = '\\'; s[j] = 'a'; break; case '\b': s[j++] = '\\'; s[j] = 'b'; break; case '\f': s[j++] = '\\'; s[j] = 'f'; break; case '\r': s[j++] = '\\'; s[j] = 'r'; break; case '\v': s[j++] = '\\'; s[j] = 'v'; break; case '\\': s[j++] = '\\'; s[j] = '\\'; break; case '\"': s[j++] = '\\'; s[j] = '\"'; break; default: /* This is not a special character, so just copy it */ s[j] = t[i]; break; } ++i; ++j; } s[j] = t[i]; /* Don't forget the null character */ } /* Copies string t to string s, converting escape sequences into their appropriate special characters. See the comment for escape() for remarks regarding which escape sequences are translated. */ void unescape(char * s, char * t) { int i, j; i = j = 0; while ( t[i] ) { switch ( t[i] ) { case '\\': /* We've found an escape sequence, so translate it */ switch( t[++i] ) { case 'n': s[j] = '\n'; break; case 't': s[j] = '\t'; break; case 'a': s[j] = '\a'; break; case 'b': s[j] = '\b'; break; case 'f': s[j] = '\f'; break; case 'r': s[j] = '\r'; break; case 'v': s[j] = '\v'; break; case '\\': s[j] = '\\'; break; case '\"': s[j] = '\"'; break; default: /* We don't translate this escape sequence, so just copy it verbatim */ s[j++] = '\\'; s[j] = t[i]; } break; default: /* Not an escape sequence, so just copy the character */ s[j] = t[i]; } ++i; ++j; } s[j] = t[i]; /* Don't forget the null character */ }
Solution by Luke Panayi
My personal solution - only deals with \n and \t as the rest is just copy pasting the same concept. Hope I'm not this lonely for the rest of the book, it's only chapter 3 and most people seem to have vanished!
#include <stdio.h> #define BUFFER 1000 void escape(char s[], char t[]) { int i, j=0; /*j is used as a counter to track how far ahead t is over s when multiple characters need to be added in the place of one*/ for (i=0; s[i-j] != '\0'; ++i) { switch(s[i-j]) { case '\n': t[i] = '\\'; t[++i] = 'n'; ++j; break; case '\t': t[i] = '\\'; t[++i] = 't'; ++j; break; default: t[i] = s[i-j]; break; } } t[i] = '\0'; } void reverseEscape(char s[], char t[]) { int i, j=0; for (i=0; s[i+j] != '\0'; ++i) { switch(s[i+j]) { case '\\': switch(s[i+j+1]) { case 'n': t[i] = '\n'; ++j; ++i; //increment i to skip next character break; case 't': t[i] = '\t'; ++j; ++i; break; } default: t[i] = s[i+j]; break; } } t[i] = '\0'; } int main() { int i, c; char s[BUFFER], t[BUFFER]; for (i=0; i<BUFFER-1 && (c=getchar()) != EOF; ++i) s[i] = c; s[i] = '\0'; escape(s,t); printf("%s\n", t); return 0; }
Solution by Codybartfast (category 0)
The unescape function here can handle a string that ends with a single backslash. If an unescape function reads ahead for the character after a backslash, without checking if it is '\0', then the loop will continue indefinately beyond the end of the string. (Alternatively, strlen could be used to find the end of a string instead of checking for '\0').
enum bool { NO, YES }; void escape(char s[], char t[]) { int i = 0, j = 0; char c, e; while ((c = s[i++])) { if ((e = esc_char(c))) { t[j++] = '\\'; t[j++] = e; } else { t[j++] = c; } } t[j] = '\0'; } char esc_char(char c) { switch (c) { case '\\': return '\\'; case '\n': return 'n'; case '\r': return 'r'; case '\t': return 't'; case '"': return '"'; default: return '\0'; } } void unescape(char s[], char t[]) { int i = 0, j = 0, esc_mode = NO; char c; while ((c = s[i++])) { if (esc_mode) { t[j++] = unesc_char(c); esc_mode = NO; } else if (c == '\\') { esc_mode = YES; } else { t[j++] = c; } } t[j] = '\0'; } char unesc_char(char c) { switch (c) { case 'n': return '\n'; case 'r': return '\r'; case 't': return '\t'; case '\\': case '"': default: return c; } }