c++/c data structures for storing strings separated by blanks - c++

What is the best data structures for storing
strings separated by blanks
the variable peers contains a list of strings separated by blanks
Each such a string has the form host:port, where host is a host name (DNS name or IP in dotted decimal notation2) and port is a positive number.
in the list i may have something like
127.0.0.1:8080 127.3.0.1:9080 127.0.0.1:3000 127.3.0.1:9080
what's the best way to deal with these kind of data,
any code example for
create this variable "peers"

#include <sstream>
#include <vector>
#include <string>
std::stringstream iss { str };
std::vector<std::string> peers;
std::string tmp;
while (iss >> tmp)
peers.push_back(tmp);

Assuming that there are only correct IP addresses and port numbers in the individual parts, they are no longer than 21 characters and the data could therefore be saved as an array of (fixed-length) strings:
char peers[][21] = {"127.0.0.1:8080", "127.3.0.1:9080", "127.0.0.1:3000", "127.3.0.1:9080"};
The advantage of this variant would be that the entries can be accessed directly via an array index:
for (int i=0; i<4; i++)
printf("%s\n", peers[i]);

What is the best data structures for storing strings separated by
blanks
It all depends how you are going to access this data. Are you going call it by some sort of ID? If yes, you might use map for sorted data or unordered map without sorting it. Are you going to access elements using id? Then maybe vector will suffice. Is number of string known before you start? Think about using array. About access, you can keep all the data inside one string and simply know which blank is which IP. You can also parse strings and save them into array/vector. If you want to access data not by ID but by it's value (while making sure it's inside container) make key it's value and use set. If you want to keep these inside container, don't access by id, you don't know how many items you will hold, might use list or forward_list. It's all up to how data will be processed.

Related

How to store a table with varying number of columns and rows? C++

I'm very confused with the new programming assignment we got in class a few days ago. It asks us to read info from a file which contains an unknown number of rows and columns and then sort the data. My question is how do I do that?
My reasoning was that if I knew the number of columns, I would just create an array of structures and then create a new structure for each row. But since the number of columns is also unknown, I don't know how to approach this.
Also, we only allowed to use <iostream> <fstream>, <cctype> and <vector> libraries.
You could use a
std::vector<std::vector<WhateverTypeYouWantToStore>>
Use std::vector. You can create a 2D vector like this:
vector<vector<string> > table;
And then read the lines from a file, and put the data into a one dimensional vector (vector<string> line). And then, You can push_back the line vector into the table, like this:
table.push_back(line);
You can see more information about vector on this page: cplusplus.com
I hope you must know what format of data that you are going to read from text file's row and column. First to understand, you will read first row, then second row and so on. If you do not know type of data, then believe all of it as string of characters. So, you can assume wherever you fine null char '\0' then you are finding data for first row, so go on read character by character look for next '\0'. Then wherever you find '\n' that will be last point of first row and you just discovered last column. After '\n' you will start reading 2nd row and so on. With this you can determine how many rows and columns are there. You keep on reading text file until you reach EOF.
See the attached image.
Text File Format
Also, define a pointer to character type and use realloc to assign memory to it. With realloc() you can grow it, as you find more data. Please go through realloc() manual for reference.

Send and receive <vector> data through network

I have a vector defined as follows:
std::vector<char*> rooms;
const int rows = 100;
const int columns = 10;
I need to send this vector as string buffer. And then receive and turn the string into another vector with same size.
This is how I send a string:
int SendData(std::string data)
{
s.SendLine(data);
return 0;
}
I just can't imagine a solution for that.
Since you already know how to send a string, and the vector is just a series of strings, then the most straightforward way to send the vector would be to simply send the strings, one after another.
Of course the devil is in the details: How will the receiver know how many strings to expect? And how will the receiver know where one string ends and the next string begins?
Answers: Before sending the first string, send some initial data indicating how many strings you intend to send. (If you want to keep things simple, this could be an additional string like "100" that the receiver will know to use as a hint; or you could send an integer as one or two or four bytes of binary data, if you prefer to do it that way [be sure to consider endianness issues if you send it as more than one byte])
As for the receiver knowing where one string ends and the next one begins, one way is to make sure to send a NUL/0 byte at the end of each string; then the receiver can look for that byte to know where each string ends. Another way is to send the number of bytes in the string before sending the string itself, and then the receiver can be sure to read in that many bytes for the string.
You say you know how to send a std::string, and that you want to send the vector as a single string. So all you need is to transform a vector of strings in a big string.
You can try to reinvent a way, or just use (or mimic) what others have already imagined :
Comma Separated Values
JSON
XML
All have their pros and cons. And the tricky part in all is the escaping of chars that are "special".
I need to send this vector as string buffer. And then receive and turn the string into another vector with same size.
This sounds that you solution to build a string from the data is a solution and your question goes to the point, where you want YOUR solution comes working. But there is a better way to transfer any kind of data without using manual coded string gymnastics.
If you only want to sent any kind of data like skalars, containers and custom build class instances over a network, you should think of using a library which do this for you without reinventing the wheel again and again. If this is your case search for serializer and you will get a ready to use solution for all kind of data!
Have a look at http://www.boost.org/doc/libs/1_58_0/libs/serialization/doc/index.html
or https://developers.google.com/protocol-buffers/

How to organize a lot of options into a single variable and then use a call to that variable

I am making a simple program where if you type 'north' it will subtract a number from your stamina. I got that too work, but there are a lot of possible input to represent 'north' you can have 'no', 'n','NORTH','NoRtH' as you can see this gets tedious after a while, if I have to create an if statement for each and every single possible variation of the word north, and not to mention the other directions I want to use, it won't look nice
I was wondering is there a way to be able to store all those possible variations of that word into something, and when when I make an if statement, it directs it to that storage unit to compare with all possible variations... because I just know that if i make 40+ if and else if statements to compare the users input with all those variations, the code will get ugly and fast.
It sounds like you want to see if a string is contained within an arbitrary set of strings. The C++ standard libraries have functionality for this.
I would use a std::set to contain a list of valid terms, like so:
std::set<std::string> north_terms_set;
north_terms_set.insert("n");
north_terms_set.insert("north");
and then check to see if a given input belongs to the set as follows:
//Convert input to lowercase
std::string input_str = "NoRtH";
std::transform(input_str.begin(), input_str.end(), input_str.begin(), ::tolower);
//compare lowercase version of input to the set of valid terms.
if (north_terms_set.find(input_str) != north_terms_set.end()) {
//User has typed something like 'north', subtract from stamina, etc.
}
While the method suggested by 111111 is simpler, this methods enables you to limit which variants are considered valid and also lets you allow alternatives such as 'north', 'up', 'top', etc.
If you want to match the following to north:
n, no, nor, nort, north
including their capitalised counter parts you can do this if you use boost string algorithms, you can obviously write your own to_lower and starts_with if you can't use boost for some reason.
std::cin >> input;
boost::to_lower(input);
if(boost::starts_with("north", input)) {
//match
}

How to use environments for lookups

My question builds upon the topic of matching a string against multiple patterns. One solution discussed here is to use sapply(keywords, grepl, strings, ignore.case=TRUE) which yields a two-dimensional matrix.
However, I run into significant speed issues, when applying this approach to 5K+ keywords and 60K+ strings..(I cancelled the process after 12hrs).
One idea is to use hash tables, or environments in R. However, I don't get how "translate/convert" my strings into an environment while keeping the numerical index?
I have strings[1]... till strings[60000]
e <- new.env(hash=TRUE)
for (i in 1:length(strings)) {
assign(x=i, value=strings, envir=e)
}
As x in assign must be a character, I can't use it like this, but I hope you get my idea..I want to be able to index the environment with the same numbers like in my string[...] vector
Thanks for your help!
R environments are not used as much as perl hashes are, I think
just because there are not widely understood 'idioms' for doing
so. In your case the key question is, do you really want the
numerical index? If so it should be the value. The key is your
string, that's the whole point of the exercise.
e <- new.env(hash=T)
strings <- as.character(chickwts$feed) # note! not unique
sapply(1:length(strings), function(i)assign(strings[i], i, e))
e$horsebean # returns 10
In this example only the last index associated with each string
is kept, but you can assign anything that might be useful to each
key, such as a vector of indices.
You can then lookup your data in a number of ways. You can regex search
for keys using ls, for example, and retrieve the values using mget():
# find all keys containing 'beans'
ls(e, patt='bean')
# retrieve bean data
mget(ls(e, pat='bean'),e)

Looping through all items of the JSON with text index on JsonCPP

{
"80550560": {"name":" HAdailton Cesar", "name2": "T-Max"},
"5987810": {"name": "Adnax", "name2": "Adna Zaza"}
}
I have this input and I need to output all the names that comes in the input, but the problem is that i don't have integer organized index, I would have to get the string number and also I don't know what the string text index is going to be.
I would imagine something like this, but I don't know how to get the 'string_text' from JsonCPP
res[string_text]["name"];
Use getMemberNames to get a list.
I'm pretty sure it is possible to iterate through too, but I have always opted to use `getMemberNames'
Reading the documentation for the Json::Value class, it have iterator capabilities like begin and end, so it should be possible to iterate the values like a standard container.