I am wondering how I can check if the getline function, let's say on string buffer and ifstream input: getline(input, buffer), stores a blank line?
So lets say I had:
Hello
How are you
So how could I identify based on the string buffer if I am dealing with a newline? I need this for formatting checking in a much more complicated file. Thanks.
After you get the string buffer, you can check:
if (get_trimmed_string(buffer).length == 0)
{
// this line is a blank line, or contains only spaces/tabs
}
And the function to trim spaces or tabs can be something like:
// delete spaces/tabs in head and tail of str
string get_trimmed_string(string str)
{
int s=str.find_first_not_of(" \t");
int e=str.find_last_not_of(" \t");
// if do find real content
if (s!=-1 && e!=-1)
return str.substr(s, e-s+1);
return "";
}
Add a function to check whether it has only white space characters.
#include <iostream>
#include <string>
bool isBlankLine(char const* line)
{
for ( char const* cp = line; *cp; ++cp )
{
if ( !isspace(*cp) ) return false;
}
return true;
}
bool isBlankLine(std::string const& line)
{
return isBlankLine(line.c_str());
}
int main()
{
std::string s1 = "Hello";
std::string s2 = " ";
std::string s3 = "How are you";
std::cout << "Is s1 blank? " << isBlankLine(s1) << std::endl;
std::cout << "Is s2 blank? " << isBlankLine(s2) << std::endl;
std::cout << "Is s3 blank? " << isBlankLine(s3) << std::endl;
return 0;
}
Here's the output:
Is s1 blank? 0
Is s2 blank? 1
Is s3 blank? 0
Related
I have a string in C++ that looks like this:
string word = "substring"
I want to read through the word string using a for loop, and each time an s is found, print out "S found!". The end result should be:
S found!
S found!
Maybe you could utilize toupper:
#include <iostream>
#include <string>
void FindCharInString(const std::string &str, const char &search_ch) {
const char search_ch_upper = toupper(search_ch, std::locale());
for (const char &ch : str) {
if (toupper(ch, std::locale()) == search_ch_upper) {
std::cout << search_ch_upper << " found!\n";
}
}
}
int main() {
std::string word = "substring";
std::cout << word << '\n';
FindCharInString(word, 's');
return 0;
}
Output:
substring
S found!
S found!
Trying to convert my following go code question
How to create a 0x appended hex string from a hex string for each byte of hex characters in golang?
to C++ - but completely lost.
#include <iostream>
#include <string>
using namespace std;
// Function to append 0x
void appendX(string str)
{
// Appends 1 occurrences of "X" to str
str.append(1, 'X');
cout << "Modified append() : ";
cout << str;
}
int main()
{
string str("01234567891011121314151617181920");
cout << "String : " << str << endl;
appendX(str);
return 0;
}
Your function appendX() is going to append only one 'X' at the end of your input string, as your comment also says.
But if you are trying to append "0x" after every hex byte within your string, (as asked in the GO language question you mentioned), you should be appending "0x" after every 2 characters in your input string. Try below:
void appendX(String str)
{
String outstr;
for(int i=0;i<str.size();i=i+2)
{
outstr.append("0x");
outstr.append(str,i,2);
}
cout << "Modified append() : ";
cout << outstr;
}
Simplest/Understandable way is to iterate over a string and add the desirable amount of characters to a result string.
std::string insertStringInto(const std::string& s, const int interval, const std::string& sep_str)
{
std::string result_str;
auto chars_count_until_sep = interval;
for (auto ch: s)
{
if (chars_count_until_sep == 0)
{
result_str += sep_str;
chars_count_until_sep = interval;
}
result_str += ch;
--chars_count_until_sep;
}
return result_str;
}
int main()
{
std::string str("01234567891011121314151617181920");
std::cout << "String : " << insertStringInto(str,2,", 0x") << std::endl;
return 0;
}
Using the Ranges V3 library (in the future all these functions should be available in the C++ standard library):
std::string insertStringInto(const std::string& in_string, const int interval, const std::string& sep_str)
{
using namespace ranges::views;
auto concat_to_str = [](auto grp) { // auxilllary function to concat single characters into a string
return ranges::accumulate(grp, std::string {});
};
auto r = in_string // Use the characters from the input string parameter
| chunk(interval) // Split string up into interval count of characters
| transform(concat_to_str) // combine characters from chunks into strings
| intersperse(sep_str); // intersperse between the chunks the separator text
return concat_to_str(r); // concat all the strings into 1 string
}
int main()
{
std::string str("01234567891011121314151617181920");
std::cout << "String : " << insertStringInto(str, 2, ", 0x") << std::endl;
return 0;
}
I have a vector of strings in C++, named lines.
This line
std::cout << "First line: >" << lines[0] << "<" << std::endl;
prints ">irst line: >string_here" instead of "First line: >string_here<".
Why does cout start printing at the start of the current line after the string, and how can I resolve it? I also tried to flush after every cout but result was the same.
This is a full code that ilustrates my problem, BEFORE it was solved:
#include <iostream>
#include <vector>
#include <string.h>
std::vector<std::string> parse(char *buffer, const char *delimiter) {
std::string buff(buffer);
size_t pos = 0;
std::string part;
std::vector<std::string> parts;
while ((pos = buff.find(delimiter)) != std::string::npos) {
part = buff.substr(0, pos);
parts.push_back(part);
buff.erase(0, pos + 1);
}
parts.push_back(buff);
return parts;
}
int main() {
char *s;
s = strdup("Many lines\r\nOf text");
std::cout << s << std::endl; // this should print the string how it is
std::vector<std::string> lines;
lines = parse(s, "\n"); // parsing the string, after "\n" delimiter
// that was the problem, I should have parsed after "\r\n"
std::cout << "First line: >"<< lines[0] << "<" << std::endl; // output
}
It's impossible to be sure without the full content of lines[0], but my (educated) guess would be that lines[0] ends with \r, the carriage return character, so everything printed after lines[0] is printed a the beginning of the line.
Last week I got an homework to write a function: the function gets a string and a char value and should divide the string in two parts, before and after the first occurrence of the existing char.
The code worked but my teacher told me to do it again, because it is not well written code. But I don't understand how to make it better. I understand so far that defining two strings with white spaces is not good, but i get out of bounds exceptions otherwise. Since the string input changes, the string size changes everytime.
#include <iostream>
#include <string>
using namespace std;
void divide(char search, string text, string& first_part, string& sec_part)
{
bool firstc = true;
int counter = 0;
for (int i = 0; i < text.size(); i++) {
if (text.at(i) != search && firstc) {
first_part.at(i) = text.at(i);
}
else if (text.at(i) == search&& firstc == true) {
firstc = false;
sec_part.at(counter) = text.at(i);
}
else {
sec_part.at(counter) = text.at(i);
counter++;
}
}
}
int main() {
string text;
string part1=" ";
string part2=" ";
char search_char;
cout << "Please enter text? ";
getline(cin, text);
cout << "Please enter a char: ? ";
cin >> search_char;
divide(search_char,text,aprt1,part2);
cout << "First string: " << part1 <<endl;
cout << "Second string: " << part2 << endl;
system("PAUSE");
return 0;
}
I would suggest you, learn to use c++ standard functions. there are plenty utility function that can help you in programming.
void divide(const std::string& text, char search, std::string& first_part, std::string& sec_part)
{
std::string::const_iterator pos = std::find(text.begin(), text.end(), search);
first_part.append(text, 0, pos - text.begin());
sec_part.append(text, pos - text.begin());
}
int main()
{
std::string text = "thisisfirst";
char search = 'f';
std::string first;
std::string second;
divide(text, search, first, second);
}
Here I used std::find that you can read about it from here and also Iterators.
You have some other mistakes. you are passing your text by value that will do a copy every time you call your function. pass it by reference but qualify it with const that will indicate it is an input parameter not an output.
Why is your teacher right ?
The fact that you need to initialize your destination strings with empty space is terrible:
If the input string is longer, you'll get out of bound errors.
If it's shorter, you got wrong answer, because in IT and programming, "It works " is not the same as "It works".
In addition, your code does not fit the specifications. It should work all the time, independently of the current value which is stored in your output strings.
Alternative 1: your code but working
Just clear the destination strings at the beginning. Then iterate as you did, but use += or push_back() to add chars at the end of the string.
void divide(char search, string text, string& first_part, string& sec_part)
{
bool firstc = true;
first_part.clear(); // make destinations strings empty
sec_part.clear();
for (int i = 0; i < text.size(); i++) {
char c = text.at(i);
if (firstc && c != search) {
first_part += c;
}
else if (firstc && c == search) {
firstc = false;
sec_part += c;
}
else {
sec_part += c;
}
}
}
I used a temporary c instead of text.at(i) or text\[i\], in order to avoid multiple indexing But this is not really required: nowadays, optimizing compilers should produce equivalent code, whatever variant you use here.
Alternative 2: use string member functions
This alternative uses the find() function, and then constructs a string from the start until that position, and another from that position. There is a special case when the character was not found.
void divide(char search, string text, string& first_part, string& sec_part)
{
auto pos = text.find(search);
first_part = string(text, 0, pos);
if (pos== string::npos)
sec_part.clear();
else sec_part = string(text, pos, string::npos);
}
As you understand yourself these declarations
string part1=" ";
string part2=" ";
do not make sense because the entered string in the object text can essentially exceed the both initialized strings. In this case using the string method at can result in throwing an exception or the strings will have trailing spaces.
From the description of the assignment it is not clear whether the searched character should be included in one of the strings. You suppose that the character should be included in the second string.
Take into account that the parameter text should be declared as a constant reference.
Also instead of using loops it is better to use methods of the class std::string such as for example find.
The function can look the following way
#include <iostream>
#include <string>
void divide(const std::string &text, char search, std::string &first_part, std::string &sec_part)
{
std::string::size_type pos = text.find(search);
first_part = text.substr(0, pos);
if (pos == std::string::npos)
{
sec_part.clear();
}
else
{
sec_part = text.substr(pos);
}
}
int main()
{
std::string text("Hello World");
std::string first_part;
std::string sec_part;
divide(text, ' ', first_part, sec_part);
std::cout << "\"" << text << "\"\n";
std::cout << "\"" << first_part << "\"\n";
std::cout << "\"" << sec_part << "\"\n";
}
The program output is
"Hello World"
"Hello"
" World"
As you can see the separating character is included in the second string though I think that maybe it would be better to exclude it from the both strings.
An alternative and in my opinion more clear approach can look the following way
#include <iostream>
#include <string>
#include <utility>
std::pair<std::string, std::string> divide(const std::string &s, char c)
{
std::string::size_type pos = s.find(c);
return { s.substr(0, pos), pos == std::string::npos ? "" : s.substr(pos) };
}
int main()
{
std::string text("Hello World");
auto p = divide(text, ' ');
std::cout << "\"" << text << "\"\n";
std::cout << "\"" << p.first << "\"\n";
std::cout << "\"" << p.second << "\"\n";
}
Your code will only work as long the character is found within part1.length(). You need something similar to this:
void string_split_once(const char s, const string & text, string & first, string & second) {
first.clear();
second.clear();
std::size_t pos = str.find(s);
if (pos != string::npos) {
first = text.substr(0, pos);
second = text.substr(pos);
}
}
The biggest problem I see is that you are using at where you should be using push_back. See std::basic_string::push_back. at is designed to access an existing character to read or modify it. push_back appends a new character to the string.
divide could look like this :
void divide(char search, string text, string& first_part,
string& sec_part)
{
bool firstc = true;
for (int i = 0; i < text.size(); i++) {
if (text.at(i) != search && firstc) {
first_part.push_back(text.at(i));
}
else if (text.at(i) == search&& firstc == true) {
firstc = false;
sec_part.push_back(text.at(i));
}
else {
sec_part.push_back(text.at(i));
}
}
}
Since you aren't handling exceptions, consider using text[i] rather than text.at(i).
I have a string with large content. I have to separate out content of string before the first newline character and after the newline character.
string content is as follows:
std::string = "exption is theo from my fimnct!
mt nsamre id kjsdf dskfk djfhj
/vonsfs/sdvfs/sdvjisd/dd.so
dfjg dfk dflkkm sdfk "
from above i have to get the content of first line upto the newline charcter in another string and keep the other content remain unchanged. The characters in first line are not fixed. it is variable sting.
What about string::substr and string::find:
#include <iostream>
int main()
{
std::string s = "foo\nbar";
std::cout << "first line: " << s.substr(0, s.find('\n')) << "\n";
}
You would do this like this:
std::string first, second, all = "...";
size_t pos = all.find('\n')
if(pos != std::string::npos)
{
first = all.substr(0, pos);
second = all.substr(pos+1);
}
Try std::algorithms:
int main (void)
{
std::string input(
"exption is theo from my fimnct!\n"
"mt nsamre id kjsdf dskfk djfhj\n"
"/vonsfs/sdvfs/sdvjisd/dd.so\n"
"dfjg dfk dflkkm sdfk"
);
std::string first_line(input.begin(), std::find(input.begin(), input.end(), '\n'));
std::string rest_lines(std::find(input.begin(), input.end(), '\n'), input.end());
std::cout << first_line << std::endl;
std::cout << "---" << std::endl;
std::cout << rest_lines << std::endl;
return 0;
}
This prints out
exption is theo from my fimnct!
---
mt nsamre id kjsdf dskfk djfhj
/vonsfs/sdvfs/sdvjisd/dd.so
dfjg dfk dflkkm sdf
std::string::substr and std::string::find_first_of