C++ printf: newline (\n) from commandline argument - c++

How print format string passed as argument ?
example.cpp:
#include <iostream>
int main(int ac, char* av[])
{
printf(av[1],"anything");
return 0;
}
try:
example.exe "print this\non newline"
output is:
print this\non newline
instead I want:
print this
on newline

No, do not do that! That is a very severe vulnerability. You should never accept format strings as input. If you would like to print a newline whenever you see a "\n", a better approach would be:
#include <iostream>
#include <cstdlib>
int main(int argc, char* argv[])
{
if ( argc != 2 ){
std::cerr << "Exactly one parameter required!" << std::endl;
return 1;
}
int idx = 0;
const char* str = argv[1];
while ( str[idx] != '\0' ){
if ( (str[idx]=='\\') && (str[idx+1]=='n') ){
std::cout << std::endl;
idx+=2;
}else{
std::cout << str[idx];
idx++;
}
}
return 0;
}
Or, if you are including the Boost C++ Libraries in your project, you can use the boost::replace_all function to replace instances of "\\n" with "\n", as suggested by Pukku.

At least if I understand correctly, you question is really about converting the "\n" escape sequence into a new-line character. That happens at compile time, so if (for example) you enter the "\n" on the command line, it gets printed out as "\n" instead of being converted to a new-line character.
I wrote some code years ago to convert escape sequences when you want it done. Please don't pass it as the first argument to printf though. If you want to print a string entered by the user, use fputs, or the "%s" conversion format:
int main(int argc, char **argv) {
if (argc > 1)
printf("%s", translate(argv[1]));
return 0;
}

You can't do that because \n and the like are parsed by the C compiler. In the generated code, the actual numerical value is written.
What this means is that your input string will have to actually contain the character value 13 (or 10 or both) to be considered a new line because the C functions do not know how to handle these special characters since the C compiler does it for them.
Alternatively you can just replace every instance of \\n with \n in your string before sending it to printf.

passing user arguments directly to printf causes a exploit called "String format attack"
See Wikipedia and Much more details

There's no way to automatically have the string contain a newline. You'll have to do some kind of string replace on your own before you use the parameter.

It is only the compiler that converts \n etc to the actual ASCII character when it finds that sequence in a string.
If you want to do it for a string that you get from somewhere, you need to manipulate the string directly and replace the string "\n" with a CR/LF etc. etc.
If you do that, don't forget that "\\" becomes '\' too.
Please never ever use char* buffers in C++, there is a nice std::string class that's safer and more elegant.

I know the answer but is this thread is active ?
btw
you can try
example.exe "print this$(echo -e "\n ")on newline".
I tried and executed
Regards,
Shahid nx

Related

Garbled character output when using cout API

I am trying to run this simple code in VS 2015
#include "stdafx.h"
# include <iostream>
int main()
{
char * szOldPath = "\"C:\icm\scripts\StartupSync\runall.bat\" nonprod";
std::cout << szOldPath << std::endl;
return 0;
}
However, the output of szOldPath is not proper and the console is printing--
unall.bat" nonprodupSync
I suspect this might be because of Unicode and I should be using wcout. So I disabled Unicode by going to Configuration Properties -> General --> Character Set and tried setting it to Not Set or Multi Byte. But still running into this issue.
I understand it is not good to disable UNICODE but I am trying to understand some legacy code written in our company and this experiment is a part of this exercise,is there any way I can get the cout command to print szOldPath successfully?
Your issue has nothing to do with Unicode.
\r is the escape sequence for a carriage return. So, you are printing out "C:\icm\scripts\StartupSync, and then \r tells the terminal to move the cursor back to the beginning of the current line, and then unall.bat" nonprod is printed, overwriting what was already there.
You need to escape all of the \ characters in your string literal, just like you had to escape the " characters.
Also, your variable needs to be declared as a pointer to const char when assigning a string literal to the pointer. This is enforced in C++11 and later:
#include "stdafx.h"
#include <iostream>
int main()
{
const char * szOldPath = "\"C:\\icm\\scripts\\StartupSync\\runall.bat\" nonprod";
std::cout << szOldPath << std::endl;
return 0;
}
Alternatively, in C++11 and later, you can use a raw string literal instead to avoid having to escape any characters with a leading \:
const char * szOldPath = R"("C:\icm\scripts\StartupSync\runall.bat" nonprod)";

Properly handle escape sequences in strings from argv in C++

I'm writing a larger program that takes arguments from the command line after the executable. Some of the arguments are expected to be passed after the equals sign of an option. For instance, the output to the log is a comma separated vector by default, but if the user wants to change the separator to a period or something else instead of a comma, they might give the argument as:
./main --separator="."
This works fine, but if a user wants the delimiter be a special character (for example: tab), they might expect to pass the escape sequence in one of the following ways:
./main --separator="\t"
./main --separator='\t'
./main --separator=\t
It doesn't behave the way I want it to (to interpret \t as a tab) and instead prints out the string as written (sans quotes, and with no quotes it just prints 't'). I've tried using double slashes, but I think I might just be approaching this incorrectly and I'm not sure how to even ask the question properly (I tried searching).
I've recreated the issue in a dummy example here:
#include <string>
#include <iostream>
#include <cstdio>
// Pull the string value after the equals sign
std::string get_option( std::string input );
// Verify that the input is a valid option
bool is_valid_option( std::string input );
int main ( int argc, char** argv )
{
if ( argc != 2 )
{
std::cerr << "Takes exactly two arguments. You gave " << argc << "." << std::endl;
exit( -1 );
}
// Convert from char* to string
std::string arg ( argv[1] );
if ( !is_valid_option( arg ) )
{
std::cerr << "Argument " << arg << " is not a valid option of the form --<argument>=<option>." << std::endl;
exit( -2 );
}
std::cout << "You entered: " << arg << std::endl;
std::cout << "The option you wanted to use is: " << get_option( arg ) << "." << std::endl;
return 0;
}
std::string get_option( std::string input )
{
int index = input.find( '=' );
std::string opt = input.substr( index + 1 ); // We want everything after the '='
return opt;
}
bool is_valid_option( std::string input )
{
int equals_index = input.find('=');
return ( equals_index != std::string::npos && equals_index < input.length() - 1 );
}
I compile like this:
g++ -std=c++11 dummy.cpp -o dummy
With the following commands, it produces the following outputs.
With double quotes:
/dummy --option="\t"
You entered: --option=\t
The option you wanted to use is: \t.
With single quotes:
./dummy --option='\t'
You entered: --option=\t
The option you wanted to use is: \t.
With no quotes:
./dummy --option=\t
You entered: --option=t
The option you wanted to use is: t.
My question is: Is there a way to specify that it should interpret the substring \t as a tab character (or other escape sequences) rather than the string literal "\t"? I could parse it manually, but I'm trying to avoid re-inventing the wheel when I might just be missing something small.
Thank you very much for your time and answers. This is something so simple that it's been driving me crazy that I'm not sure how to fix it quickly and simply.
The escape sequences are already parsed from the shell you use, and are passed to your command line parameters array argv accordingly.
As you noticed only the quoted versions will enable you to detect that a "\\t" string was parsed and passed to your main().
Since most shells may just skip a real TAB character as a whitespace, you'll never see it in your command line arguments.
But as mentioned it's mainly a problem of how the shell interprets the command line, and what's left going to your program call arguments, than how to handle it with c++ or c.
My question is: Is there a way to specify that it should interpret the substring \t as a tab character (or other escape sequences) rather than the string literal "\t"? I could parse it manually, but I'm trying to avoid re-inventing the wheel when I might just be missing something small.
You actually need to scan for a string literal
"\\t"
within the c++ code.

How could I copy data that contain '\0' character

I'm trying to copy data that conatin '\0'. I'm using C++ .
When the result of the research was negative, I decide to write my own fonction to copy data from one char* to another char*. But it doesn't return the wanted result !
My attempt is the following :
#include <iostream>
char* my_strcpy( char* arr_out, char* arr_in, int bloc )
{
char* pc= arr_out;
for(size_t i=0;i<bloc;++i)
{
*arr_out++ = *arr_in++ ;
}
*arr_out = '\0';
return pc;
}
int main()
{
char * out= new char[20];
my_strcpy(out,"12345aa\0aaaaa AA",20);
std::cout<<"output data: "<< out << std::endl;
std::cout<< "the length of my output data: " << strlen(out)<<std::endl;
system("pause");
return 0;
}
the result is here:
I don't understand what is wrong with my code.
Thank you for help in advance.
Your my_strcpy is working fine, when you write a char* to cout or calc it's length with strlen they stop at \0 as per C string behaviour. By the way, you can use memcpy to copy a block of char regardless of \0.
If you know the length of the 'string' then use memcpy. Strcpy will halt its copy when it meets a string terminator, the \0. Memcpy will not, it will copy the \0 and anything that follows.
(Note: For any readers who are unaware that \0 is a single-character byte with value zero in string literals in C and C++, not to be confused with the \\0 expression that results in a two-byte sequence of an actual backslash followed by an actual zero in the string... I will direct you to Dr. Rebmu's explanation of how to split a string in C for further misinformation.)
C++ strings can maintain their length independent of any embedded \0. They copy their contents based on this length. The only thing is that the default constructor, when initialized with a C-string and no length, will be guided by the null terminator as to what you wanted the length to be.
To override this, you can pass in a length explicitly. Make sure the length is accurate, though. You have 17 bytes of data, and 18 if you want the null terminator in the string literal to make it into your string as part of the data.
#include <iostream>
using namespace std;
int main() {
string str ("12345aa\0aaaaa AA", 18);
string str2 = str;
cout << str;
cout << str2;
return 0;
}
(Try not to hardcode such lengths if you can avoid it. Note that you didn't count it right, and when I corrected another answer here they got it wrong as well. It's error prone.)
On my terminal that outputs:
12345aaaaaaa AA
12345aaaaaaa AA
But note that what you're doing here is actually streaming a 0 byte to the stdout. I'm not sure how formalized the behavior of different terminal standards are for dealing with that. Things outside of the printable range can be used for all kinds of purposes depending on the kind of terminal you're running... positioning the cursor on the screen, changing the color, etc. I wouldn't write out strings with embedded zeros like that unless I knew what the semantics were going to be on the stream receiving them.
Consider that if what you're dealing with are bytes, not to confuse the issue and to use a std::vector<char> instead. Many libraries offer alternatives, such as Qt's QByteArray
Your function is fine (except that you should pass to it 17 instead of 20). If you need to output null characters, one way is to convert the data to std::string:
std::string outStr(out, out + 17);
std::cout<< "output data: "<< outStr << std::endl;
std::cout<< "the length of my output data: " << outStr.length() <<std::endl;
I don't understand what is wrong with my code.
my_strcpy(out,"12345aa\0aaaaa AA",20);
Your string contains character '\' which is interpreted as escape sequence. To prevent this you have to duplicate backslash:
my_strcpy(out,"12345aa\\0aaaaa AA",20);
Test
output data: 12345aa\0aaaaa AA
the length of my output data: 18
Your string is already terminated midway.
my_strcpy(out,"12345aa\0aaaaa AA",20);
Why do you intend to have \0 in between like that? Have some other delimiter if yo so desire
Otherwise, since std::cout and strlen interpret a \0 as a string terminator, you get surprises.
What I mean is that follow the convention i.e. '\0' as string terminator

sscanf for this type of string

I'm not quite sure even after reading the documentation how to do this with sscanf.
Here is what I want to do:
given a string of text:
Read up to the first 64 chars or until space is reached
Then there will be a space, an = and then another space.
Following that I want to extract another string either until the end of the string or if 8192 chars are reached. I would also like it to change any occurrences in the second string of "\n" to the actual newline character.
I have: "%64s = %8192s" but I do not think this is correct.
Thanks
Ex:
element.name = hello\nworld
Would have string 1 with element.name and string2 as
hello
world
I do recommend std::regex for this, but apart from that, you should be fine with a little error checking:
#include <cstdio>
int main(int argc, const char *argv[])
{
char s1[65];
char s2[8193];
if (2!=std::scanf("%64s = %8192s", s1, s2))
puts("oops");
else
std::printf("s1 = '%s', s2 = '%s'\n", s1, s2);
return 0;
}
Your format string looks right to me; however, sscanf will not change occurences of "\n" to anything else. To do that you would then need to write a loop that uses strtok or even just a simple for loop evaluating each character in the string and swapping it for whatever character you prefer. You will also need to evaluate the sscanf return value to determine if the 2 strings were indeed scanned correctly. sscanf returns the number of field successfully scanned according to your format string.
#sehe shows the correct usage of sscanf including the check for the proper return value.

How to print '\n' instead of a newline?

I am writing a program that uses prints a hex dump of its input. However, I'm running into problems when newlines, tabs, etc are passed in and destroying my output formatting.
How can I use printf (or cout I guess) to print '\n' instead of printing an actual newline? Do I just need to do some manual parsing for this?
EDIT: I'm receiving my data dynamically, it's not just the \n that I'm corned about, but rather all symbols. For example, this is my printf statement:
printf("%c", theChar);
How can I make this print \n when a newline is passed in as theChar but still make it print normal text when theChar is a valid printable character?
Print "\\n" – "\\" produces "\" and then "n" is recognized as an ordinary symbol. For more information see here.
The function printchar() below will print some characters as "special", and print the octal code for characters out of range (a la Emacs), but print normal characters otherwise. I also took the liberty of having '\n' print a real '\n' after it to make your output more readable. Also note that I use an int in the loop in main just to be able to iterate over the whole range of unsigned char. In your usage you would likely just have an unsigned char that you read from your dataset.
#include <stdio.h>
static void printchar(unsigned char theChar) {
switch (theChar) {
case '\n':
printf("\\n\n");
break;
case '\r':
printf("\\r");
break;
case '\t':
printf("\\t");
break;
default:
if ((theChar < 0x20) || (theChar > 0x7f)) {
printf("\\%03o", (unsigned char)theChar);
} else {
printf("%c", theChar);
}
break;
}
}
int main(int argc, char** argv) {
int theChar;
(void)argc;
(void)argv;
for (theChar = 0x00; theChar <= 0xff; theChar++) {
printchar((unsigned char)theChar);
}
printf("\n");
}
Just use "\\n" (two slashes)
You can escape the backslash to make it print just a normal backslash: "\\n".
Edit: Yes you'll have to do some manual parsing. However the code to do so, would just be a search and replace.
If you want to make sure that you don't print any non-printable characters, then you can use the functions in ctype.h like isprint:
if( isprint( theChar ) )
printf( "%c", theChar )
else
switch( theChar )
{
case '\n':
printf( "\\n" );
break;
... repeat for other interesting control characters ...
default:
printf( "\\0%hho", theChar ); // print octal representation of character.
break;
}
printf("\\n");
In addition to the examples provided by other people, you should look at the character classification functions like isprint() and iscntrl(). Those can be used to detect which characters are or aren't printable without having to hardcode hex values from an ascii table.
In C/C++, the '\' character is reserved as the escape character. So whenever you want to actually print a '\', you must enter '\'. So to print the actual '\n' value you would print the following:
printf("\\n");
Just use String::replace to replace the offending characters before you call printf.
You could wrap the printf to do something like this:
void printfNeat(char* str)
{
string tidyString(str);
tidyString.replace("\n", "\\n");
printf(tidyString);
}
...and just add extra replace statements to rid yourself of other unwanted characters.
[Edit] or if you want to use arguments, try this:
void printfNeat(char* str, ...)
{
va_list argList;
va_start(argList, msg);
string tidyString(str);
tidyString.replace("\n", "\\n");
vprintf(tidyString, argList);
va_end(argList);
}
As of C++11 you can also use raw strings
std::printf(R"(\n)");
everything inside the R"( and )" will be printed literally. escape sequences will not be processed.
There are three solutions for this question:
Solution 1:
Every Symbol, Number, Alphabet has it's own ASCII value. The ASCII value of '\' as 92 and 'n' as 110. The immediate values(Numbers (ASCII)) are stored onto two integer variables. While printing, the format specifier %c (Character), is used.
void main() {
int i=92, j=110;
clrscr();
printf("%c%c", i, j);
getch();
}
Try it out in your C programming software...
Solution 2:
The programs works. But I think this one isn't fair...
At the output screen, type the input as \n...
you will get another \n..
void main() {
char a[10];
gets(a);
printf("\n\n\n\n");
puts(a);
getch();
}
Try out the programs
Solution 3:
Already said above use \n