C++: Output file of system command not generated - c++

I am trying to run a shell command from my code. However, the output file (ts.dat) is not generated.
Can somebody let me know how to solve this problem?
string cmd1, input;
cout << "Enter the input file name: ";
cin >> input;
cmd1 = "grep 'DYNA>' input | cut -c9-14 > ts.dat";
system((cmd1).c_str());

Edit this line:
cmd1="grep 'DYNA>' input | cut -c9-14 > ts.dat";
To this:
cmd1="grep 'DYNA>' " + input + " | cut -c9-14 > ts.dat";
You need to actually use the value from the input string. The way you have your code currently, you are just writing the word input in your string and not using the value that is stored in the string.

cmd1="grep 'DYNA>' "+input+" | cut -c9-14 > ts.dat";
Placing input inside the quotes will let the compiler parse it as a string instead of a variable.

Related

Extracting numbers from string into an array

I'm having a problem with an assignment. I have to open a text file that looks more or less like this:
-------------------------------------------------------------
|ammount | time |delay |
-------------------------------------------------------------
|100 | 342 | 4324 |
with a few more rows. All I have to do is get the numbers into an array, which, for the example above, would look like this: ar[0]=100, ar[1]=342, ar[2]=4324. I imagine that I need to read the file line by line into strings with getline, but what next? If I use stringstream, I would get |100 instead of just 100. I'm really out of ideas now.
To read one line of input like you described (file may be an ifstream or a istringstream here):
for (int i = 0; i < 3; ++i)
{
file.ignore(numeric_limits<streamsize>::max(), '|'); // Ignores all characters until it finds a '|' character
file >> ar[i]; // Reads the number following the '|' to ar[i]
}
file.ignore(numeric_limits<streamsize>::max(), '\n'); // Finally, ignores all characters until newline
You can even make a small shortcut macro if you want:
#define ignore_until(c) ignore(numeric_limits<streamsize>::max(), c)
and use it like this:
file.ignore_until('|');

Separate a line to columns using several spaces (>1) as a delimiter using C++ or linux

I have several lines looking like this:
4539(random number of spaces)07235001(random number of spaces)Aach(random number of spaces)Trier Saarburg
I want to separate it to 4 columns using C++ or linux. The output I want will look like this:
4539|07235001|Aach|Trier Saasburg
So I want to treat several spaces as the delimiter but not the single one.
(random number of spaces thankfully is always > 1)
Lines do not always consist of 4 columns and the space problem is not always at the last column.
Thanks in advance
You should read each field individually. The last field can be read until a newline
character is received:
std::string column1;
std::string column2;
std::string column3;
std::string column4;
while (input_file >> column1)
{
input_file >> column2;
input_file >> column3;
getline(input_file, column4);
}
Another method is to read the entire line using getline and then fetch out the substring fields using std::string::find and std::string::substr.
You can use awk with regular expressions for this:
echo "4539 07235001 Aach Trier Saarburg" | awk 'BEGIN { FS = "[ ]{2,}" } { OFS = "|" }; {$1=$1; print $0 }'
FS variable is used to set the field separator for each record and may contain any regular expression. OFS is the output equivalent of the FS variable.

How to make my function only find real worlds from permutation

The code below gets a word from the user and then switches each letter around, it list all the possible combinations that it can make, I wish to filter out all the results that aren't words, I have a dictionary and words from the dictionary can get grabbed using GetWord();
an example
input admirer
output married
currently it would do
input admirer
output admirre, adminerr...ect
The following code makes this happen.
void Permutations(string input) {
//sorts input for new word
sort(input.begin(), input.end());
do cout << input << endl; while (next_permutation(input.begin(), input.end()));
}
int FindPermutations() {
string word;
cout << "Input word: ";
cin >> word;
//Runs Premutations with given string
Permutations(word);
return 0;
}
So my question is how can I make the permutation only find real words?
Download an English dictionary text file from http://wordlist.sourceforge.net.
Or if you are on unix: cat /usr/share/dict/words > words.txt
Check if the word exists in the file to figure if its a real word.
You could use a look up table containing the starting location of the first word of each alphabet in the file and jump to that location to optimise the search algorithm a little.

Parsing of file with Key value in C/C++

Need some help in parsing the file
Device# Device Name Serial No. Active Policy Disk# P.B.T.L ALB
Paths
--------------------------------------------------------------------------------------- -------------------------------------
1 AB OPEN-V-CM 50 0BC1F1621 1 SQST Disk 2 3.1.4.0 N/A
2 AB OPEN-V-CM 50 0BC1F1605 1 SQST Disk 3 3.1.4.1 N/A
3 AB OPEN-V*2 50 0BC1F11D4 1 SQST Disk 4 3.1.4.2 N/A
4 AB OPEN-V-CM 50 0BC1F005A 1 SQST Disk 5 3.1.4.3 N/A
The above information is in devices.txt file and and i want to extract the device number corresponding to the disk no i input.
The disk number i input is just an integer (and not "Disk 2" as shown in the file).
Open the file and skip first 3 lines.
Start reading line by line from 4th line onward. You can get the device number easily as it is the first column.
To get the disk no, search through each line using the space character. When you encounter one space character it means you've gone past one column. Ignore the repeated spaces and continue this until you reach the disk no. You must handle the spaces in the column data separately if it exist.
Load the disk no and device no in to say a map and later you can use your input to query the device info from this map.
#include <sstream>
#include <fstream>
#include <iostream>
#include <cctype>
using namespace std;
int main(int argc, char* argv[])
{
int wantedDisknum = 4;
int finalDeviceNum = -1;
ifstream fin("test.txt");
if(!fin.is_open())
return -1;
while(!fin.eof())
{
string line;
getline(fin, line);
stringstream ss(line);
int deviceNum;
ss >> deviceNum;
if(ss.fail())
{
ss.clear();
continue;
}
string unused;
int diskNum;
ss >> unused >> unused >> unused >> unused >> unused >> unused >> unused >> diskNum;
if(diskNum == wantedDisknum)
{
finalDeviceNum = deviceNum;
break;
}
}
fin.close();
cout << finalDeviceNum << endl;
system("pause");
return 0;
}
In UNIX, you can easily achieve this using awk or other script lang.
cat Device.txt | awk '{if ( $1 == 2 ) print}'
In C++, you have to extract specific column using strtok and compare it with 'val' if it matches print that line.'
Assuming there is no "Disk" in any of the following columns:
1) Skip lines until you encounter '-' as the first character of a line, then skip that line too.
2) read a line
2.a) skip characters of the current line until isdigit(line[i]) function returns true, then read current character and characters following it into a temporary buffer until isdigit(line[i]) returns false. This is the device id.
2.b) Skip characters of the current line until you find a 'D'
2.b.i) match 'i', 's', 'k' characters, if any of them fails, go to 2.b
2.c) skip characters of the current line until isdigit(line[i]) function returns true, then read current character and characters following it into another buffer until isdigit(line[i]) returns false. This is the disk id.
3) print out both buffers
I don't have my Regular Expression cheat sheet handy, but I'm pretty sure it would be straightforward to run each line in the file through a regex that:
1) looks for a integer in the line
2) skips whitespace followed by text three times
3) matches characters one space and characters
Boost, Qt, and most other common C++ class libraries have a Regex parser for just this kind of thing.

sed matching multiple line pattern

I have a log of following format
<<
[ABC] some other data
some other data
>>
<<
DEF some other data
some other data
>>
<<
[ABC] some other data
some other data
>>
I wanted to select all logs which are having ABC expected result is
<<
[ABC] some other data
some other data
>>
<<
[ABC] some other data
some other data
>>
What will the expression for sed command ?
For fetching contents b/w << >> expression will be
sed -e '/<</,/>>/!d'
But how can I force it to have [ABC] in b/w
This might work for you:
sed '/^<</,/^>>/{/^<</{h;d};H;/^>>/{x;/^<<\n\[ABC\]/p}};d' file
<<
[ABC] some other data
some other data
>>
<<
[ABC] some other data
some other data
>>
sed comes equipped with a register called the hold space (HS).
You can use the HS to collect data of interest. In this case lines between /^<</,/^>>/
h replaces whatever is in the HS with what is in the pattern space (PS)
H appends a newline \n and then the PS to the HS
x swaps the HS for the PS
N.B. This deletes all lines other than those between <<...>> containing [ABC].
If you want to retain other lines use:
sed '/^<</,/^>>/{/^<</{h;d};H;/^>>/{x;/^<<\n\[ABC\]/p};d}' file
<<
[ABC] some other data
some other data
>>
<<
[ABC] some other data
some other data
>>
This works on my side:
awk '$0~/ABC/{print "<<";print;getline;print;getline;print }' temp.txt
tested as below:
pearl.242> cat temp.txt
<<
[ABC] some other data
some other data
>>
<<
DEF some other data
some other data
>>
nkeem
<<
[ABC] some other data
some other data
>>
pearl.243> awk '$0~/ABC/{print "<<";print;getline;print;getline;print }' temp.txt
<<
[ABC] some other data
some other data
>>
<<
[ABC] some other data
some other data
>>
pearl.244>
If you donot want to hard code this statement print "<<";,then you can go for the below:
pearl.249> awk '$0~/ABC/{print x;print;getline;print;getline;print}{x=$0}' temp.txt
<<
[ABC] some other data
some other data
>>
<<
[ABC] some other data
some other data
>>
pearl.250>
To me, sed is line based. You can probably talk it into being multi line, but it would be easier to start the job with awk or perl rather than trying to do it in sed.
I'd use perl and make a little state machine like this pseudo code (I don't guarantee it'll catch every little detail of what you are trying to achieve)
state = 0;
for each line
if state == 0
if line == '<<'
state = 1;
if state == 1
If line starts with [ABC]
buffer += line
state =2
if state == 2
if line == >>
do something with buffer
state = 0
else
buffer += line;
See also http://www.catonmat.net/blog/awk-one-liners-explained-part-three/ for some hints on how you might do it with awk as a 1 liner...
TXR: built for multi-line stuff.
#(collect)
<<
[ABC] #line1
#line2
>>
# (output)
>>
[ABC] #line1
#line2
<<
# (end)
#(end)
Run:
$ txr data.txr data
>>
[ABC] some other data
some other data
<<
>>
[ABC] some other data
some other data
<<
Very basic stuff; you're probably better off sticking to awk until you have a very complicated multi-line extraction job with irregular data with numerous cases, lots of nesting, etc.
If the log is very large, we should write #(collect :vars ()) so the collect doesn't implicitly accumulate lists; then the job will run in constant memory.
Also, if the logs are not always two lines, it becomes a little more complicated. We can use a nested collect to gather the variable number of lines.
#(collect :vars ())
<<
[ABC] #line1
# (collect)
#line
# (until)
>>
# (end)
# (output)
>>
[ABC] #line1
# {line "\n"}
<<
# (end)
#(end)