breaking down an input sentence - c++

in the code i am working on, the input will be of this form: abcd = insert(15MB). What i need to do is insert 15MB into the identifier 'abcd'. Here is the code i have.
#include <iostream>
#include <algorithm>
#include <string>
#include <iomanip>
#include <limits>
#include <stdio.h>
using namespace std;
string extract(string pMem);
double toByte(int phyMem, string val);
string pMem, comment, sGen, val,foo;
int gen, phyMem, i=0, oBrckt=0, cBrckt=0;
double pmemSize =0;
int main()
{
getline(cin,foo);
if((foo.find("insert"))!= string::npos)
cout<<"Found insert"<<endl;
cin.clear();
}
The problem: I am unable to find the code word insert from the input command. I am guessing the problem is because the word insert(15MB) is considered as a whole. Is there any way to break it down so that i can save abcd into the identifier "tag", and 50MB into the identifier "Memory"?

You may use scanf, which is faster than cin and also provides the functionality you want:
char t[256], m[256];
scanf("%s = insert(%[^)]);", t, m);
string tag = t, Memory = m;
This basically means: read a string, then skip " = insert(", then read the inner string until you find a ')', then skip the final ");".
Just make sure you are reading from the correct input.
If you really want to read the input with getline, you can still use sscanf to achieve the same, on top of your foo string:
sscanf(foo.c_str(), "%s = insert(%[^)]);", t, m);
Note the extra 's' in sscanf is not a typo here. t and m are just temporary char buffers to store your content, you can assign it directly to a string afterwards if you wish. Please note the code above assumes the 'tag' and 'Memory' contents will not be longer than 255 characters each.

Related

I have made a program in C++ to separate words from a line by spacebar and display those words as an array. What's wrong in my code?

Please help me to find a bug in this program.It separates a line into words by spacebar. And display as a list.
If the first char of a word is in lower case, it is converted to uppercase.
#include <iostream>
#include <string>
using namespace std;
int main()
{
char line[30]="Hi there buddy",List[10][20];
unsigned int i=0,List_pos=0,no;
int first=0,last;
while(i!=sizeof(line)+1)
{
if(line[i]==' ' or i==sizeof(line))
{
last=i;
no=0;
for(int j=first;j<last;++j)
{
if(no==0)
List[List_pos][no]=toupper(line[j]);
else
List[List_pos][no]=line[j];
++no;
}
++List_pos;
first=last+1;
}
++i;
}
for(unsigned int a=0;a<List_pos;++a)
cout<<"\nList["<<a+1<<"]="<<List[a];
return 0;
}
Expected Output:
List[1]=Hi
List[2]=There
List[3]=Buddy
Actual Output:
List[1]=Hi
List[2]=ThereiXŚm
List[3]=Buddy
I suggest you use a string, as you already included it. And 'List is not really necessary in this situation. Try making a single for loop where you separate your line into words, in my opinion when you work with arrays you should use for loops. In your for loop, as you go through the line, you could just add a if statement which determines whether you're at the end of a word or not. I think the problem in your code is the multiple loops but I am not sure of it.
I provide you a code which works. Just adapt it to your display requirements and you will be fine
#include <iostream>
#include <string>
using namespace std;
int main()
{
string line = "Hi there buddy";
for (int i = 0; i < line.size(); i++) {
if (line[i] == ' ') {
line[i + 1] = toupper(line[i+1]);
cout<<'\n';
} else {
cout<<line[i];
}
}
return 0;
} ```
Challenged by the comment from PaulMcKenzie, I implemented a C++ solution with 3 statements:
Define a std::string, with the words to work on
Define a std::regex that finds words only. Whitespaces and other delimiters are ignored
Use the std::transform to transform the input string into output lines
std::transform has 4 parameters.
With what the transformation should begin. In this case, we use the std::sregex_token_iterator. This will look for the regex (so, for the word) and return the first word. That's the begin.
With what the transformation should end. We use the empty std::sregex_token_iterator. That means: Do until all matches (all words) have been read.
The destination. For this we will use the std::ostream_iterator. This will send all transformed results (what the lambda returns) to the given output stream (in our case std::cout). And it will add a delimiter, here a newline ("\n").
The transormation function. Implemented as lambda. Here we get the word from the std::sregex_token_iterator and transform it into a new word according to what we want. So, a word with a capitalized first letter. We add a little bit text for the output line as wished by the OP.
Please check:
#include <string>
#include <iostream>
#include <regex>
#include <iterator>
int main()
{
// 1. This is the string to convert
std::string line("Hi there buddy");
// 2. We want to search for complete words
std::regex word("(\\w+)");
// 3. Transform the input string to output lines
std::transform(
std::sregex_token_iterator(line.begin(), line.end(), word, 1),
std::sregex_token_iterator(),
std::ostream_iterator<std::string>(std::cout, "\n"),
[i = 1](std::string w) mutable {
return std::string("List[") + std::to_string(i++) + "]=" + static_cast<char>(::toupper(w[0])) + &w[1];
}
);
return 0;
}
This will give us the following output:
List[1]=Hi
List[2]=There
List[3]=Buddy
Please get a feeling for the capabilities of C++
Found a solution for your next problem (when the user inputs a sentence only the first word it displayed). When you input a "space", the cin just thinks you are done. You need to use the getLine() to get the whole sentence.
getline(cin, line);
Instead of
cin>>line;

C++ std::getline result string won't let me concatenate another string to it

I am attempting to read data from a .txt file which contains nothing but a list of names. I want to do the following for each name:
1) read a name and store it in a string variable.
2) Add quotes to the name ("name")
3) make a map entry using each name (map["name"]= x)
I am using the std::getline function to read each line and I'm trying to add the quotes simply by using ( string name="\""+line+"\"" ).
The problem is that every time I add something to the end of the line string, nothing is added!
This is my code:
#include <iostream>
#include <string>
#include <map>
#include <fstream>
#include <stdlib.h>
using namespace std;
int main(){
ifstream reader("input.txt");
string line;
string name;
map<string,int> arr;
int np=5;
for(int i=0;i<np;i++){
getline(reader,line);
name="\"" +line +"\"";
cout<< name << endl;
}
return 0;
}
This is my input txt file:
dave
laura
owen
vick
amr
this is the output I'm currently getting:
"dave
"laura
"owen
"vick
"amr"
Thank you very much!
I suppose your input lines ends with \r\n, while your getline reads until '\n'. If that is true then solution is to remove manually \r char at the end of line:
getline(reader,line);
line.pop_back();
[edit]
or instead of pop_back():
auto cr_pos = line.rfind('\r');
if ( cr_pos != std::string::npos )
line = line.substr(0, cr_pos);

Read from text file C++ (fname, lname, class, seat number), store and verify

I have a text file of the classlook like this:
FName LName Class SeatNum
FName2 LName2 Class2 SeatNum2
...
and the list goes on.
How to read lines of strings and store them into different variables?
How to combine Class & SeatNum to be an ID (3D-20)?
How to verify for every input name and ID has to be matched?
For example, input > FName LName Class2-SeatNum2 is wrong, please try again.
Your help is greatly appreciated.
Thanks!
Just a note for next time - because you didn't detail the problem, it was hard to figure out what you mean. Anyhow:
in order to do what you asked you need to:
a) read the data from the file
b) split the data based on the character which is between the cells.
In C++, The split string algorithm is in boost - if you dont know what that is, make sure you take a look in here: http://www.boost.org/
Soltion:
I`m modifying various cPlusPlus guides here to fit your purpouse:
#include <sstream>
#include <iostream>
#include <fstream>
#include <vector>
#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/classification.hpp>
using namespace std;
vector<string> getData (string filePath) {
vector<string> Cells; // In the end, here we will store each cell's content.
stringstream fileContent(""); // This is a string stream, which will store the database as a string.
ofstream myfile; // the file which the database is in
myfile.open (filePath); // Opening the file
while ( getline (myfile,line) ) // Reading it until it's over
{
fileContent << line; // adding each line to the string
}
split(Cells, fileContent.str(), is_any_of(" "));// Here, insert the char which seperates the cells from each other.
myfile.close()
return Cells; // returning the split string.
}
Hope i helped :)

getline to split string manipulation error

Hey guys so I have an assignment for class where I have to split a string and manipulate it. However, when I try to split the string and assign it to an array only the first element comes and the other two don't. Please help.
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
using namespace std;
int main()
{
string str;
cout<<"Enter a first name, middle initial, last name: ";
cin>> str;
string word;
string array[3];
stringstream stream(str);
int counter = 0;
while( getline(stream, word, ' ') )
{
cout<<word;
array[counter] = word;
counter++;
}
cout<<"The "<<array[0].length()<<" characters of the first name are: "<<array[0]<<endl;
cout<<"The "<<array[2].length()<<" characters of the last name are: "<<array[2]<<endl;
string newstring = array[2]+", "+array[0]+" "+array[1];
cout<<"In the phone book, the name would be: "<<newstring<<endl;
cout<<"The length of the name is: "<<newstring.length()<<endl;
cout<<"The comma is at position: "<<newstring.find(",")<<endl;
array[0].swap(array[2]);
cout<<"After the swap, the last name is "<<array[2]<<" and the first name is "<<array[0];
system("pause");
return 0;
}
There are a few blatant errors in your code:
You need to always check your input after trying to read! You do that using the while-loop but you also need to verify that you actually successfully read the string first.
It seems you are mixing the what the input operator for std::string and std::getline() are doing: the input operator reads the first word after skipping leading spaces while std::getline() read, well, a line (whether the line terminator can be specified as third argument).
When reading fixed sized array you always need to make sure you do not read more than fits into this array! You may have heart about hackers exploiting software by using buffer overruns: assuming you'd actually indeed read a line first followed by splitting it into words you'd have created one of those exploitable programs! If you don't want to check before each word if there is enough space in the array, you'd use, e.g., a std::vector<std::string> (doing so also has a problem with hackers, namely that it opens up the program for a Denial of Service attack but although this is still a problem it is a somewhat lesser problem).
There are also a few smaller issues with your program, too:
If you are only reading from a string stream, you should use std::istringstream as there is no need to also set up the writing part of the std::stringstream.
The programs asks for "first name, middle name, and last name". I would read that specification to use, e.g., "John, F., Kennedy" but it seems you'd expect "John F. Kennedy". One reason I would expect that commas are to be used is that I don't have a middle name, i.e., I would enter "Dietmar, , Kühl".

fstream isnt reading from a text file after two lines

im struggling with this part of code , no matter what i try i cant get it to read into a record after two lines
the text file contains
Mickey Mouse
12121
Goofy
24680
Andy Capp
01928
Quasi Modo
00041
end
and the code is
#include<iostream>
#include<string.h>
#include <stdio.h>
#include <windows.h>
#include<iomanip>
#include<conio.h>
#include<fstream>
#include<string>
using namespace std;
struct record
{
char name[20];
int number;
};
void main()
{
record credentials[30];
int row=0;
fstream textfile;//fstream variable
textfile.open("credentials.txt",ios::in);
textfile.getline (credentials[row].name,30);
//begin reading from test file, untill it reads end
while(0!=strcmp(credentials[row].name,"end"))
{
textfile>>credentials[row].number;
row++;
//read next name ....if its "end" loop will stop
textfile.getline (credentials[row].name,30);
}
textfile.close();
}
the record is only taking the first two lines and the rest is empty
any ideas ??
The problem is that:
textfile>>credentials[row].number;
while not consume the newline character. The subsequent call to textfile.getline() reads a blank line and the next:
textfile>>credentials[row].number;
attempts to read "Goofy" into an int which fails and set the failbit of the textfile stream meaning all further attempts to read fail. Check the return value to detect failure:
if (textfile >> credentials[row].number)
{
// Success.
}
I am not entirely sure how the program ends as "end" will never be read but I suspect it ends abnormally as there is no mechanism to prevent overruning the end of the credentials array (i.e no row < 30 as part of the loop terminating condition).
Other:
Instead of using a fixed sized char[] to read the names into you can use std::getline():
#include <string>
struct record
{
std::string name;
int number;
};
if (std::getline(textfile, credentials[row].name))
{
}
Instead of using a fixed sized record[] you could use a std::vector<record> which will grow as required.