C++ Parameterübergabe an ausführbare Datei unter Linux

LieberNetterFlo

Rear Admiral
Registriert
Feb. 2006
Beiträge
5.838
Hallo zusammen,

ich spiele gerade mit meinem Raspberry Pi rum und hab dort am SPI Bus einen LED Strip hängen (32 RGB LEDs). Diese kann ich auch schon erfolgreich leuchten lassen (mit unten stehenden Programm).

Nun würde ich der ausführbaren Datei aber gerne über die Parameter sagen welche Farbe leuchten soll. Mein Problem ist die Parameterübergabe. Ich hab zwar im Internet Code gefunden, aber leider braucht mein Array das in einer ganz besonderen Form.

Wisst ihr wie das geht?

p.s. die ganzen INCLUDES sind überrest von meinen vorigen versuchen und das
Code:
int main( int argc,      // Number of strings in array argv
          char* argv[])  // Array of command-line argument strings
ist wohl ein Anfang wie man Parameter übergibt. Ich kan da auch drauf zugreifen mit argv[x] aber ich bekomms nicht ins richtige Format.

ich würde gerne übergeben entweder 255255255 oder 255 255 255 oder FFFFFF oder FF FF FF. (Favorit: FFFFFF).

Daraus müsste ich nun die Zeichen extrahieren und ein 0xFF oder \xFF bekommen.

Code:
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <stdlib.h>
#include <unistd.h>
#include <iomanip>
using namespace std;

int main( int argc,      // Number of strings in array argv
          char* argv[])  // Array of command-line argument strings
{
// Initialisierung
cout << "Starting ..." << endl;
char buffer[96];
int i=0;

//alles aus
while(i<94){
        buffer[i] = '\x00';
        i++;
        buffer[i] = '\x00';
        i++;
        buffer[i] = '\x00';
        i++;
        };i=0;

//alles gleiche farbe
while(i<94){
        buffer[i] = '\xff';
        i++;
        buffer[i] = '\x00';
        i++;
        buffer[i] = '\xff';
        i++;
        };i=0;

ofstream myfile; // Dateistream anlegen
myfile.open ("/dev/spidev0.0",ios::binary); // Datei bzw Device öffnen
myfile.write(buffer,96); // Daten schreiben

// Programmende
cout << "... the end!" << endl;
return 0;
}
 
Code:
unsigned int arg;
sscanf(argv[1U], "%x", &arg);
unsigned char c0 = (arg >> 0U) & 0xFF;
unsigned char c1 = (arg >> 8U) & 0xFF;
unsigned char c2 = (arg >> 16U) & 0xFF;

Ungetestet, aber so ähnlich sollte es funktionieren.

PS: Mein Beispiel wäre für die Übergabe im Format FFFFFF.
 
Zuletzt bearbeitet:
Hi,

mit dieser Schleife kannst du deine Kommandozeilenparameter wieder auf die Konsole ausgeben.

Code:
#include <iostream>

int main(int argc, char **argv)
{
	for(int i = 0; i < argc; i++)
	{
		std::cout << argv[i] << '\n';
	}
	return 0;
}

Also nächstes musst du statt cout die Verarbeitung deines Übergabeparameters beim Programmaufruf entspechend bearbeiten, so dass dein buffer das richtige Format hat.

Damit es ganz einfach wird, würde ich vorschlagen, pro Farbe einen Parameter zu verwenden, also dein Programm so aufrufen:
Code:
./deinprogramm f f f
Beachte die Leerzeichen.

Ich hoffe das hilft dir weiter
 
@Simpson474

Danke. Ich nehme mal an du meinst statt argc argv in deinem code?
ich gebe deine 3 Parameter einfach mal aus und erhalte auf der Console ein "ª" für den Parameter FF, wenn ich aber cout << '\xFF' mache erhalte ich ein "ÿ" d.h. es klappt nicht so ganz. (deinen Code verstehe ich auch nicht so ganz ... was macht das 1U ?

@FlyingEagle
Danke. Die Übergabeparameter wieder ausgeben ist kein problem, das umwandeln in das hex Format klappt aber bisher nicht. ich muss schon mit FF FF FF arbeiten, sonst kann ichs via LEDs gar nicht kontrollieren.
 
Das mit argc/argv ist bereits korrigiert, war nur in der ersten geposteten Version ;)

Mach die Ausgabe der Parameter mal mit einem cast auf unsigned int, also so:
Code:
cout << (unsigned int)c0;
cout << (unsigned int)'\xFF';
 
hey

also wenn ich das programm so aufrufe "programm FF00AA" kommt bei folgenden ausgaben
Code:
cout << (unsigned int)c0 << endl;
cout << (unsigned int)'\xFF' << endl;
cout << c0 << endl;
cout << '\xff' << endl;
folgendes raus
 
170 ist 0xAA, dreh einfach mal die Variablen c0 bis c2 um, dann sollte die 0xFF in c0, 0x00 in c1 und 0xAA in c2 stehen.
 
ich glaub ich steh grad auf der Leitung ^^ wie gebe ich das denn dann aus wie ich meinen "buffer" oben ausgeben? also in eine Datei?

und kann ich das c auch einfach als array machen? insegsamt werd ich nämlich 32 * 3 brauchen,

also so "datei FFFFFF FFAAFF AAFFCC AAAABB 11DDFF A0F23F ...." usw ... 32 parameter jeweils aus 3
Ergänzung ()

ok, habs jetzt mal so gemacht
Code:
unsigned int arg;
unsigned char parameter[96];
sscanf(argv[1U], "%x", &arg);
parameter[2] = (arg >> 0U) & 0xFF;
parameter[1] = (arg >> 8U) & 0xFF;
parameter[0] = (arg >> 16U) & 0xFF;

aber ausgeben wie meinen buffer kann ichd as leider unten nicht
Code:
debugfile.open ("/root/cprog/debug.bin",ios::binary);
debugfile.write(parameter,3);
debugfile.close();

da krieg ich nen compiler-fehler
sample.cpp: In function 'int main(int, char**)':
sample.cpp:57:28: error: invalid conversion from 'unsigned char*' to 'const char*' [-fpermissive]
/usr/include/c++/4.6/bits/ostream.tcc:184:5: error: initializing argument 1 of 'std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::write(const _CharT*, std::streamsize) [with _CharT = char, _Traits = std::char_traits<char>, std::streamsize = int]' [-fpermissive]

kann ich da nur const char ausgeben? und haba ber nen unsigned char? kann ich das konvertieren?
 
Zuletzt bearbeitet:
So in etwa:
Code:
char buffer[96];
for (int i = 0; i < 32; i++)
{
    unsigned int arg;
    sscanf(argv[1 + i], "%x", &arg);
    buffer[(i * 3) + 0] = (arg >> 16U) & 0xFFU;
    buffer[(i * 3) + 1] = (arg >> 8U) & 0xFFU;
    buffer[(i * 3) + 2] = (arg >> 0U) & 0xFFU;
}

ofstream myfile; // Dateistream anlegen
myfile.open ("/dev/spidev0.0",ios::binary); // Datei bzw Device öffnen
myfile.write(buffer,96); // Daten schreiben
myfile.close(); // kann auch nicht schaden :)

// Programmende
cout << "... the end!" << endl;
return 0;

EDIT: Du kannst die Variable "buffer" bzw. "parameter" ruhig auch als char lassen, dann ist der Kompilerfehler weg. Bei den Bitoperationen (Bitshift, Maskierung) habe ich jedoch lieber unsigned Datentypen, da diese ein definiertes Verhalten bei diesen Operationen aufweisen.

EDIT: Ich hab noch einen Fehler bei der "sscanf" Anweisung korrigiert. Beachte jedoch, dass du jetzt wirklich 32 Übergabeparameter benötigst. Man kann das ganze auch dynamisch machen, so dass nur die Anzahl der übergebenen Parameter auch wirklich verwendet wird:
Code:
char* buffer = new char[(argc - 1) * 3U];
for (int i = 0; i < (argc - 1); i++)
{
    unsigned int arg;
    sscanf(argv[1 + i], "%x", &arg);
    buffer[(i * 3) + 0] = (arg >> 16U) & 0xFFU;
    buffer[(i * 3) + 1] = (arg >> 8U) & 0xFFU;
    buffer[(i * 3) + 2] = (arg >> 0U) & 0xFFU;
}

ofstream myfile; // Dateistream anlegen
myfile.open ("/dev/spidev0.0",ios::binary); // Datei bzw Device öffnen
myfile.write(buffer, (argc - 1) * 3U); // Daten schreiben
myfile.close(); // kann auch nicht schaden :)

delete[] buffer;

// Programmende
cout << "... the end!" << endl;
return 0;
 
Zuletzt bearbeitet:
ok, cool, das geht soweit ... jetzt braucht nur noch jede LED nen eigenen parameter. Weisst du was ich damit meine? aktuell geht "programm 00FF00" und alle LEDs leuchten grün (R G B). d.h. er schreibt aktuell

00FF0000FF0000FF0000FF0000FF0000FF0000FF0000FF0000FF0000FF0000FF0000FF0000FF0000FF0000FF0000FF0000FF0000FF0000FF0000FF0000FF0000FF0000FF0000FF0000FF0000FF0000FF0000FF0000FF0000FF0000FF0000FF00

das is 32 mal "00FF00"

:)
 
Siehe mein letztes Edit im Post darüber.

EDIT: Die folgende Version würde bei weniger als 32 Parametern die letzte Farbe einfach für alle weiteren LEDs wiederholen:
Code:
char buffer[96];
for (int i = 0; i < 32; i++)
{
    unsigned int arg;
    sscanf(argv[1 + ((i > (argc - 1))? (argc - 1) : i)], "%x", &arg);
    buffer[(i * 3) + 0] = (arg >> 16U) & 0xFFU;
    buffer[(i * 3) + 1] = (arg >> 8U) & 0xFFU;
    buffer[(i * 3) + 2] = (arg >> 0U) & 0xFFU;
}

ofstream myfile; // Dateistream anlegen
myfile.open ("/dev/spidev0.0",ios::binary); // Datei bzw Device öffnen
myfile.write(buffer, 96U); // Daten schreiben
myfile.close(); // kann auch nicht schaden :)

// Programmende
cout << "... the end!" << endl;
return 0;
 
Zuletzt bearbeitet:
hmm, ne, 32 parameter is schon gut ... das einzige was ich mir noch vorstellen kann: die anzahl der parameter um einen erweitern und den ersten nehmen als wählparameter -> wenn 0 dann nimm den ersten für alle und wenn 1 dann erwartet er wirklich nochmal 32 stk
 
du bist echt genial!!! Vielen vielen dank!!! Es geht so ziemlich genau so wie ich es mir vorgestellt habe!!! Sonntag ist gerettet!

ich bin grad verwirrt .... ich hatte nochmal was getestet, den Code dann wieder rausgeworfen und kann ichs zwar wieder normal kompilieren, aber nicht mehr ausführen ... "Speicherzugriffsfehler"?!
folgendes geht noch ->
Code:
char* buffer = new char[(argc - 1) * 3U];
for (int i = 0; i < (argc - 1); i++)
{
    unsigned int arg;
    sscanf(argv[1 + i], "%x", &arg);
    buffer[(i * 3) + 0] = (arg >> 16U) & 0xFFU;
    buffer[(i * 3) + 1] = (arg >> 8U) & 0xFFU;
    buffer[(i * 3) + 2] = (arg >> 0U) & 0xFFU;
}
 
ofstream myfile; // Dateistream anlegen
myfile.open ("/dev/spidev0.0",ios::binary); // Datei bzw Device öffnen
myfile.write(buffer, (argc - 1) * 3U); // Daten schreiben
myfile.close(); // kann auch nicht schaden :)
 
delete[] buffer;
 
// Programmende
cout << "... the end!" << endl;
return 0;

aber das letzte geht nicht mehr :( also das wo die letzte Farbe in alle weiteren schreibt :(
 
Zuletzt bearbeitet:
Das war mit dem ungetestet gemeint ;)

Ich hab jetzt schnell ein Visual C++ Projekt aufgesetzt und den Fehler mal entfernt und die Lesbarkeit ein bisschen verbessert (weniger +1 und -1 Operationen):

Code:
char buffer[96];
int count = argc - 1;
if (count > 0)
{
	int j = 0; 
	for (int i = 1; i <= 32; i++)
	{
		unsigned int arg;
		sscanf(argv[(i > count)? count : i], "%x", &arg);
		buffer[(j * 3) + 0] = (arg >> 16U) & 0xFFU;
		buffer[(j * 3) + 1] = (arg >> 8U) & 0xFFU;
		buffer[(j * 3) + 2] = (arg >> 0U) & 0xFFU;
		j++;
	}
     
	ofstream myfile; // Dateistream anlegen
	myfile.open ("/dev/spidev0.0",ios::binary); // Datei bzw Device öffnen
	myfile.write(buffer, 96U); // Daten schreiben
	myfile.close(); // kann auch nicht schaden :)

	// Programmende
	cout << "... the end!" << endl;
}
else
{
	cout << "to few arguments" << endl;
}
 
Zuletzt bearbeitet:
Funktioniert top :D Danke!!!!!!!!

eventuell muss ich es noch um einige Funktionen erweitern ... wenn ich da wieder feststecke dann meld ich mich hier wieder ;)
 
Zuletzt bearbeitet:
Zurück
Oben