How do I print "\n" explicitly in a string in c++ - c++

hi i have a unknown string in c++ containing "\n" "\t" etc.
say;
string unknown1=read_from_file();
if unknown1="\n\t\n\t\n\n\n\n\n" now I want to print
"\n\t\n\t\n\n\n\n\n"
to the screen explcitly other than a bunch of empty spaces.... how should I do that? remember that I don't know what is in unknown1...
to emphasize, I know that we could print \n explicitly if we change "\n" into "\n" for every such character... But the problem is that I don't know what is inside unknown1... It is read from a file....
Thanks for answering, however we have further concerns:
The procedure answered has one more porblem... Suppose I don't know that the only possible special character in the file is \n or \t... maybe there are something like \u ? \l ? i think we can't exhaust every possibility right? Is there kind of built in C++ function just to output the corresponding characters?

\n , \t are escape sequences, but you can print them by adding an extra \ before them, \\ is used to obtain a single backslash. A single backslash means it is an escape sequence ( if it is a valid one ), but two backslashes represent the backslash character, so whenever you need to output a backslash, just add two of them.
So, if you use
string unknown1="\\n\\t\\n\\t\\n\\n\\n\\n\\n";
You will get your desired output.
If you are reading from a file , then do something like this
string unknown1="\n\t\n\t\n\n\n\n\n";
for ( int i = 0 ; i < unknown1.length() ; i++ )
{
if( unknown1[i] == '\n')
cout<<"\\n";
}
Like that, you will have to check for each escape sequence that may be used.

Run specific checks for the non-printable characters you are worried about like this.
char c;
while(c!=EOF){
if(c=='\n')printf("\\n");
if(c=='\t')printf("\\t");
and so on and so forth.
c = the next charater;
}
oops, I wrote C instead of C++ but #Arun A.S has the right syntax

See below example. You can add your own characters to the switch to extend the characters it handles.
#include <iostream>
#include <string>
std::string escapeSpecialChars(const std::string& str)
{
std::string result;
for(auto c : str)
{
switch(c)
{
case '\n':
result += "\\n";
break;
case '\t':
result += "\\t";
break;
default:
result += c;
break;
}
}
return result;
}
int main()
{
std::string str = "\n\n\n\t";
std::cout << escapeSpecialChars(str);
return 0;
}

You could create your own function to print characters using a std::map:
void printChar( const char ch )
{
static const std::map< char, std::string > char_map = {
{ '\n', "\\n" }
// add mappings as needed
};
auto found = char_map.find( ch );
if ( found != char_map.end() )
std::cout << found->second;
else
std::cout << ch;
}
// usage
std::string str = "a\nbc";
for ( auto ch : str ) printChar ( ch );

Related

Inserting a character in a string

I have a string name2. I want to remove the capital characters in it and put lowercase instead.
Input:Car Output:car
Here is my loop code:-
if(isupper(name2.at(i))) {
string tem=to_string(tolower(name2.at(i)));
name2.erase(i,1);
name2.insert(i,tem);
}
i is just the loop variable.
However , here is my input vs output
Input:Sushant Output:115ushant
It is giving some sort of ASCII equivalent ouput , I suppose.
How do I fix this?
Here, to_string interprets the result of tolower as an integer. So what you see inserted in your string is the ASCII value of 's' (115). To fix this, there is no need to convert to string, just use characters directly:
char c = tolower(name.at(i));
name2.erase(i, 1);
name2.insert(i, c);
Easier and more efficient would be to just directly tolower() the character at the ith position:
name[i] = std::tolower(name[i]);
That being said, simpler would be to lowercase the whole string in one go, and take for granted that some characters will be lowercased unnecessarily:
std::transform(name.begin(), name.end(), name.begin(),
[](unsigned char c){ return std::tolower(c); }
);
See also: std::tolower.
It can be done simply using the range-based for loop.
Here is a demonstrative program.
#include <iostream>
#include <string>
#include <cstring>
int main()
{
std::string s;
std::cout << "Enter a word: ";
std::cin >> s;
for ( char &c : s )
{
if ( std::isupper( ( unsigned char )c ) )
{
c = tolower( c );
}
}
std::cout << s << '\n';
}
Its output might look like
Enter a word: Sushant
sushant
As for your if statement then at least this sub-statement
string tem=to_string(tolower(name2.at(i)));
does not make sense. For example
std::cout << std::to_string( 'A' ) << '\n';
can output
65
that corresponds to the ASCII value of the character 'A'.
That is the function std::to_string converts the promoted code of the character 'A' as an integer to a string.

newline from user input without pressing enter

First of all, I should mention that I found several closely related questions. Eg here and here. However, neither do I want to use printf nor do I want to use \n (because I know already that it does not work).
Is it possible for the user to enter a newline, probably an escape sequence, without hitting enter?
As an example:
#include <iostream>
#include <string>
int main () {
std::string a,b;
std::cin >> a;
std::cin >> b;
std::cout << a << "\n" << b;
}
Is it possible for a user to provide a single line of input
hello ??? world
such that the above prints
hello
world
?
You can do like this
std::string a, b;
std::cin >> a>>b;
std::cout << a << "\n" << b;
User can give input with space.
(I assume that you do not want spaces to delimit strings. For example,
Foo bar ??? baz qux
should be two lines.)
It is not possible that you configure the streams so that ??? is automatically converted to a newline character. For the user to input a newline character, they have to input a newline character, not anything else.
You have to parse it yourself.
Here's an example parser that treats ??? as delimiter:
void read_string(std::istream& is, std::string& dest)
{
std::string str = "";
for (char c; is.get(c);) {
switch (c) {
case '?':
if (is.get(c) && c == '?') {
if (is.get(c) && c == '?') {
dest = str;
return;
} else {
str += "??";
}
} else {
str += "?";
}
default:
str += c;
}
}
}
For example, the input
? is still one question mark????? is still two question marks???
is parsed as two lines:
? is still one question mark
?? is still two question marks
live demo

Implementation of word counting on non-text-based file as wc in Linux in C++

I am recently working on implementing word counting as wc in Linux in C++. I've read a lot of posts about how to implement this function, but I've still got a problem. When I use text-based file as the input, it'll return right word counts. Otherwise, it returns incorrect counts. So I am wondering if the logic of my code is wrong. I really can't figure this out. Please help me solve this problem.
What I expected is to get the exact number of word counts as wc does, for example:
wc -w filename
it'll return
wordCounts filename
I want to get the exactly same number of wordCounts as wc does and return as the result of function.
I've used .cpp and .txt files as input, and I got right word count.But when I use .out or other files it returns different result.
Here's my code:
int countWords()
{
std::ifstream myFile(pathToFile);
char buffer[1];
enum states {WHITESPACE,WORD};
int state = WHITESPACE;
int wordCount = 0;
if(myFile.is_open())
{
while(myFile.read(buffer,1))
{
if(!isspace(buffer[0]))
{
if (state == WHITESPACE )
{
wordCount++;
state = WORD;
}
}
else
{
state = WHITESPACE;
}
}
myFile.close();
}
else
{
throw std::runtime_error("File has not opend");
}
return wordCount;
}
It isn't obvious at all, but on a Mac (so it might not apply to Linux, but I expect it does), I can get the same result as wc by using setlocale(LC_ALL, ""): before calling your counting function.
The other problem is, as I noted in a comment, that isspace() takes an integer in the range 0..255 or EOF, but when you get signed values from plain char, you are indexing out of range and you get whatever you get (it is undefined behaviour). Without the setlocale() call, the character codes 9 (tab, '\t'), 10 (newline, '\n'), 11 (vertical tab, '\v'), 12 (formfeed, '\f'), 13 (carriage return, '\r') and 32 (space, ' ') are treated as 'space' by isspace(). When the setlocale() function is called on the Mac, the character code 160 (NBSP — non-breaking space) is also counted as a space, and that brings the calculation into sync with wc.
Here's a mildly modified version of your function which counts lines and characters as well as words. The function is revised to take a file name argument — you may do as you wish with yours, but you should avoid global variables whenever possible.
#include <cctype>
#include <clocale>
#include <fstream>
#include <iostream>
int countWords(const char *pathToFile)
{
std::ifstream myFile(pathToFile);
char buffer[1];
enum states { WHITESPACE, WORD };
int state = WHITESPACE;
int wordCount = 0;
int cc = 0;
int lc = 0;
if (myFile.is_open())
{
while (myFile.read(buffer, 1))
{
cc++;
if (buffer[0] == '\n')
lc++;
if (!isspace(static_cast<unsigned char>(buffer[0])))
{
if (state == WHITESPACE)
{
wordCount++;
state = WORD;
}
}
else
{
state = WHITESPACE;
}
}
myFile.close();
std::cerr << "cc = " << cc << ", lc = " << lc
<< ", wc = " << wordCount << "\n";
}
else
{
throw std::runtime_error("File has not opened");
}
return wordCount;
}
int main()
{
setlocale(LC_ALL, "");
std::cout << countWords("/dev/stdin") << "\n";
}
When compiled (from wc79.cpp into wc79), and run on itself, I get the output:
$ ./wc79 < wc79
cc = 13456, lc = 6, wc = 118
118
$ wc wc79
6 118 13456 wc79
$
The two are now in agreement.

Replace the character with two other

I have a std::string, how can i replace : character with %%?
std::replace( s.begin(), s.end(), ':', '%%' );
this code above doesn't work:
error no instance matches the arguement list
Thanks!
Unfortunately, there is no way to replace all : characters in one shot. But you can do it in a loop, like this:
string s = "quick:brown:fox:jumps:over:the:lazy:dog";
int i = 0;
for (;;) {
i = s.find(":", i);
if (i == string::npos) {
break;
}
s.replace(i, 1, "%%");
}
cout << s << endl;
This program prints
quick%%brown%%fox%%jumps%%over%%the%%lazy%%dog
If you need to replace only the first colon, then use the body of the loop by itself, without the loop around it.

Convert string with explicit escape sequence into relative character

I need a function to convert "explicit" escape sequences into the relative non-printable character.
Es:
char str[] = "\\n";
cout << "Line1" << convert_esc(str) << "Line2" << endl:
would give this output:
Line1
Line2
Is there any function that does this?
I think that you must write such function yourself since escape characters is a compile-time feature, i.e. when you write "\n" the compiler would replace the \n sequence with the eol character. The resulting string is of length 1 (excluding the terminating zero character).
In your case a string "\\n" is of length 2 (again excluding terminating zero) and contains \ and n.
You need to scan your string and when encountering \ check the following char. if it is one of the legal escapes, you should replace both of them with the corresponding character, otherwise skip or leave them both as is.
( http://ideone.com/BvcDE ):
string unescape(const string& s)
{
string res;
string::const_iterator it = s.begin();
while (it != s.end())
{
char c = *it++;
if (c == '\\' && it != s.end())
{
switch (*it++) {
case '\\': c = '\\'; break;
case 'n': c = '\n'; break;
case 't': c = '\t'; break;
// all other escapes
default:
// invalid escape sequence - skip it. alternatively you can copy it as is, throw an exception...
continue;
}
}
res += c;
}
return res;
}
You can do that fairly easy, using the boost string algorithm library. For example:
#include <string>
#include <iostream>
#include <boost/algorithm/string.hpp>
void escape(std::string& str)
{
boost::replace_all(str, "\\\\", "\\");
boost::replace_all(str, "\\t", "\t");
boost::replace_all(str, "\\n", "\n");
// ... add others here ...
}
int main()
{
std::string str = "This\\tis\\n \\\\a test\\n123";
std::cout << str << std::endl << std::endl;
escape(str);
std::cout << str << std::endl;
return 0;
}
This is surely not the most efficient way to do this (because it iterates the string multiple times), but it is compact and easy to understand.
Update:
As ybungalobill has pointed out, this implementation will be wrong, whenever a replacement string produces a character sequence, that a later replacement is searching for or when a replacement removes/modifies a character sequence, that should have been replaced.
An example for the first case is "\\\\n" -> "\\n" -> "\n". When you put the "\\\\" -> "\\" replacement last (which seems to be the solution at a first glance), you get an example for the latter case "\\\\n" -> "\\\n". Obviously there is no simple solution to this problem, which makes this technique only feasible for very simple escape sequences.
If you need a generic (and more efficient) solution, you should implement a state machine that iterates the string, as proposed by davka.
I'm sure that there is, written by someone, but it's so trivial that I doubt it's been specifically published anywhere.
Just recreate it yourself from the various "find"/"replace"-esque algorithms in the standard library.
Have you considered using printf? (or one of its relatives)
Here's a cute way to do it on Unixy platforms.
It calls the operating system's echo command to make the conversion.
string convert_escapes( string input )
{
string buffer(input.size()+1,0);
string cmd = "/usr/bin/env echo -ne \""+input+"\"";
FILE * f = popen(cmd.c_str(),"r"); assert(f);
buffer.resize(fread(&buffer[0],1,buffer.size()-1,f));
fclose(f);
return buffer;
}