I'm trying to write a quine program for the follow C source code:
#include<stdio.h>
char name[] = "Jacob Stinson";
int main(){
char *c="#include<stdio.h> char name[] = \"Jacob Stinson\"; int main(){char *c=%c%s%c; prinf(c,34,c,34);}";
printf(c,34,c,34);
}
I need to include the backslash before the " in the string in order to properly print out line 3, however, when I print out *c, I want those backslashes to be present, as to correctly copy the source code. Currently it omits the backslashes from the output.
Wanted to see if anyone knows how to go about doing this.
As the compiler interprets escape sequences in only one direction (deescaping them) I think there's no possibility to include an escape sequence in the code and make it appear as such in the listing. The compiler will always eliminate one of the backslashes on input of the source file, making it appear different on output. The printf uses %s format to allow for the recursive part of the problem and allow you to shelf print, and, as you have guessed correctly, you have to use integer versions of delimiting chars for the " delimiting chars. Why to use %c to be able to delimit the strings in your program if there's an alternative method to include escape sequences? By the same reason, I was not able to include any end of line delimiter, so I wrote the same problem in one line (without using the #include <stdio.h> line) My solution was a one line (without the final end of line.)
Related
I have a strange problem when using string function in C.
Currently I have a function that sends string to UART port.
When I give to it a string like
char buf[32];
strcpy(buf, "AT+CPMS=\"SM");
strcat(buf, "\"");
uart0_putstr(buf);
//or
uart0_putstr("AT+CPMS=SM"); //not a valid AT command, but without quotes just for test
it works well and sends string to UART. But when I use such call:
char buf[32];
strcpy(buf, "AT+CPMS=\"SM\"");
uart0_putstr(buf);
//or
uart0_putstr("AT+CPMS=\"SM\"");
it doesn't print to UART anything.
Maybe you can explain me what the difference between strings in first and second/third cases?
First the C language part:
String literals: All C string literals include an implicit null byte at the end; the C string literal "123" defines a 4 byte array with the values 49,50,51,0. The null byte is always there even if it is never mentioned and enables strlen, strcat etc. to find the end of the string. The suggestion strcpy(buf, "AT+CPMS=\"SM\"\0"); is nonsensical: The character array produced by "AT+CPMS=\"SM\"\0" now ends in two consecutive zero bytes; strcpy will stop at the first one already. "" is a 1 byte array whose single element has the value 0. There is no need to append another 0 byte.
strcat, strcpy: Both functions always add a null byte at the end of the string. There is no need to add a second one.
Escaping: As you know, a C string literal consists of characters book-ended by double quotes: "abc". This makes it impossible to have simple double quotes as part of the string because that would end the string. We have to "escape" them. The C language uses the backslash to give certain characters a special meaning, or, in this case, suppress the special meaning. The entire combination of backslash and subsequent source code character are transformed into a single character, or byte, in the compiled program. The combination \n is transformed into a single byte with the value 13 (usually interpreted as a newline by output devices), \r is 10 (usually carriage return), and \" is transformed into the byte 34, usually printed as the " glyph. The string Between the arrows is a double quote: ->"<- must be coded as "Between the arrows is a double quote: ->\"<-" in C. The middle double quote doesn't end the string literal because it is "escaped".
Then the UART part: The internet makes me believe that the command you want to send over the UART looks like AT+CPMS="SM", followed by a carriage return. The corresponding C string literal would be "AT+CPMS=\"SM\"\r".
The page I linked also inserts a delay between sending commands. Sending too quickly may cause errors that appear only sometimes.
The things to note are :
The AT command syntax probably demands that SM be surrounded by quotes on both sides.
Additionally, the protocol probably demands that a command end in a carriage return.
This ...
char buf[32];
strcpy(buf, "AT+CPMS=\"SM");
strcat(buf, "\"");
... produces the same contents in buf as this ...
char buf[32];
strcpy(buf, "AT+CPMS=\"SM\"");
... does, up to and including the string terminator at index 12. I fully expect an immediately following call to ...
uart0_putstr(buf);
... to have the same effect in each case unless uart0_putstr() looks at bytes past the terminator or its behavior is sensitive to factors other than its argument.
If it does look past the terminator, however, then that might explain not only a difference between those two, but also a difference with ...
uart0_putstr("AT+CPMS=\"SM\"");
... because in this last case, looking past the string terminator would overrun the bounds of the array, producing undefined behavior.
Thanks all. Finally It was resolved with adding NULL char to the end of string.
#include <stdio.h>
char *prg = "char *prg = %c%s%c;main(){printf(prg,34,prg,34);} " ;
void main (){
printf(prg,34,prg,34);
}
Reason behind the following output
char *prg = "char *prg = %c%s%c;main(){printf(prg,34,prg,34);} ";main(){printf(prg,34,prg,34);}
the content in *prg Is printed but in place of "%c%s%c" the content is replaced, why is it embedded
That's the way printf() works - in the format (the first prg argument), each conversion specification (%c, %s) converts a subsequent argument (34, prg) according to the conversion specifier (c, s) and writes the result to the standard output.
That program is a classical example of a program that prints its source code to stdout. Ascii character 34 is the ascii literal for " which is needed to be able to print the delimiters of a C string without incurring in an infinite recursive problem. There are some characters that cannot be used literally, as they are transformed by the compiler, one of these is ", which dissapears when compiled in a string literal, others are the escaped char literals \n, \t,... depending on that, convert into a different char literal. This is the reason the source code must be all in one line (control chars transform themselves by the compiler), no #include ... statements must be allowed (because it ends in a newline), and other things like this.
Compile it and rearrange it (you have modified it, for clarity, on posting) so you can output the exact same source code as you give the compiler.
Note
The program code, to mimic exactly its source form in the output, must be written as:
char*p="char*p=%c%s%c;main(){printf(p,34,p,34);}";main(){printf(p,34,p,34);}
without a trailing newline at the end of the line.
If you substitute 34 by '\"', and p by its value, you'll get:
...
printf(
"char*p=%c%s%c;main(){printf(p,34,p,34);}",
'\"',
"char *p=%c%s%c;main(){printf(p,34,p,34);}",
'\"');
that will form the original string, putting the right delimiters at the proper positions. (note: the %c and %s in the third parameter are not further expanded)
Note2
This program depends on ASCII encoding for ". It should'n work on EBCDIC encodings (you must use the encoding for " instead of the number 34)
My goal here is to read through a text file that has to follow these formatting regulations:
No spaces/tabs between characters
Characters must be either non-negative integer or new line character (no letters/symbols)
I can only use functions given in stdlib.h and stdio.h
I am thinking of reading through the file character by character using the fgetc() function, but I can't think of a way that tests whether or not the character is a new line character (isn't a new line char /n, which would be two chars together which would ruin the idea of going char by char?).
Following this train of thought I was thinking that using getline(), which would negate the necessity of checking if a char is a new line character, would be easier (am I right in thinking this or would this not negate such a requirement?). Yet if I were to do this what would be the easiest way to traverse through the char string that this would produce in order to still check each individual character?
Also, if someone could think of an easier route as to checking for the format of a file using the given libraries that would be much appreciated.
If you use getline it will retain the newline character so you'll still have to check for it.
If you can use any of the standard C library then you can use isdigit(...) from ctypes.h
It returns non-zero if the input character is a digit.
If you use the getline function the input would be written into the buffer that you pass as the first argument. It will append a null terminal character to this buffer so you can walk through it as so:
for(char* s = buffer; *s; s++)
/* test *s */
I just came across this quine question, but no one really went into how it works: C/C++ program that prints its own source code as its output
char*s="char*s=%c%s%c;main(){printf(s,34,s,34);}";main(){printf(s,34,s,34);}
What I especially don't understand is the following has the same output even though I changed the ints:
char*s="char*s=%c%s%c;main(){printf(s,34,s,34);}";main(){printf(s,5,s,11);}
It still prints the 34s! Can someone walk me through this step by step?
Let's start by formatting the code to span multiple lines. This breaks the fact that it's a quine, but makes it easier to see what's happening:
char* s = "char*s=%c%s%c;main(){printf(s,34,s,34);}";
main() {
printf(s, 34, s, 34);
}
Essentially, this is a declaration of a string s that's a printf-formatted string, followed by a declaration of a function main that invokes printf on four arguments. (This definition of main uses the old-fashioned "implicit int" rule in C where functions are assumed to have int as a return type unless specified otherwise. I believe this is currently deprecated in C and know for certain that this is not legal C++ code.)
So what exactly is this printf call doing? Well, it might help to note that 34 is the ASCII code for a double-quote, so the line
printf(s, 34, s, 34);
is essentially
printf(s, '"', s, '"');
This means "print the string s with arguments ", s, and "." So what's s? It's shown here:
char* s = "char*s=%c%s%c;main(){printf(s,34,s,34);}";
This follows a common self-reference trick. Ignoring the %c%s%c part, this is basically a string representation of the rest of the program. The %c%s%c part occurs at the point where it becomes self-referential.
So what happens if you call printf(s, '"', s, '"')? This will fill in the placeholder %c%s%c with "char*s=%c%s%c;main(){printf(s,34,s,34);}", which is the string contents of the string s. Combined with the rest of the string s, this therefore proints
char*s="char*s=%c%s%c;main(){printf(s,34,s,34);}";main(){printf(s,34,s,34);";
which is the source code of the program. I think this is kinda neat - the closest English translation of a general Quine program I know is "print this string, the second time in quotes" (try it - see what happens!), and this basically does exactly that.
You were asking why changing the numbers to 5 and 11 didn't change that 34 was being printed. That's correct! The string literal s has 34 hard-coded into it, so changing the 5 and 11 in the call to printf won't change that. What it will do is no longer print the quotation marks around the inside of the string s and instead print non-printing characters.
I'm working with Arduino.
I want to send Ctrl+z after a string in C. I tried truncating ^Z but that didn't work. So how to do that ?
Ctrl+Z = 26 = '\032' = '\x1A'. Either of the backslash escape sequences can be written in a string literal (but be careful with the hex escape as if it is followed by a digit or A-F or a-f, that will also be counted as part of the hex escape, which is not what you want).
However, if you are simulating terminal input on a Windows machine (so you want the character to be treated as an EOF indication), you need to think again. That isn't how it works.
It may or may not do what you want with Arduino, either; in part, it depends on what you think it is going to do. It also depends on whether the input string will be treated as if it came from a terminal.
I hacked this up as I needed similar
#include <stdio.h>
#define CTRL(x) (#x[0]-'a'+1)
int main (void)
{
printf("hello");
printf("%c", CTRL(n));
printf("%c", CTRL(z));
}
hope it helps 8)
I assume by "truncating" you actually meant appending.
In ASCII, CTRL+z is code point 26 so you can simply append that as a character, something like:
#define CTRL_Z 26
char buffer[100];
sprintf (buffer, "This is my message%c", CTRL_Z);
The sprintf method is only one of the ways of doing this but they all basically depend on you putting a single byte at the end with the value 26.
The following should work:
whatever you are trying to write append \032 at the end
For example:
strcpy(InputCommand,"hi\032");
GetSerialData(InputCommand,......); //this is my own function which uses serialPuts()