0

I'm calling a LINUX command from within a C++ programme which creates the following output. I need to copy the first column of the output to a C++ variable (say a long int). How can I do it?? If that is not possible how can I copy this result into a .txt file with which I can work with?

Edit

          0 +0
 2361294848 +2361294848
 2411626496 +50331648
 2545844224 +134217728
 2713616384 +167772160

I have this stored as a file, file.txt and I'm using the following code to extract the left column with out the 0 to store it at integers

string stringy="";
int can_can=0;
for(i=begin;i<length;i++)
{
if (buffer[i]==' ' && can_can ==1) //**buffer** is the whole text file read in char*
{
num=atoi(stringy.c_str());
array[univ]=num; // This where I store the values.
univ+=1;
can_can=1;
  }
  else if (buffer[i]==' ' && can_can ==0) 
 {
stringy="";  
}
else if (buffer[i]=='+')
{can_can=0;}
else{stringy.append(buffer[i]);}
}

I'm getting a segmentation error for this. What can be done ?

Thanks in advance.

2
  • 2
    Show us the code! How are you running the Linux command? Commented Sep 11, 2012 at 19:01
  • how is this output retrieved in the first place? Commented Sep 11, 2012 at 19:01

4 Answers 4

3

Just create a simple streambuf wrapper around popen()

#include <iostream>
#include <stdio.h>

struct SimpleBuffer: public std::streambuf
{   
    typedef std::streambuf::traits_type traits;
    typedef traits::int_type            int_type;

    SimpleBuffer(std::string const& command)
        : stream(popen(command.c_str(), "r"))
    {   
        this->setg(&c[0], &c[0], &c[0]);
        this->setp(0, 0); 
    }   
    ~SimpleBuffer()
    {   
        if (stream != NULL)
        {   
            fclose(stream);
        }   
    }   
    virtual int_type underflow()
    {   
        std::size_t size = fread(c, 1, 100, stream);
        this->setg(&c[0], &c[0], &c[size]);

        return size == 0 ? EOF : *c; 
    }   

    private:
        FILE*   stream;
        char    c[100];

};  

Usage:

int main()
{
    SimpleBuffer    buffer("echo 55 hi there Loki");
    std::istream    command(&buffer);

    int  value;
    command >> value;

    std::string line;
    std::getline(command, line);

    std::cout << "Got int(" << value << ") String (" << line << ")\n";
}

Result:

> ./a.out
Got int(55) String ( hi there Loki)
Sign up to request clarification or add additional context in comments.

Comments

1

It is popen you're probably looking for. Try

man popen

.

Or see this little example:

#include <iostream>
#include <stdio.h>

using namespace std;

int main() 
{

    FILE *in;
    char buff[512];

    if(!(in = popen("my_script_from_command_line", "r"))){
        return 1;
    }

    while(fgets(buff, sizeof(buff), in)!=NULL){
          cout << buff; // here you have each line 
                        // of the output of your script in buff
    }
    pclose(in);

    return 0;
}

Comments

0

Unfortunately, it’s not easy since the platform API is written for C. The following is a simple working example:

#include <cstdio>
#include <iostream>

int main() {
    char const* command = "ls -l";

    FILE* fpipe = popen(command, "r");

    if (not fpipe) {
        std::cerr << "Unable to execute commmand\n";
        return EXIT_FAILURE;
    }

    char buffer[256];
    while (std::fgets(buffer, sizeof buffer, fpipe)) {
        std::cout << buffer;
    }

    pclose(fpipe);
}

However, I’d suggest wrapping the FILE* handle in a RAII class to take care of resource management.

Comments

0

You probably want to use popen to execute the command. This will give you a FILE * that you can read its output from. From there, you can parse out the first number with (for example) something like:

fscanf(inpipe, "%d %*d", &first_num);

which, just like when reading from a file, you'll normally repeat until you receive an end of file indication, such as:

long total = 0;

while (1 == fscanf(inpipe, "%l %*d", &first_num))
    total = first_num;

printf("%l\n", total);

3 Comments

your 1 == fscanf seems not right: from man fscanf: '[..] return the number of input items successfully matched and assigned, [..]'. Would be 2 in your case, wouldn't it?
@PatrickB.: No -- the "and assigned" is crucial here. The * in the second conversion prevents its result from being assigned.
ok, I just saw that there was only one argument... and the total == first_num?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.