why does the first 2 chars get skipped when executing? C++ - c++

while(!Info.eof()) {
std::getline(Info, line,'\r');
char a[line.length()];
char things[]= ":.\n\0";
for(int i=0;i<sizeof(a); i++) {
a[i]= line[i];
}
ptr = strtok(a, things);
ptr = strtok(nullptr,things);
while (ptr!= nullptr) {
ptr = strtok(nullptr,things);
std::cout << ptr << std::endl;
}
Info is the ifstream input file. line is a string. When I cout << line it displays everything no problem, the problem is i need to take away everything other than the needed strings and int, which I have done but the first 2 lines don't show. When I first executed this it displayed everything, yesterday it skipped the first line and today the first two lines. I guess this has something to do with memory or something unseen, I need help please, thanks.

Well, for starters, you are calling strtok() 3 times before your 1st cout print. So you are skipping the first few substrings.
Also, you have mistakes in your code, namely using eof() in a loop, and using non-standard variant-length arrays.
Try something more like this instead:
while (std::getline(Info, line))
{
const char *things = ":.";
ptr = strtok(line.data()/* or: &line[0]*/, things);
while (ptr)
{
std::cout << ptr << std::endl;
ptr = strtok(nullptr, things);
}
...
}
Or, as a for loop:
while (std::getline(Info, line))
{
const char *things = ":.";
for(ptr = strtok(line.data()/* or: &line[0]*/, things);
ptr != nullptr;
ptr = strtok(nullptr, things))
{
std::cout << ptr << std::endl;
}
...
}
Although, you really shouldn't be using strtok() in C++ at all. std::string has its own find_first_of() and substr() methods that you can use instead, eg:
while (std::getline(Info, line))
{
std::string::size_type start = 0, end;
while (start < line.size())
{
end = line.find_first_of(":.", start);
if (end == std::string::npos)
{
std::cout << line.substr(start) << std::endl;
break;
}
std::cout << line.substr(start, end-start) << std::endl;
start = end + 1;
}
...
}

One thing you're missing -- C-style strings are terminated with a zero on the end. You're not doing that.
Secondly, you did two strtoks before your while loop, which is why you're losing a few things.

Related

How to use commas to split chars in a loop?

I'm writing a program in c++ and I'm trying to separate letters like this: "A,B,C"
But it comes out like this, and I don't know why: ",A,B,C".
Help?
My code is below:
#include <iostream>
#include <ctype.h>
using namespace std;
int main()
{
char startChar='Z';
char stopChar='A';
while (startChar>stopChar)
{
cin >> startChar;
startChar = toupper(startChar);
cin >> stopChar;
stopChar=toupper(stopChar);
}
for (char chLoop=startChar; chLoop<=stopChar; chLoop++)
{
if (stopChar > startChar)
cout << ",";
cout <<chLoop;
}
}
thanks!
When stopChar is C and startChar is A, this condition will be true and therefore a , will be printed in every iteration of the loop (including the first):
if (stopChar > startChar)
cout << ",";
You can fix it by changing it to:
if (chLoop != startChar)
std::cout << ',';
That is, only if chLoop is not startChar, print a ,.
Another option that doesn't require an if at all:
std::cout << startChar; // print the first char before the loop
for (char chLoop = startChar + 1; chLoop <= stopChar; chLoop++) {
std::cout << ',' << chLoop; // now print the , unconditionally
}
Ted Lyngmo’s answer is correct. I just wanted to add some useful information about generating sequences with joiners (or separators).
The usual idiom in C++ works by printing your first element, then printing the remaining elements with the joiner prepended. For example:
char first = 'A';
char last = 'Z' + 1; // in C++, last/end is always _one past_
std::cout << first;
while (++first != last)
{
std::cout << "," << first;
}
In general, you also want to check to make sure you have at least one element before you start:
char first = 'A';
char last = 'Z' + 1; // in C++, last/end is always _one past_
if (first != last) // make sure there is at least one item to print
{
std::cout << first;
while (++first != last)
{
std::cout << "," << first;
}
}
This works for any sequence you can get iterators for as well:
std::vector xs = { 2, 3, 5, 7, 11 };
auto first = xs.begin();
auto last = xs.end();
if (first != last)
{
std::cout << *first;
while (++first != last)
{
std::cout << "," << *first;
}
}
Everything is a variation of this. Here’s one some people like and others hate, but typically gets good performance on std::string and std::ostream:
if (first != last)
std::accumulate( std::next(first), last, *first, [&delimiter]( auto a, auto b )
{
return a.append( delimiter ).append( b );
} );
C++ can’t leave things alone, though, and programmers want smaller, simpler, prettier code. There’s an entire thread about this operation, and Kikuko’s answer gives you a C++20 ranges_v3 solution.

C++ String to byte

so i have a string like this:std::string MyString = "\\xce\\xc6";
where when i print it like this:std::cout << MyString.c_str()[0] << std::endl;
as output i get:\
and i want it to be like this:std::string MyDesiredString = "\xce\xc6";
so when i do:
std::cout << MyDesiredString.c_str()[0] << std::endl;
// OUTPUT: \xce (the whole byte)
so basically i want to identify the string(that represents bytes) and convert it to an array of real bytes
i came up with a function like this:
// this is a pseudo code i'm sure it has a lot of bugs and may not even work
// just for example for what i think
char str_to_bytes(const char* MyStr) { // MyStr length == 4 (\\xc6)
std::map<char*, char> MyMap = { {"\\xce", '\xce'}, {"\\xc6", 'xc6'} } // and so on
return MyMap[MyStr]
}
//if the provided char* is "\\xc6" it should return the char '\xc6'
but i believe there must be a better way to do it.
as much as i have searched i haven't found anything useful
thanks in advance
Try something like this:
std::string teststr = "\\xce\\xc6";
std::string delimiter = "\\x";
size_t pos = 0;
std::string token;
std::string res;
while ((pos = teststr.find(delimiter)) != std::string::npos) {
token = teststr.substr(pos + delimiter.length(), 2);
res.push_back((char)stol(token, nullptr, 16));
std::cout << stol(token, nullptr, 16) << std::endl;
teststr.erase(pos, pos + delimiter.length() + 2);
}
std::cout << res << std::endl;
Take your string, split it up by the literals indicating a hex. value is provided (\x) and then parse the two hex. characters with the stol function as Igor Tandetnik mentioned. You can then of course add those byte values to a string.

C++: Separating a char* with '\t' delimiter

I've been fighting this problem for a while now, and can't seem to find a simple solution that doesn't involve parsing a char * by hand. I need to split my char* variable by '\t', and I've tried the following ways:
Method 1:
char *splitentry;
std::string ss;
splitentry = strtok(read_msg_.data(), "\\t");
while(splitentry != NULL)
{
std::cout << splitentry << std::endl;
splitentry = strtok(NULL, "\\t");
}
Using the input '\tthis\tis\ta\ttest'
results in this output:
his
is
a
es
Method 2:
std::string s(read_msg_.data());
boost::algorithm::split(strs, s, boost::is_any_of("\\t");
for (int i = 0; i < strs.size(); i++)
std::cout << strs.at(i) << std::endl;
Which creates an identical output.
I've tried using boost::split_regex and used "\\t" as my regex value, but nothing gets split. Will I have to split it on my own, or am I going about this incorrectly?
I would try to make things a little simpler by sticking to std:: functions. (p.s. you never use this: std::string ss;)
Why not do something like this?
Method 1: std::istringstream
std::istringstream ss(read_msg_.data());
std::string line;
while( std::getline(ss,line,ss.widen('\t')) )
std::cout << line << std::endl;
Method 2: std::string::substr (my preferred method as it is lighter)
std::string data(read_msg_.data());
std::size_t SPLITSTART(0); // signifies the start of the cell
std::size_t SPLITEND(0); // signifies the end of the cell
while( SPLITEND != std::string::npos ) {
SPLITEND = data.find('\t',SPLITSTART);
// SPLITEND-SPLITSTART signifies the size of the string
std::cout << data.substr(SPLITSTART,SPLITEND-SPLITSTART) << std::endl;
SPLITSTART = SPLITEND+1;
}

Allocation of data through a list of pointers in C++

I'm trying to read the data of several objects from a file. The reading itself works fine, but I'm having trouble with writing the data into a std::list<MyObject*>. I tried a couple of things but it always ends with the application crashing after printing some stuff, which I think is random memory content. Below you can find the current version. I also tried Iterators but that didn't work either.
Here's what happens in the calling method:
PAProject proj2 = PAProject();
proj2.projectName = "myfirstOne";
PaFigureLoader::loadFigures(&proj2);
std::list<PAFigure*>::iterator figIterator;
for(figIterator = proj2.figures.begin();
figIterator != (proj2.figures.end());
figIterator++) {
PAFigure* fig = *figIterator;
if(fig->firstname.empty()) {
std::cout << "Nothing to see here\n";
break;
} else {
std::cout << fig->firstname << "\n";
}
}
The list is std::list<PAFigure*> figures
Method causing all the trouble:
static void loadFigures(PAProject *project)
{
//open input stream
fs::ifstream ifstream(filename);
std::string input;
ifstream >> input;
PAFigure * fig;
//keep a string for all the splitting:
std::string result;
//define regexs
std::regex reg1 ("(<firstname>)([a-zA-Z0-9]*)(</firstname>)");
std::regex reg2 ("(<lastname>)([a-zA-Z0-9]*)(</lastname>)");
//iterate through file to find all figures
while(input.compare("</allfigures>") != 0) {
//do the figure-loading stuff
if(input.compare("<figure>")==0) {
PAFigure newFigure = PAFigure();
project->figures.push_front(&newFigure);
fig = &newFigure;
}
//find contents
if(input.find("<firstname>")!= std::string::npos) {
std::regex_replace (std::back_inserter(result), input.begin(), input.end(), reg1, "$2");
fig->firstname = result;
result.erase();
std::cout << fig->firstname << " is firstname\n";
}
if(input.find("<lastname>")!= std::string::npos) {
std::regex_replace (std::back_inserter(result), input.begin(), input.end(), reg2, "$2");
fig->lastname = result;
result.erase();
}
//read next line
ifstream >> input;
}
PAFigure * figtest = project->figures.back();
std::cout << figtest->firstname << " last element\n";
figtest = project->figures.front();
std::cout << figtest->firstname << " first element\n";
}
Here's the output:
died
Anna is firstname
died
Dorian is firstname
Dorian last element
Dorian first element
Dorian died
Anna died
I added
PAFigure::~PAFigure()
{
std::cout << this->firstname << " died\n";
}
because I had that weird feeling that my elements were just gone, and apparently the PAFigure newFigure = PAFigure() does infact never get a firstname.
I admit that my coding experience in C++ and especially with pointer/references is very... basic. I have no idea how to solve this, not even talking about solving it in an elegant way.
Use pointer rather than reference.
Here is what's wrong:
PAFigure newFigure = PAFigure();
You should use a pointer to push, rather than reference.
PAFigure *newFigure = new PAFigure();
project->figures.push_front(newFigure);
// and create another object too.
PAFigure *fig = new PAFigure();

how to find number of elements in an array of strings in c++?

i have an array of string.
std::string str[10] = {"one","two"}
How to find how many strings are present inside the str[] array?? Is there any standard function?
There are ten strings in there despite the fact that you have only initialised two of them:
#include <iostream>
int main (void) {
std::string str[10] = {"one","two"};
std::cout << sizeof(str)/sizeof(*str) << std::endl;
std::cout << str[0] << std::endl;
std::cout << str[1] << std::endl;
std::cout << str[2] << std::endl;
std::cout << "===" << std::endl;
return 0;
}
The output is:
10
one
two
===
If you want to count the non-empty strings:
#include <iostream>
int main (void) {
std::string str[10] = {"one","two"};
size_t count = 0;
for (size_t i = 0; i < sizeof(str)/sizeof(*str); i++)
if (str[i] != "")
count++;
std::cout << count << std::endl;
return 0;
}
This outputs 2 as expected.
If you want to count all elements sizeof technique will work as others pointed out.
If you want to count all non-empty strings, this is one possible way by using the standard count_if function.
bool IsNotEmpty( const std::string& str )
{
return !str.empty();
}
int main ()
{
std::string str[10] = {"one","two"};
int result = std::count_if(str, &str[10], IsNotEmpty);
cout << result << endl; // it will print "2"
return 0;
}
I don't know that I would use an array of std::strings. If you're already using the STL, why not consider a vector or list? At least that way you could just figure it out with std::vector::size() instead of working ugly sizeof magic. Also, that sizeof magic won't work if the array is stored on the heap rather than the stack.
Just do this:
std::vector<std::string> strings(10);
strings[0] = "one";
strings[1] = "two";
std::cout << "Length = " << strings.size() << std::endl;
You can always use countof macro to get the number of elements, but again, the memory was allocated for 10 elements and thats the count that you'll get.
The ideal way to do this is
std::string str[] = {"one","two"}
int num_of_elements = sizeof( str ) / sizeof( str[ 0 ] );
Since you know the size.
You could do a binary search for not null/empty.
str[9] is empty
str[5] is empty
str[3] is not empty
str[4] is empty
You have 4 items.
I don't really feel like implementing the code, but this would be quite quick.
Simply use this function for 1D string array:
template<typename String, uint SIZE> // String can be 'string' or 'const string'
unsigned int NoOfStrings (String (&arr)[SIZE])
{
unsigned int count = 0;
while(count < SIZE && arr[count] != "")
count ++;
return count;
}
Usage:
std::string s1 = {"abc", "def" };
int i = NoOfStrings(s1); // i = 2
I am just wondering if we can write a template meta program for this ! (since everything is known at compile time)
A simple way to do this is to use the empty() member function of std::string like this e.g.:
size_t stringArrSize(std::string *stringArray) {
size_t num = 0;
while (stringArray->empty() != true) {
++num;
stringArray++;
}
return num;
}