Possible vacancy compensation for sscanf - c++

I have a string that is written as follows:
^SYSINFO:2,3,0,3,1,,3
You will notice that there is one digit missing in the line, this may not always be the case. I use sscanf to scan the line and extract the last integer.
sscanf(response_c, "^SYSINFO:%*d,%*d,%*d,%*d,%*d,,%d", &networkattach_i);
How can I compensate for the digit that is currently missing, but may be written also?
The following does NOT work:
sscanf(response_c, "^SYSINFO:%*d,%*d,%*d,%*d,%*d,%*d,%d", &networkattach_i);

You can try using getline to parse your string. An example would be,
using namespace std;
string input = "^SYSINFO:2,3,0,3,1,,3";
istringstream ss(input);
string token;
getline(ss, token, ':'); //reads till SYSINFO
while(getline(ss, token, ',')) {
cout << token << '\n';
}

Related

How can I cin a char with multiple words?

I tried looking on the internet but I've not seen an answer.
So I have to cin a char with multiple words, like "Cars have four wheels." And I need to take every word and cout him. I learned at school that you can do this:
char a[100][20];
cin.getline(a, 100);
But it doesn't work. What's the proper way to cin a char with multiple words separate by a space;
You can try using std::istringstream for parsing the words.
std::vector<std::string> word_database;
std::string text_line;
while (std::getline(std::cin, text_line))
{
std::string word;
std::istringstream text_stream(text_line);
while (text_stream >> word)
{
word_database.push_back(word);
}
}
In the above code, one line of text is input to the text_line variable.
An istringstream is created using the line of text. The "words" are extracted from the text stream using operator>>. The words are appended to the database.

C++ reading in a file, ignoring commas and outputting data to the screen

I have a file in the format:
FirstName,MiddleName,LastName,Major,City,State,GPA
I'm trying to read in the file and output the data without the commas to the screen. This is what I have so far, but it only outputs the GPA's:
#include <fstream>
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
int main(){
string fileline;
string word;
ifstream studentData;
studentData.open("studentData.csv");
while(studentData){
getline(studentData,fileline);
istringstream ss(fileline);
while(getline(ss, word,','));{
cout << word << '\n';
}
}
return(0);
}
I think the problem is this line:
while(getline(ss, word,','));{
Try removing the semicolon. This would be the right way:
while(getline(ss, word,',')){
The semicolon makes the loop do nothing until it reads the last word (which I'm guessing is the GPA), which you then print.
Let us know if that works!
The semicolon in while(getline(ss, word, ','); shouldn't be there. That said, stringstreams are slow, I'd prefer to do this as follows.
while(std::getline(studentData, fileline)) {
std::erase(std::remove(fileline.begin(), fileline.end(), ','), fileline.end());
std::cout << fileline << '\n';
}
If you just want to copy without commas, why not just copy without commas?
ifstream studentData("StudentData.csv");
studentData >> noskipws;
std::remove_copy(std::istream_iterator<char>(studentData),
std::istream_iterator<char>(),
std::ostream_iterator(std::cout)
',');
OTOH, if your input doesn't have anything separating the fields except the commas, this will produce output with them all run together. You might prefer to write out a space character between fields instead:
std::transform(std::istream_iterator<char>(studentData),
std::istream_iterator<char>(),
std::ostream_iterator<char>(std::cout),
[](char ch) { return ch == ',' ? ' ' : ch; });
This way you'll still have something to help keep track of where one field ends and the next starts. Of course, if you prefer, say, a tab rather than a space, you can change the space to a tab.

StringStream input with comma delimited string - know columns apriori

I have a csv that I'd like to tokenize line by line with StringStream. The key is that I know apriori what the columns would look like. For example, say I know the file looks like the following
StrHeader,IntHeader
abc,123
xyz,456
I know ahead of time it is a string column, followed by an int column.
Common approach is to read the file line by line
std::string line;
stringstream lineStream;
while (getline(infile, line)) // read line by line
{
cout << "line " << line << endl;
lineStream << line;
string token;
while(getline(lineStream, token, ',')) // push into vector? this is not ideal
{
}
I know I can have 2 loops, and have inner loop tokenizes the string based on commas. Lots of sample code on stackoverflow would store the result into a vector<string>.
I don't want to do create a new vector every line. Since I know apriori what columns the file would have, can I somehow read directly into a string and int variable? Like this
std::string line;
stringstream lineStream;
while (getline(infile, line)) // read line by line
{
cout << "line " << line << endl;
lineStream << line; // DOESNT WORK - tell lineStream we have comma delimited string
string strValue;
int intValue;
lineStream >> strValue >> intValue; // SO MUCH CLEANER
// call foo(strValue, intValue);
}
The problem above is this line
lineStream << line; // DOESNT WORK - tell lineStream we have comma delimited string
From what I could tell, the above code works if the input line is space delimited, not comma delimited.
I have no control over the input. So, simply replacing the "spaces" with "commas" in the original string is not an ideal solution since I don't know if the input already has spaces.
Any ideas? thanks
You could try to only read to the delimiter with std::getline() and then put that in a string stream for conversion.
while (!infile.eof()){
std::getline(infile, strValue, ',');
std::getline(infile, line);
strstr.str(line);
strstr.clear();
int intValue;
strstr >> intValue;
foo(strValue, intValue);
}

is it possible to read from a specific character in a line from a file in c++?

Hey all so I have to get values from a text file, but the values don't stand alone they are all written as this:
Population size: 30
Is there any way in c++ that I can read from after the ':'?
I've tried using the >> operator like:
string pop;
inFile >> pop;
but off course the whitespace terminates the statement before it gets to the number and for some reason using
inFile.getline(pop, 20);
gives me loads of errors because it does not want to write directly to string for some reason..
I don't really want to use a char array because then it won't be as easy to test for the number and extract that alone from the string.
So is there anyway I can use the getline function with a string?
And is it possible to read from after the ':' character?
#include <iostream>
#include <fstream>
#include <string>
#include <cstring>
#include <cstdlib>
using namespace std;
int main()
{
string fname;
cin >> fname;
ifstream inFile;
inFile.open(fname.c_str());
string pop1;
getline(inFile,pop1);
cout << pop1;
return 0;
}
ok so here is my code with the new getline, but it still outputs nothing. it does correctly open the text file and it works with a char array
You are probably best to read the whole line then manipulate the string :-
std::string line;
std::getline(inFile, line);
line = line.substr(19); // Get character 20 onwards...
You are probably better too looking for the colon :-
size_t pos = line.find(":");
if (pos != string::npos)
{
line = line.substr(pos + 1);
}
Or something similar
Once you've done that you might want to feed it back into a stringstream so you can read ints and stuff?
int population;
std::istringstream ss(line);
ss >> population;
Obviously this all depends on what you want to do with the data
Assuming your data is in the form
<Key>:<Value>
One per line. Then I would do this:
std::string line;
while(std::getline(inFile, line))
{
std::stringstream linestream(line);
std::string key;
int value;
if (std::getline(linestream, key, ':') >> value)
{
// Got a key/value pair
}
}

c++ string manipulation reversal

I am currently doing c++ and am going through how to take in an sentence through a string and reverse the words (This is a word......word a is This etc)
I have looked at this method:
static string reverseWords(string const& instr)
{
istringstream iss(instr);
string outstr;
string word;
iss >> outstr;
while (iss >> word)
{
outstr = word + ' ' + outstr;
}
return outstr;
}
int main()
{
string s;
cout << "Enter sentence: ";
getline(cin, s);
string sret = reverseWords(s);
cout << reverseWords(s) << endl;
return 0;
}
I have gone through the function and kind of understand but I am a bit confused as to EXACTLY what is going on at
iss >> outstr;
while (iss >> word)
{
outstr = word + ' ' + outstr;
}
return outstr;
Can anybody explain to me the exact process that is happening that enables the words to get reversed?
Thank you very much
iss is an istringstream, and istringstreams are istreams.
As an istream, iss has the operator>>, which reads into strings from its string buffer in a whitespace delimeted manner. That is to say, it reads one whitespace separated token at a time.
So, given the string "This is a word", the first thing it would read is "This". The next thing it would read would be "is", then "a", then "word". Then it would fail. If it fails, that puts iss into a state such that, if you test it as a bool, it evaluates as false.
So the while loop will read one word at a time. If the read succeeds, then the body of the loop appends the word to the beginning of outstr. If it fails, the loop ends.
iss is a stream, and the >> is the extraction operator. If you look upon the stream as a continuous line of data, the extraction operator removes some data from this stream.
The while loop keep extracting words from the stream until it is empty (or as long as the stream is good one might say). The inside of the loop is used to add the newly extracted word to the end of the outstr
Look up information about c++ streams to learn more.
The instruction:
istringstream iss(instr);
allows instr to be parsed when the operator>> is used, separating words thourgh a whitespace character. Each time the operator >> is used it makes iss point to the next word of the phrase stored by instr.
iss >> outstr; // gets the very first word of the phrase
while (iss >> word) // loop to get the rest of the words, one by one
{
outstr = word + ' ' + outstr; // and store the most recent word before the previous one, therefore reversing the string!
}
return outstr;
So the first word retrieved in the phrase is actually stored in the last position of the output string. And then all the subsequent words read from the original string will be put before the previous word read.