Pregunta
Descripción:
- Obtener salida de un ejecutable
Nota:
- No se compilará debido a la declaración fgets()
Pregunta:
- ¿Cuál es la mejor alternativa a fgets, ya que fgets requiere char *?
- ¿Hay una mejor alternativa?
Ilustración:
void Q_analysis (const char *data)
{
string buffer;
size_t found;
found = buffer.find_first_of (*data);
FILE *condorData = _popen ("condor_q", "r");
while (fgets (buffer.c_str(), buffer.max_size(), condorData) != NULL)
{
if (found == string::npos)
{
Sleep(2000);
} else {
break;
}
}
return;
}
Solución
Debería usar la función string.getline para cadenas cppreference
sin embargo, en su caso, debería usar un char [] para leer.
por ejemplo
string s;
char buffer[ 4096 ];
fgets(buffer, sizeof( buffer ), condorData);
s.assign( buffer, strlen( buffer ));
o su código:
void Q_analysis( const char *data )
{
char buffer[ 4096 ];
FILE *condorData = _popen ("condor_q", "r");
while( fgets( buffer, sizeof( buffer ), condorData ) != NULL )
{
if( strstr( buffer, data ) == NULL )
{
Sleep(2000);
}
else
{
break;
}
}
}
Otros consejos
En lugar de declarar el búfer como una cadena, declararlo como algo así como:
char buffer[MY_MAX_SIZE]
llame fgets con eso, y luego construya la cadena desde el búfer si lo necesita en esa forma en lugar de ir hacia el otro lado.
La razón por la que lo que está haciendo no funciona es que está obteniendo una copia del contenido del búfer como una cadena de estilo c, no un puntero en el intestino del búfer. Es, por diseño, de solo lectura.
- MarkusQ
Tienes razón en que no puedes leer directamente en un std::string
porque es c_str
y data
Ambos métodos devuelven punteros constantes.Podrías leer en un std::vector<char>
en cambio.
También podrías utilizar el getline
función.Pero requiere un objeto iostream, no un puntero de ARCHIVO C.Sin embargo, puede pasar de uno a otro de una manera específica del proveedor.Ver "Una guía práctica para manipular manijas" para ver un diagrama y algunas sugerencias sobre cómo pasar de un tipo de archivo a otro.Llamar fileno
en tu FILE*
para obtener un descriptor de archivo numérico y luego usar fstream::attach
asociarlo con un fstream
objeto.Entonces puedes usar getline
.
Pruebe la biblioteca de impulso: creo que tiene una función para crear un fstream desde un ARCHIVO *
o puede usar fileno () para obtener un identificador de archivo C estándar desde el ARCHIVO, luego use fstream :: attach para adjuntar una secuencia a ese archivo. Desde allí puede usar getline (), etc. Algo como esto:
FILE *condorData = _popen ("condor_q", "r");
std::ifstream &stream = new std::ifstream();
stream.attach(_fileno(condorData));
No lo he probado demasiado bien, pero el siguiente parece hacer el trabajo:
//! read a line of text from a FILE* to a std::string, returns false on 'no data'
bool stringfgets(FILE* fp, std::string& line)
{
char buffer[1024];
line.clear();
do {
if(!fgets(buffer, sizeof(buffer), fp))
return !line.empty();
line.append(buffer);
} while(!strchr(buffer, '\n'));
return true;
}
Sin embargo, tenga en cuenta que con gusto leerá una línea de texto de 100G, por lo que debe tenerse cuidado de que este no sea un vector DoS de archivos o sockets no confiables.