I am reading through a large log file of bans, and from those bans I want to specify a name within that line (see John below). I then want to print out only the IP of that line. Here are a few lines from an example log file:
[13:42:51] james preston (IP: 11.111.11.11) was banned by john
[13:42:51] gerald farmer (IP: 222.22.222.22) was offline banned by James
[13:42:51] luke parker (IP: 33.33.333.333) was banned by john
So far I can get the lines of the bans containing "john" however I would like to then extract the IP address from those lines.
int main() {
ifstream BanLogs;
BanLogs.open("ban-2019.log");
// Checking to see if the file is open
if (BanLogs.fail()) {
cerr << "ERROR OPENING FILE" << endl;
exit(1);
}
string item;
string name = "john";
int count = 0;
//read a file till the end
while (getline(BanLogs, item)) {
// If the line (item) contains a certain string (name) proceed.
if (item.find(name) != string::npos) {
cout << item << endl;
count++;
}
}
cout << "Number of lines " << count << endl;
return 0;
}
Since you are new to programming, here is the most vanilla way:
size_t startIdx = item.find("(IP: ");
if (startIdx == std::string::npos) continue;
startIdx += 5; // skip the "(IP: " part
size_t endIdx = item.find(')', startIdx + 1);
if (endIdx == std::string::npos) continue;
cout << item.substr(startIdx, endIdx - startIdx) << endl;
This kind of jobs are much easier to do with scripting languages, i.e. Python.
As mentioned in the comments, regular expressions are one option.
Another would be to use std::string::find which you are already using to select the relevant lines. You cloud search for "(IP:" to get the starting position of the address (The actual starting position is the result of std::string::find plus 4 for the length of the search string). Then you can search for ")" to get the end position of the IP address in the string. Using these two positions you can extract a substring containing the IP address by using std::string::substr.
Related
I've been trying to fix this for ages,
I've got a program that takes in a random word from a supplied dictionary (txt file),
and then adds this word to a vector of strings.
The randomWord() function works as intended, but the getWords() seems to mash-up everything when I try to print out the vector.
The vector declaration:
vector<string> pass_words; //Array of words used in password
These are the two functions:
//gets a random word from the wordlist file.
string randomWord()
{
wordfile.open ("wordlist.txt"); //open the wordlist file
string wordonline;
string word;
int wordwant = rand()%58110; //Maximum is 58109 which is the last word, minimum is 0.
for (int linenum = 0; getline (wordfile, wordonline) && linenum <(wordwant+1) ; linenum++) {
if (linenum == wordwant) {
word = wordonline;
}
}
wordfile.close();
return word;
}
// gets random words based on number of words supplied.
void getWords() {
cout << "WORD GET" << endl;
string thisword;
for (int i=0 ; i<num_words; i++) {
thisword = randomWord();
pass_words.push_back(thisword) ;
cout << pass_words[i] << " " ; //debugging
}
cout << endl; //debugging
return;
}
Here is a sample output
WORD GET
posingdsate
What am I doing wrong?
Also apparently, when I put another loop for the pass_words vector, I can see the values, but never after or within the getWords() function.
Here's the other loop's output:
housemaids
--
necessitate
--
contacts
--
kampala
--
pion
--
scooped
--
posing
--
There is a very high probability that you're reading in CR characters from a CRLF delimited file, assuming it is just LF delimited, and printing them, where the carriage return will slam the cursor to the left and write over existing text.
You will need to either read this as CRLF or strip out any CR or LF characters.
You can also force a newline:
std::cout << pass_words[i] << std::endl;
I am writing program for Library Management. I have a file Student.dat which have four columns. Initially when no book is issued it looks like this.
---------------Students List ----------------
Roll No. Name Book Issued Issued Book No.
001 Abhi 0 No
002 Ashu 0 No
After issuing book to '001'.
---------------Students List ----------------
Roll No. Name Book Issued Issued Book No.
001 Abhi 1 1001
02 Ashu 0 No
The roll number of second student becomes '02'.
This is complete issue function in library.cpp
void Library::book_issue()
{
//Some code
fp.open("Students.dat", std::ios::in | std::ios::out);
fp1.open("Books.dat", std::ios::in | std::ios::out);
//////////////////////////////////////////////////////////////////////
int oldPos = fp.tellg();
while (std::getline(fp, line) && !found_stu)
{
std::stringstream ss(line);
ss >> roll_n >> s_name >> tkn >> issued_b_num;
////////////
std::getline(ss, line);
if (boost::iequals(roll_n, r_num))
{
found_stu = true;
if (tkn == 0)
{
std::cout << "Enter Book No. : ";
std::getline(std::cin, b_num);
while (fp1 >> book_n >> b_name >> a_name && !found_book)
{
if (boost::iequals(book_n, b_num))
{
Book::show_book(book_n, b_name, a_name);
found_book = true;
tkn = 1;
Student::reset_issued_book_num();
issued_b_num = book_n;
//////////////////////////////////////////////////////////////////
fp.seekg(oldPos);
fp << roll_n << " " << s_name << " " << tkn << " " << issued_b_num << '\n';
std::cout << "Book Issued Successfully\n";
break;
}
}
if (!found_book)
{
std::cerr << "Book does not exist\n";
}
}
}
}
if (!found_stu)
{
std::cout << "Student record does not exist\n";
}
fp.close();
fp1.close();
}
I want to know whether I have used oldPos variable correctly?
Edit:
After assigning length of Issued Book No. as length of book number, I get repeated record.
---------------Students List ----------------
Roll No. Name Book Issued Issued Book No.
001 Abhi 1 1001
001 Abhi 1 1001
002 Ashu 0 No
The problem is that you overwrite the file that you read. So if one line would become longer, you'd overwrite characters of the next line(s).
As 002 becomes 02 and not 2, I'll assume that No in the file is followed by a whitespace. So if I use to show in a visible manner the LineFeed, the following content of your file:
...NO <LF>002...
will be overwriten with:
...1001<LF>02...
^ (end of the write, remaining chars unchanged)
So the 3 chars No are overwritten with 100, the LineFeed is overwritten with 1 and the 0 is overwritten with the new LineFeed.
If you want to write in-place like you try here, you must ensure that the size of each line remains fixed in all circumstances. So "No" should be followed by the number of space needed to match the length of a book number.
Other remarks
It's not the cause of the error, but tellg() returns a std::streampos, which can be much larger than an int. So I'd recommend to prefer:
auto oldPos = fp.tellg(); // here you're sure it's the right type
Note also that tellg()/seekg() are meant for input stream and tellp()/seekp()for output streams. Fortunately, for bidirectional file streams, there is only one position for reading and writing. But for other kind of bidirectional strings, this is not guaranteed (see this question).
Finally, if the goal of your repositionning is to overwrite the last line, read (and found) you should update it from time to time.
I have the following code to open a file and read the data from it, then take the relavent part and print it to screen.
char* search = "model name";
int Offset;
string Cpu;
ifstream CpuInfo;
CpuInfo.open ("/proc/cpuinfo");
if(CpuInfo.is_open())
{
while(!CpuInfo.eof())
{
getline(CpuInfo,Cpu);
if ((Offset = Cpu.find(search, 0)) != string::npos)
{
//cout << "found '" << search << " " << line << endl;
break;
}
}
CpuInfo.close();
}
Cpu.replace (0,13,"");
cout << Cpu
This usually outputs the type of CPU your using, but one problem is that some people have various spaces inbetween the words that it prints out.
My question is how to remove all the spaces from inbetween the words. They can of random ammount and aren't always present.
Thank you in advance.
Since your question states: "how to remove all the spaces from inbetween the words":
You can use std::remove_if from the standard <algorithm> library in addition to std::isspace:
std::string mystring = "Text with some spaces";
std::remove_if(mystring.begin(), mystring.end(), std::isspace);
This now becomes:
Textwithsomespaces
REFERENCES:
http://en.cppreference.com/w/cpp/algorithm/remove
I'm told to ask the user for a string ( a sentence). Then the user is asked to input another string to search in string 1 (the sentence). The program has to count the number of times the second string shows up in the first string. I'm not getting any errors but it's is not counting the letters. This is the result i get:
Enter a sentence:i love to eat soup
Enter string to search: ou
There are 0 of the string ou in the first string you provided.
Can someone please tell me what i'm doing wrong? I'm a beginner at c++ so i'm having some trouble understanding.
#include <iostream>
#include <string>
using namespace std;
int main() {
string sentence;
string search;
int count = 0;
cout<<"Enter a sentence:";
getline (cin, sentence);
cout<<"Enter string to search:";
getline (cin, search);
cout << "There are " << count << " of the string " << search << " in the first string you provided." <<"\n";
for (int i=0; i < sentence.size(); ++i)
{
if (sentence == search)
count++;
}
return count;
}
Two issues:
You print count before you calculate it.
You are not actually searching for a substring. You should look at the documentation for std::string to find an appropriate way to search for substrings. However, you are on the right track.
Well, you're trying to output the results before calculating them.
Also, == is for exact matches, not substring searches.
You have your cout print line after the loop where you search for the string and set the count. Move it below that loop.
looks like you should put the cout statement in the end of this method. Because in your code, count is always 0 when you output it
You should modify your loop so that it really searches for substrings and count their occurrences:
string::size_type pos = sentence.find(search);
while (pos != string::npos)
{
pos = sentence.find(search, pos + search.size());
count++;
}
Also, you most likely want to move this line after the point where you actually compute the value of count:
cout << "There are " << count << ...
Otherwise, it will obviously output the value to which count was initialized originally (i.e. 0).
C++ newbie here. Writing a simple program. Everything works,except when I attempt to extract firstname and surname and print these individually, the number of letters printed in surname will always be the same size as the number in firstname. So if the name is will jackson, the program will print firstname as: will and second name as: jack. How do I solve this?
here is the code
for( i = 0; i < 19; i++)
if(cAddress[i] == ' ' || cAddress[i] == '_' || cAddress[i] == '-' || cAddress[i] == '.')
break;
strncpy(cFirst, cAddress, i);
cFirst[i] = '\0';
cout << endl << "\n";
cout << "Your first name is " << cFirst << endl;
strcpy(cSur,cAddress + i + 1);
cSur[i] = '\0';
cout << endl;
cout << "Your surname is " << cSur << endl;
You are adding a \0 character at the (i+1)th position - this marks the end of string, so that's all it prints. Before that line, cSur probably contains the entire surname.
Most of your code looks a lot like C -- and doesn't even take full advantage of the C standard library. In C++, I'd write something more like:
int pos = Address.find_first_of(" _-.");
std::string FirstName(Address, 0, pos);
std::string SurName(Address, pos);
If, for whatever reason, you insist on using C style strings, you might consider starting with strpbrk to find the separator.
cSur[i] = '\0';
is incorrect. i is the length of the first name. cSur is already zero terminated by strcpy.
Having explained that, Jerry Coffin's answer is what I would recommend as good c++ code.