This code was for implementing cat in Lin, and when I compiled it, it returned me "tp undefined". When I asked my professor, he said the way I used getline is in C language. I'm confused.
int main(int argc, char*argv[]) {
FILE* file;
for (int i = 1; i < argc; i++) {
file = fopen(argv[i],"w");//
if (file < 0) {
perror("Error, Can't open file!");
return -1;
}
if (file.is_open()) {
string tp;
while (getline(file, tp)) { // c type
printf("%d\n", tp);
}
}
}
fclose(file);
return 0;
}
Problem:
printf is incorrectly formatted. %d is for signed integers. %s is for strings of characters (More info here). Additionally, if you want to work with printf() you will need a C string or to call the std::string::c_str() function.
You're doing things in C style (using FILE*, fopen(), etc).
Solution:
If you still want or need to use a C style, replace with printf("%d\n", tp); with printf("%s\n", tp.c_str());.
Use a C++ style instead:
FILE* -> std::ifstream.
fopen() -> std::ifstream::is_open().
file < 0 -> std::ifstream::fail().
perr -> std::cerr.
printf() -> std::cout.
fclose() -> std::ifstream::close().
Additional information:
using namespace std; is considered a bad practice (More info here).
Full code:
#include <iostream>
#include <fstream>
int main(int argc, char*argv[])
{
for(int i = 1; i < argc; i++)
{
std::ifstream file(argv[i]);
if(file.fail())
{
std::cerr << "Error opening file.\n";
return 1;
}
std::string tp;
while(std::getline(file,tp))
std::cout << tp;
}
return 0;
}
Related
Can someone tell me what am i doing wrong here i am getting an error saying getline() not declared in this scope.........any help would be appreciated.
no matching function for call to getline(char**, size_t*, FILE*&)
#include<iostream>
#include<fstream>
#include<string>
using namespace std;
char *s;
int main(int argc, char *argv[])
{
FILE* fd = fopen("input.txt", "r");
if(fd == NULL)
{
fputs("Unable to open input.txt\n", stderr);
exit(EXIT_FAILURE);
}
size_t length = 0;
ssize_t read;
const char* backup;
while ((read = getline(&s, &length, fd) ) > 0)
{
backup = s;
if (A() && *s == '\n')
{
printf("%sis in the language\n", backup);
}
else
{
fprintf(stderr, "%sis not in the language\n", backup);
}
}
fclose(fd);
return 0;
}
You'll need to use C++ style code in order to use getline in a cross platform way.
#include <fstream>
#include <string>
using namespace std;
std::string s;
bool A() { return true; }
int main(int argc, char *argv[])
{
ifstream myfile("input.txt");
if(!myfile.is_open())
{
fprintf(stderr, "Unable to open input.txt\n");
return 1;
}
size_t length = 0;
size_t read;
std::string backup;
while (getline(myfile, s))
{
backup = s;
if (A() && s == "\n")
{
printf("%s is in the language\n", backup.c_str());
}
else
{
fprintf(stderr, "%s is not in the language\n", backup.c_str());
}
}
return 0;
}
What are you trying to do with getline(&s, &length, fd)? Are you trying to use the C getline?
Assuming you have opened the file correctly, in c++ your getline should look something like this: getline(inputStream, variableToReadInto, optionalDelimiter).
You didn't include <stdio.h> but you did include <fstream>. Maybe use ifstream fd("input.txt");
What's A()
If you ARE trying to use the C getline, the using namespace std may be interfering
Why are you using printf and fprintf and not cout << xxxxxx and fd << xxxxxx
You seem to be a bit confused with various getline function signatures.
The standard C++ std::getline signature is
template< class CharT, class Traits, class Allocator >
std::basic_istream<CharT,Traits>& getline( std::basic_istream<CharT,Traits>& input,
std::basic_string<CharT,Traits,Allocator>& str,
CharT delim );
It takes an input stream object, a string and a character delimiter (there's an overload without the delimiter too).
The posix getline signature is
ssize_t getdelim(char **lineptr, size_t *n, int delim, FILE *stream);
with the delimiter optional again.
now in your code your passing arguments as if calling the posix version without delimiter. If you want to use the standard one you'll have to change the arguments (i.e. istream object instead of FILE*). I don't know if the posix one is even available for you, since posix is different from any C++ standard.
Note that the fputs, FILE*, fprintf are C filehandling functions, not the C++ ones.
Loop isn't making 10 copies and i have no idea how to change file names
#include "iostream"
#include "fstream"
#include "windows.h"
using namespace std;
void main()
{
char str[200];
ifstream myfile("as-1.txt");
if (!myfile)
{
cerr << "file not opening";
exit(1);
}
for (int i = 0; i < 10; i++)
{
ofstream myfile2("as-2.txt");
while (!myfile.eof())
{
myfile.getline(str, 200);
myfile2 << str << endl;
}
}
system("pause");
}
Solution using plain C API from <cstdio>. Easily customizable.
const char* file_name_format = "as-%d.txt"; //Change that if you need different name pattern
const char* original_file_name = "as-1.txt"; //Original file
const size_t max_file_name = 255;
FILE* original_file = fopen(original_file_name, "r+");
if(!original_file)
//file not found, handle error
fseek(original_file, 0, SEEK_END); //(*)
long file_size = ftell(original_file);
fseek(original_file, 0, SEEK_SET);
char* original_content = (char*)malloc(file_size);
fread(original_content, file_size, 1, original_file);
fclose(original_file);
size_t copies_num = 10;
size_t first_copy_number = 2;
char file_name[max_file_name];
for(size_t n = first_copy_number; n < first_copy_number + copies_num; ++n)
{
snprintf(file_name, max_file_name, file_name_format, n);
FILE* file = fopen(file_name, "w");
fwrite(original_content, file_size, 1, file);
fclose(file);
}
free(original_content);
(*) As noted on this page, SEEK_END may not necessarily be supported (i.e. it is not a portable solution). However most POSIX-compliant systems (including the most popular Linux distros), Windows family and OSX support this without any problems.
Oh, and one more thing. This line
while (!myfile.eof())
is not quite correct. Read this question - it explains why you shouldn't write such code.
int main()
{
const int copies_of_file = 10;
for (int i = 1; i <= copies_of_file; ++i)
{
std::ostringstream name;
name << "filename as-" << i << ".txt";
std::ofstream ofile(name.str().c_str());
ofile.close();
}
return 0;
}
That will make 10 copies of a blank .txt file named "filename as-1.txt" "filename as-2.txt" etc.
Note also the use of int main: main always has a return of int, never void
In C++, I need to start a secondary program from a primary program, sending the second some arguments. I need to return the data produced by the secondary program to the primary program. In this case, the data happens to be a two-dimensional std::string array; we'll call it stringArray. This is easy enough to do:
// snippet from Primary
std::string executionString ("./secondaryProgram arg1 arg2 arg3");
system(executionString);
What I don't know how to do is get the data that Secondary Program produces back to the Primary program (short of writing to a temporary file from Secondary and then reading the file from Primary).
In other words, it would be great if I could do something like:
// snippet from Primary
std::string stringArray[2][3];
stringArray = system(executionString);
I'm not hoping for a solution as simple as this or working code from anyone, any nudge in the right direction is appreciated.
I cannot use sockets for this purpose. I have not been able to figure out how to build a pipe between std::cout and std::cin that works for this case. My only real constraint is that my solution involve system() somehow.
system() does not create pipes to the child process. The child process inherits the parent's standard in, standard out, and standard error descriptors.
On Linux, you can use popen() if you want access to the child's stdin or stdout.
Since you have to use system(), you could
have the secondary program store its results in a file. Your main program would then open the file after the system completes. Sort of like this:
std::string executionString ("./secondaryProgram arg1 arg2 arg3 > output_file.txt");
system(executionString);
std::ifstream result("output_file.txt");
while( result >> str) {
result_vector.push_back(str);
}
Take a look at boost.interprocess. It contains many utilities that can be used for IPC in a portable way.
If you don't want to rely on boost, you can do something like this. Compile with C++11 mode and -pthread GCC option.
Why don't you write the relevant information in the second process to a file, and then read that file in the first process. Seems weird to do it this way, but I think it meets your professor's criteria, at least the parts you've shared with us.
Boost Interprocess should work for you. It supports message queues between threads on different processes.
You can use pipes to communicate. The link provided has examples for linux, but it's very similar to what you would write for windows.
If you need to send arbitrary data that might change at run time you might consider serializing the data sent over the pipes and deserializing it at the receiver. You might use XML, JSON, or something like Protobuf. If you make it human readable that adds the opportunity to reuse components or debug what's happening using the eyeball mark 1
Alright here's what I ended up doing.
"translate"
#include <iostream>
#include <fstream>
#include <vector>
#include <sstream>
#include <algorithm>
#include <cstdlib>
#include <unistd.h>
std::vector<std::string> sortTerms(int n, char* argv[]) {
std::vector<std::string> sortedTerms (n);
for (int i = 0; i < n; i++) {
sortedTerms[i] = argv[i+1]; // first term argv is program name
}
std::sort(sortedTerms.begin(),sortedTerms.end());
return sortedTerms;
}
std::vector<std::string> splitString(int n,std::string str) {
std::vector<std::string> stringVector (n);
std::istringstream iss(str);
for (int i = 0; i < n; i++)
std::getline(iss, stringVector[i], ' ');
return stringVector;
}
int main(int argc, char** argv) {
const int NUM_TERMS = (argc - 1); // number of words to translate
std::string output[NUM_TERMS][2]; // used to store a translated word alongside the English equivalent
std::string stringBuffer; // used to start dictionary with arguments
std::vector<std::string> stringVector (NUM_TERMS); // used as a buffer
std::ofstream outputFile("translated.txt"); // file to write translations to
const bool VERBOSE = true;
stringBuffer.clear();
stringBuffer.append("./dictionary ");
// Sort English words and load them into output
stringVector = sortTerms(NUM_TERMS, argv);
for (int i = 0; i < NUM_TERMS; i++) {
output[i][0] = stringVector[i];
stringBuffer = stringBuffer.append(stringVector[i]);
stringBuffer = stringBuffer.append(" ");
}
int pipeStatus;
int pipeOutput[2]; // file descriptor
pipeStatus = pipe(pipeOutput); // create output read/write pipe ends
if (pipeStatus < 0) {
std::cerr << "ERROR CREATING PIPE" << std::endl;
exit(1);
}
int pid = 0;
pid = fork();
if (pid == 0) { // dictionary
// Connect the pipes
dup2 (pipeOutput[1],1);
// Execute the program
system(stringBuffer.c_str());
// Close pipes
close(pipeOutput[0]);
close(pipeOutput[1]);
exit(0);
}
else if (pid > 0) { // Original process
char* buffer = new char[1024]; // input buffer
// Receive string from dictionary
read(pipeOutput[0],buffer,1024); // read in from output of dictionary
stringBuffer = buffer; // I'd rather work with a std::string
stringVector = splitString(NUM_TERMS, stringBuffer);
for (int i = 0; i < NUM_TERMS; i++)
output[i][1] = stringVector[i];
// Close pipes
close(pipeOutput[0]);
close(pipeOutput[1]);
if (VERBOSE) {
for (int i = 0; i < NUM_TERMS; i++)
std::cout << output[i][0] << " -> " << output[i][1] << std::endl;
}
// write translationString to file
for (int i = 0; i < NUM_TERMS; i++) {
outputFile.write(output[i][0].c_str(),output[i][0].length());
outputFile.write(" -> ",4);
outputFile.write(output[i][1].c_str(),output[i][1].length());
outputFile.write("\n",1);
}
outputFile.close();
exit(0);
}
else if (pid == -1) {
std::cerr << "ERROR FORKING PROCESS" << std::endl;
exit(1);
}
return 0;
}
"dictionary"
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
std::vector<std::string> splitString(std::string str)
{
std::vector<std::string> stringVector (2);
std::istringstream iss(str);
std::getline(iss, stringVector[0], ' ');
std::getline(iss, stringVector[1], ' ');
return stringVector;
}
int main(int argc, char* argv[]) {
const int NUM_TERMS = (argc - 1);
std::string stringBuffer;
std::string returnString[NUM_TERMS];
std::vector<std::string> stringVector;
std::ifstream dictionaryFile ("./dictionary.txt");
// There must be at least one arguement
if (argc <= 1)
std::cout << "Nothing to translate..." << std::endl;
for (int i = 0; i < NUM_TERMS; i++) {
while (dictionaryFile) {
getline(dictionaryFile,stringBuffer);
stringVector = splitString(stringBuffer);
if (stringVector[0] == argv[i+1]) { // wut
returnString[i] = stringVector[1];
break;
}
}
}
// clear string buffer
stringBuffer.clear();
// Form translated words string
for (int i = 0; i < NUM_TERMS; i++) {
stringBuffer.append(returnString[i]);
if (i < (NUM_TERMS - 1))
stringBuffer.append(" "); // append a space after each but the last term
}
// print translated words
std::cout << stringBuffer << std::endl;
dictionaryFile.close();
return 0;
}
"dictionary.txt"
Apple Apfel
Banana Banane
Blackberry Brombeere
Blueberry Heidelbeere
Cherry Kirsche
Fruit Obst
Grape Traube
Lemon Zitrone
Lime Limone
Orange Orange
Peach Pfirsich
Pear Birne
Plum Zwetschge
Raspberry Himbeere
Strawberry Erdbeere
meant to be run like $ ./dictionary Apple Orange Strawberry
produces "translated.txt"
Apple -> Apfel
Orange -> Orange
Strawberry -> Erdbeere
I've still got a bit of polishing to do before I turn it in, but that's the gist of it. Thanks guys!
I am writing a C++ application and I need to read the result of a system command.
I am using popen() more or less as shown here:
const int MAX_BUFFER = 2048;
string cmd="ls -l";
char buffer[MAX_BUFFER];
FILE *stream = popen(cmd.c_str(), "r");
if (stream){
while (!feof(stream))
{
if (fgets(buffer, MAX_BUFFER, stream) != NULL)
{
//here is all my code
}
}
pclose(stream);
}
I've been trying to re-write this in a different way. I saw some non-standard solutions like:
FILE *myfile;
std::fstream fileStream(myfile);
std::string mystring;
while(std::getline(myfile,mystring))
{
// .... Here I do what I need
}
My compiler does not accept this though.
How can I read from popen in C++?
Your example:
FILE *myfile;
std::fstream fileStream(myfile);
std::string mystring;
while(std::getline(myfile,mystring))
Does't work because although you're very close the standard library doesn't provide an fstream that can be constructed from a FILE*. Boost iostreams does however provide an iostream that can be constructed from a file descriptor and you can get one from a FILE* by calling fileno.
E.g.:
typedef boost::iostreams::stream<boost::iostreams::file_descriptor_sink>
boost_stream;
FILE *myfile;
// make sure to popen and it succeeds
boost_stream stream(fileno(myfile));
stream.set_auto_close(false); // https://svn.boost.org/trac/boost/ticket/3517
std::string mystring;
while(std::getline(stream,mystring))
Don't forget to pclose later still.
Note: Newer versions of boost have deprecated the constructor which takes just a fd. Instead you need to pass one of boost::iostreams::never_close_handle or boost::iostreams::close_handle as a mandatory second argument to the constructor.
Here is something which i wrote long back, may help you. It might have some errors.
#include <vector>
#include <string>
#include <stdio.h>
#include <iostream>
bool my_popen (const std::string& cmd,std::vector<std::string>& out ) {
bool ret_boolValue = true;
FILE* fp;
const int SIZEBUF = 1234;
char buf [SIZEBUF];
out = std::vector<std::string> ();
if ((fp = popen(cmd.c_str (), "r")) == NULL) {
return false;
}
std::string cur_string = "";
while (fgets(buf, sizeof (buf), fp)) {
cur_string += buf;
}
out.push_back (cur_string.substr (0, cur_string.size () - 1));
pclose(fp);
return true;
}
int main ( int argc, char **argv) {
std::vector<std::string> output;
my_popen("ls -l > /dev/null ", output);
for ( std::vector<std::string>::iterator itr = output.begin();
itr != output.end();
++itr) {
std::cout << *itr << std::endl;
}
}
I'm trying to output text from a file one line at a time. I'm currently hardcoding it and I have this so far:
int main(int argc, char *argv[])
{
int x;
int k;
int limit = 5;
FILE *file;
file = fopen("C:\\Documents and Settings\\jon\\My Documents\\Visual Studio 2008\\Projects\\Project1\\Assignment8_2\\Debug\\TestFile1.txt", "r");
if (file == NULL) {
perror("Error");
}
for (k = 1; k <= limit; k++) {
while ((x = fgetc(file)) != '\n') {
printf("%c", x);
}
}
fclose(file);
}
I was wondering where in the code above, if at all, I can check for EOF. I assume I need to do that, but not sure why. Still learning.... Thanks!
If you can bound the maximum length of a line, fgets may be a better way to read each line; but since you mention C++, you might consider using, instead, getline (caveat: fgets also put the \n in the buffer it fills, getline doesn't). Both make easy to check for end of file (fgets returns NULL on eof, getline sets the eofbit on its istream argument, which it also returns).
Maybe you can try this:
#include <iostream>
#include <iomanip>
#include <fstream>
using namespace std;
int main() {
int sum = 0;
int x;
ifstream inFile;
inFile.open("test.txt");
if (!inFile) {
cout << "Unable to open file";
exit(1); // terminate with error
}
while (inFile >> x) {
sum = sum + x;
}
inFile.close();
cout << "Sum = " << sum << endl;
return 0;
}
fgets() for C, getline() for C++.
C:
#include <stdio.h>
#include <stdlib.h>
// adjust as appropriate
size_t const MAX_LINE_LENGTH = 1024;
int main()
{
FILE * in;
char line[ MAX_LINE_LENGTH ];
if ( ( in = fopen( "test.txt", "r" ) ) == NULL )
{
puts( "Failed to open test.txt." );
return EXIT_FAILURE;
}
while ( fgets( line, MAX_LINE_LENGTH, in ) != NULL )
{
printf( "%s", line );
}
fclose( in );
return EXIT_SUCCESS;
}
C++:
#include <iostream>
#include <fstream>
#include <string>
int main()
{
std::ifstream in( "test.txt" );
std::string line;
while ( getline( in, line ) )
{
std::cout << line << std::endl;
}
in.close();
return 0;
}
you can call feof() to check for EOF or check if the return code for fgetc() matches EOF.
I'm adding both versions to your code although I'm not sure what the loops (especially the outer one) are supposed to do, but within the context of your sample, EOF checking would look like this..
/* EOF would now terminate both loops, using feof() and fgetc() return to check EOF */
for (k = 1; k <= limit && !feof(file); k++) {
while ((x = fgetc(file))!='\n' && x!=EOF) {
printf("%c", x);
}
}
you should check the eof from the output of fgetc:
...
x = fgetc(file);
while (x != '\n' && x != EOF) {
...
fgetc manual there