beginner: on reading in from file and using istringstream - c++

I have never used istringstream before. I have only split lines before with 1 delimiter so I don't know how to use istringstream. I am splitting lines from a file that look like this:
Table, Wanted, 100
Car, For Sale, 5000
I need to split the strings and then create an array of structs. I have a struct set up already I just don't know how to split the strings. My struct is called item and has types: string type, bool sale, double price. For sale, I want it to say 1 if it is for sale and 0 if it is wanted.
Basically, I want to split it so I can create new variables, type, sale, and price and then create a newItem{type, sale, price} in my item struct and go from there. An example of the code would be extremely helpful. Thanks so much.

A simple method to split a string using a delimiter character is to use std::getline.
std::string line = "Table, Wanted, 100"; // Let's say you have read a line from file.
std::istringstream input{line}; // Create an input stream from string.
// Read all characters up until the delimiter ',' on each iteration.
for (std::string token; std::getline(input, token, ',');) {
/* Do something with each token... */
}
Live example

Related

Read elements from a txt file that are separeted by a character

I'am working on a program where there are first names, last names and a numbers on a file and i need to read that information into my program. My actual problem is that there is people who doesnt have a second name or second last name. To solve the issue I started trying to read from a file until a specific character is found, For example:
Robert, Ford Black,208 //Where Robert is the first name, and Ford Black are his two last names
George Richard, Bradford,508 //Where George Richard are both his first names, and Bradford is his only last
name
I am saving this information in three separeted string, one that will store first and second name, first last and second last name and the third one for the numbers.
I'm trying to only use native libraries from c++.
I've been reading that getline(a,b,c) and IStringStream can actually solve my problem but I don't know how to correctly implement it
It's just a matter of using std::getline with a delimiter character to read out of the string stream. See a simplified example (no error checking) below:
for (std::string line; std::getline(std::cin, line); )
{
std::string firstName, lastName;
std::istringstream iss(line);
std::getline(iss, firstName, ','); // A comma delimits end-of-input
iss >> std::ws; // Skip over any whitespace characters
std::getline(iss, lastName); // Read remaining line
std::cout << "First Name: " << firstName << std::endl;
std::cout << "Last Name: " << lastName << std::endl;
}
Note the line iss >> std::ws; using std::ws from <iomanip> is there to eat up extra whitespace characters (which appear after your comma, in your example).
I'm assuming the C++ line comments in the input are only an annotation for this question, and not part of the actual input.
#include<bits/stdc++.h>
using namespace std;
int main()
{
ifstream myfile("files.txt");
string fullname;
while(getline(myfile,fullname,'/')) break; //here im reading till the first / is acquired and the entire string is stored in "fullname"
string firstname,lastname;
size_t pos=fullname.find(',');
firstname=fullname.substr(0,pos); //store the firstname
lastname=fullname.substr(pos+1);// storee the lastname
cout<<firstname<<" "<<lastname;
}
As the question posed was to read names im assuming before the digit if there were a " / " you can read upto the first occurance of /. this will give you the fullname. Then using the substr on the fullname and find the occurance of a comma if at all it exists. All the characters to the left of position of comma will form your first name and the rest on the right of the position of comma will form the lastname.

How to parse a string with comma separated values in AWS IoT SQL?

I am trying to parse a long string with comma-separated values such as "lat,long,distance,,elevation". String is actually quite long and I need to fetch each value and save the fetched values in different columns in dynamodb. I am using dyamodbv2 rule. Functions I found that could be useful were substring(String, Int [, Int]), length(String), indexof(String, String) and get().
For example I get data like this:
{
LOCATION_DATA: "lat,long,distance,,elevation"
}
Here is what I have done so far,
//first value - 0 to next comma
substring(LOCATION_DATA, 0, indexof(LOCATION_DATA, ',')) as latitude,
//second value - substring starting from last substring to next comma
substring(substring(LOCATION_DATA, indexof(LOCATION_DATA, ',') +1 ) ,
0,
indexof(substring(LOCATION_DATA, indexof(LOCATION_DATA, ',') +1 ), ',')
) as longitude,
...
But this gets too verbose and moving to next comma-separated value increasingly difficult. Is there a way to convert comma-separated values to array and then fetch them with get(0), get(1).. ? I have to fetch around 20 fields this way!
Also, the values can be of varying length, and some fields can be empty, such as value between "distance,,elevation" in example strings. These empty values can be ignored.
As far as I now, there is no way I can store and create custom functions, or use any other function than provided in http://docs.aws.amazon.com/iot/latest/developerguide/iot-sql-functions.html.
In rails, you can convert a string to array based on a separator
Example
LOCATION_DATA = "lat,long,distance,,elevation"
myarray = LOCATION_DATA.split(',')
Then you can use
myarray[0]="lat"
myarray[1]="long"
myarray[2]="distance"
myarray[3]=""
myarray[4]="elevation"
You can also convert these strings to integer or float as:
myarray[0].to_i
myarray[2].to_f
Hope This Helps

Sorting words on same line in file using sort()

Is there a way to sort words alphabetically that appear on the same line? I know that if I have words on a new line I am able to sort them easily using:
vector<string> file;
string line;
file.clear();
ifstream infile("foo.txt", ios_base::in);
infile.seekg(3);
while (getline(infile, line)){
file.push_back(line);
}
sort(file.begin(), file.end());
ofstream outFile;
outFile.open("foo.txt");
for (const auto &e : file) outFile << e << "\n";
But what if the words were on one line in the file (unseparated by spaces), for example: catapebat(cat ape bat). Is there an easy way to do this in C++? Would I not do the getline bit, since I am only grabbing one line? How would I approach this problem?
Use getline to read a line.
Create an istringstream from the string you just read
Read words from there into a vector<string>
Sort the words in that vector
I would suggest getting a dictionary of words like this and comparing each word with the beginning of the string. If there's a match, you remove that many characters from the beginning of the string and store the word in an array. Repeat this until you get an array that contains all the words and then sort the array alphabetically.
Note: It might be worth going through the entire dictionary and keeping track of each matching word. Once the dictionary has been exhausted, select the longest match as the word before continuing on.

How to separate a line of input into multiple variables?

I have a file that contains rows and columns of information like:
104857 Big Screen TV 567.95
573823 Blender 45.25
I need to parse this information into three separate items, a string containing the identification number on the left, a string containing the item name, and a double variable containing the price. The information is always found in the same columns, i.e. in the same order.
I am having trouble accomplishing this. Even when not reading from the file and just using a sample string, my attempt just outputs a jumbled mess:
string input = "104857 Big Screen TV 567.95";
string tempone = "";
string temptwo = input.substr(0,1);
tempone += temptwo;
for(int i=1 ; temptwo != " " && i < input.length() ; i++)
{
temptwo = input.substr(j,j);
tempone += temp2;
}
cout << tempone;
I've tried tweaking the above code for quite some time, but no luck, and I can't think of any other way to do it at the moment.
You can find the first space and the last space using std::find_first_of and std::find_last_of . You can use this to better split the string into 3 - first space comes after the first variable and the last space comes before the third variable, everything in between is the second variable.
How about following pseudocode:
string input = "104857 Big Screen TV 567.95";
string[] parsed_output = input.split(" "); // split input string with 'space' as delimiter
// parsed_output[0] = 104857
// parsed_output[1] = Big
// parsed_output[2] = Screen
// parsed_output[3] = TV
// parsed_output[4] = 567.95
int id = stringToInt(parsed_output[0]);
string product = concat(parsed_output[1], parsed_output[2], ... ,parsed_output[length-2]);
double price = stringToDouble(parsed_output[length-1]);
I hope, that's clear.
Well try breaking down the files components:
you know a number always comes first, and we also know a number has no white spaces.
The string following the number CAN have whitespaces, but won't contain any numbers(i would assume)
After this title, you're going to have more numbers(with no whitespaces)
from these components, you can deduce:
grabbing the first number is as simple as reading in using the filestream <<.
getting the string requires you to check until you reach a number, grabbing one character at a time and inserting that into a string. the last number is just like the first, using the filestream <<
This seems like homework so i'll let you put the rest together.
I would try a regular expression, something along these lines:
^([0-9]+)\s+(.+)\s+([0-9]+\.[0-9]+)$
I am not very good at regex syntax, but ([0-9]+) corresponds to a sequence of digits (this is the id), ([0-9]+\.[0-9]+) is the floating point number (price) and (.+) is the string that is separated from the two number by sequences of "space" characters: \s+.
The next step would be to check if you need this to work with prices like ".50" or "10".

Counting columns of a space separated file

My question concerns the use of std::count (or another appropriate function) to count the columns of a space separated file.
I currently use something like this:
std::ifstream inFile("file");
int lines = std::count(std::istreambuf_iterator<char>(inFile),
std::istreambuf_iterator<char>(), '\n');
to count the lines.
Since all the lines are equal (same amount of data), would something like
std::ifstream inFile("file");
int columns = std::count(std::istreambuf_iterator<char>(inFile),
std::istreambuf_iterator<char>('\n'), ' ') + 1;
do what I need?
Thanks
EDIT:
I mean, if in "file" there is data like 1 2 or 1 [many spaces here] 2, would the value of columns anyway be 2 or not?
No, you'll count spaces, not columns. You need to tokenize your line, e.g. by boost::tokenizer