Rückgabe von funktion.. (Pointer)

MC Breit

Erfahrenes Mitglied
Hi!

Ich hab mri gerade eine funktion basename geschrieben, jetzt hab ich aber ein problem, und zwar will ich mein ergebniss ja auch wieder weiterverarbeiten ;)

Am besten währe in der praxis der aufruf alla
char *dir=argv[0];
basename(filename, dir);
prinft("Name der datei: %s", filename);

Ich habe es jetzt multiple versucht, wie es im buch stand mit dem *, und ohne, und mit festgelegter stringlänge, einen char basename() aus der funktion zu machen, aber alles hat nicht so richtig geklappt, was bedeutet entweder bekomm ich making integer from pointer while passing arguments, oder die exe strützt später ab, bzw verursacht einen fehler.

Wenn ihr mir villeicht erklähren könntet, wie das geht, währe ich sehr dankbar.
Meine funktion sieht so aus:
Code:
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>

void basename(char *path)
{
  char res[500], cache[500];
  int pos=0, len=0;

  //String lenght..
  len = strlen(path);
  len--;
  
  //Put first character to cache
  sprintf(cache, "%c", path[len]);
  len--;
  
  //Cache chars while matching first backslash..
  for(pos=len; pos>=0; pos--)
  {
    if( path[pos] == '\\' )
    {
      break;
    }
    sprintf(cache, "%s%c", cache, path[pos]);
  }
  
  //Reverse result..
  len = strlen(cache);
  len--;
  sprintf(res, "%c", cache[len]);
  len--;
  for(pos=len; pos>=0; pos--)
  {
    sprintf(res, "%s%c", res, cache[pos]);
  }
  
  //return res;
}
     
int main(int argc, char *argv[])
{
  char php_path[800], *file_to_run, *dir;

  //Get the path to php (*php_path)..
  GetPrivateProfileString("settings", "php_path", "C:\\php4\\php.exe", php_path, 800, "D:\\Programming\\TeamOrga\\dev\\win-remote\\config.ini");

  dir = argv[0];

  //Extract basename..
  basename(dir);
  printf("Basename: %s\n", dir);
  system("PAUSE");
  
  file_to_run = "D:\\Programming\\TeamOrga\\dev\\TeamOrga.php-gtk";
  
  ShellExecute(NULL, NULL, php_path, file_to_run, NULL, SW_HIDE);
  return 0;
}
 
Zuletzt bearbeitet:
Eine Funktion, die etwas zurückgibt, kann nicht vom Typ void sein. Wenn du tatsächlich einen char-Pointer zurückgeben willst, muss die Funktion so aussehen (aber lies erst unten, warum du es dennoch nicht tun solltest):
Code:
char test[] = "huhu";

char* basename(char *path)
{
  return test;
}

Zeiger oder Referenzen auf lokale Variablen darfst du aber auf keinen Fall zurückgeben. *) res und cache beispielsweise liegen auf dem Stack, solange die Funktion nicht verlassen wird. Sobald dies jedoch geschieht (nach dem return), werden sie freigeben. Der zurückgegebene Zeiger, der vorher noch auf res zeigte, ist nun ungültig. Er zeigt nun wahrscheinlich auf irgendwelchen Datenschrott (es kann natürlich sein, dass die alten Werte von res noch nicht überschrieben sind, aber das ist nur Zufall).

Die sichere Lösung ist, hier den Aufrufer der Funktion den Buffer für das Resultat übergeben zu lassen.
Code:
void basename(char *path, char* res_buffer, int res_size)
{
  // res_buffer und res_size prüfen!

  // ergebnis in buffer schreiben, beispiel
  strcpy( res_buffer, "Hallo" );
  // nix returnen
}  

int main()
{
  char ergebnis[500];
  char path[] = "test";
  basename( path, ergebnis, 500 );
  printf( ergebnis );
  ...
}

Wenn du allerdings C++ benutzt, könntest du vielleicht besser einen std::string zurückgeben.
Code:
#include <string>
...
using std::string;
...
string basename( ...  )
{
  string res = "huhu";
  return res; // kein problem, da eine KOPIE von res  
  // an den Aufrufer übergeben wird.
}


---
*) Es gibt ein paar Ausnahmefälle, in denen es sicher ist, zum Beispiel bei Zeigern auf statische Variablen.
 
Oke, danke!
Jetzt hab ich es verstanden ;)

Wenns jemand mal bruahcen sollte, hier die 2 funktionen basename und basedir, die extrahier entweder einen dateinamen oder einen pfad aus dem absoluten oder relativen pfad einer datei (zb argv[0])..
Code:
/*****
* basename - extrahiert einen dateinamen aus einer pfadangaben
* der pfad kann absout oder relativ (mit führendem ./) sein.
*/

void basename(char *path, char *buffer, int buffer_size)
{
  char res[buffer_size], cache[buffer_size];
  int pos=0, len=0;

  //String lenght..
  len = strlen(path);
  len--;
  
  //Put first character to cache
  sprintf(cache, "%c", path[len]);
  len--;
  
  //Cache chars while matching first backslash..
  for(pos=len; pos>=0; pos--)
  {
    if( path[pos] == '\\' )
    {
      break;
    }
    sprintf(cache, "%s%c", cache, path[pos]);
  }
  
  //Reverse result..
  len = strlen(cache);
  len--;
  sprintf(res, "%c", cache[len]);
  len--;
  for(pos=len; pos>=0; pos--)
  {
    sprintf(res, "%s%c", res, cache[pos]);
  }
  
  //return result..
  strcpy(buffer, res);
}

/*****
* basedir - extrahiert den pfad aus einer pfadangabe.
* der pfad kann absout oder relativ (mit führendem ./) sein.
*/

void basedir(char *path, char *buffer, int buffer_size)
{
  char res[buffer_size], cache[buffer_size], xbasename[buffer_size]; 
  int pos=0, len=0;
  
  //Get basename
  basename(path, xbasename, buffer_size);
  
  //Length of path..
  len = strlen(path)-strlen(xbasename);
  //Put firs character to res..
  sprintf(res, "%c%", path[0]);
  //Cache chars to lenght of path..
  for(pos=1;pos<len;pos++)
  {
    sprintf(res, "%s%c", res, path[pos]);
  }
  
  
  //return result..
  strcpy(buffer, res);
  
}
 
Warum nimmst du nicht gleich den buffer (statt char res[])? Dann brauchst du am Ende nichts kopieren.
 
Zurück