Seite 1 von 1

Fehler im Programm ich komm nicht weiter

Verfasst: Di Feb 02, 2010 4:49 pm
von monkey
Hallo zusammen hab mich erst heute angemeldet und schon habe ich ein Problem bei dem ich nicht weiter komme.
Ich schreibe gerade ein Programm mit dem ich Notizen in der Konsole anzeigen und erstellen kann an sich nichts weltbewegendes, dennoch habe ich einen kleinen Fehler bei dem ich einfach nicht weiter komme. Ich will an eine Funktion ein char array übergeben das nach einem bestimmten Muster überprüft ob in dem Array bestimmte Zeichenketten existieren. Das Programm wird mit ein paar Warnungen kompiliert, aber wenn ich es ausführe kommt die Meldung Speicherzugriffsfehler. Ich hoffe ihr könnt mir weiter helfen.

Code: Alles auswählen

note_maker.c: In function ‘main’:
note_maker.c:47: warning: passing argument 1 of ‘getline’ from incompatible pointer type
note_maker.c: In function ‘check_trigger’:
note_maker.c:89: warning: passing argument 2 of ‘strcmp’ makes pointer from integer without a cast
note_maker.c:93: warning: passing argument 2 of ‘strcmp’ makes pointer from integer without a cast
note_maker.c:97: warning: passing argument 2 of ‘strcmp’ makes pointer from integer without a cast
note_maker.c:101: warning: passing argument 2 of ‘strcmp’ makes pointer from integer without a cast
P.S. Anscheinend wird der Quellcode nicht bei dem Beitrag angezeigt wenn ich einen Dateianhang hochlade. Also hier ist noch der Quellcode. Hat das Forum kein NOPASTE - Funktion?

Code: Alles auswählen

/*------------- Programm um Notizen zu speichern -----------*/
//-------------------------------------------------------------------------------
// Das Programm bietet vier Funktionen um mit den Notizen zu arbeiten.
// 1. Lese Funktion bei dem Trigger -r werden die ganzen Notizen angezeigt.
// 2. Schreibe Funktion bei dem Trigger -w wird die angegebene Notiz gespeichert.
// 3. Lösche Funktion bei dem Trigger -d wird die angegebene Notiz gelöscht.
// 4. Hilfe Funktion bei dem Trigger -h wird eine Übersicht sämtlicher Funktionen angezeigt.
#define _GNU_SOURCE
#include <stdlib.h>
#include <stdio.h>
#include <readline/readline.h>

#define FILE_NAME "/home/crap/.note_maker_save"
#define FILE_NAME_BACKUP "/home/crap/.note_macker_save_backup"

int check_trigger(int argc, char *argv);
void show_help();
void check_file();

int main(int argc, char *argv[])
{
  /*  Deklaration der einzelnen Variablen  */
  int trigger, counter = 1;
  const char var[] = "Notiz ";
  const char *buffer = NULL;
  const char *text_input;
  size_t length = 0;
  ssize_t text_output;

  /*  Sicherheitsprüfung   */
  trigger = check_trigger(argc, argv[1]);
  check_file();

  /*  Hauptteil des Programms   */
  if((argc > 0) || (argc < 2))
    {

      FILE *file_deskriptor;

      switch(trigger)
	{
	case 1:
	  /*   ANZEIGEN der Notizen   */
	  file_deskriptor = fopen(FILE_NAME, "r");
	  while(feof(file_deskriptor) == 0)
	    {
	      text_output = getline(&buffer, &length, file_deskriptor);
	      fprintf(stdout, "\n%d Notiz: %s", counter, text_output);
	      counter++;
	    }
	  break;
    
	case 2:
	  /*   SCHREIBEN der Notizen  */
	  file_deskriptor = fopen(FILE_NAME, "a");
	  text_input = readline("\nNotiz:\t");
	  fputs(text_input, file_deskriptor);
	  fclose(file_deskriptor);
	  break;
    
	case 3:
	  /*   LÖSCHEN der Notizen    */
	  
	  break;
    
	case 4:
	  /*   HILFE anzeigen         */
	  show_help();
	  break;
    
	default:
	  break;
	}
      fclose(file_deskriptor);
    }
  else
    {
      show_help();
    }
  return 0;
}

int check_trigger(int argc, char* argv)
{
  const char read[] = "-r";
  const char write[] = "-w";
  const char delete[] = "-d";
  const char help[] = "-h";
  if(strcmp(read, argv[1]) == 0)
    {
      return 1;
    }
  else if(strcmp(write, argv[1]) == 0)
    {
      return 2;
    }
  else if(strcmp(delete, argv[1]) == 0)
    {
      return 3;
    }
  else if(strcmp(help, argv[1]) == 0)
    {
      return 4;
    }
  else
    {
      return 0;
    }
}

void show_help()
{
  printf("\n\n\tnote_maker");
  printf("\n\t-r\t\t\tAnzeigen der Notizen.");
  printf("\n\t-w\t\t\tSpeicher der angegebenen Notiz.");
  printf("\n\t-d\t\t\tLöschen der angegebenen Notiz.");
  printf("\n\t-h\t\t\tDiesen Hilfetext anzeigen.");
}

void check_file()
{
  FILE *var;
  
  /*checke ob FILE_NAME vorhanden ist*/
  var = fopen(FILE_NAME, "r");
  if(var == NULL)
    {
      fclose(var);
      var = fopen(FILE_NAME, "a");
      fclose(var);
    }
  else
    {
      fclose(var);
    }
  
  /*checke ob FILE_NAME_BACKUP vorhanden ist*/
  var = fopen(FILE_NAME_BACKUP, "r");
  if(var == NULL)
    {
      fclose(var);
      var = fopen(FILE_NAME_BACKUP, "a");
      fclose(var);
    }
  else
    {
      fclose(var);
    }
}

Re: Fehler im Programm ich komm nicht weiter

Verfasst: Di Feb 02, 2010 4:58 pm
von cloidnerux
note_maker.c:47: warning: passing argument 1 of ‘getline’ from incompatible pointer type
An der Stelle rufst du getline auf:

Code: Alles auswählen

text_output = getline(&buffer, &length, file_deskriptor);
Du hast aber vergessen, das "buffer" schon ein Pointer ist, daher warnt dich der Compiler.
note_maker.c:89: warning: passing argument 2 of ‘strcmp’ makes pointer from integer without a cast

Code: Alles auswählen

if(strcmp(read, argv[1]) == 0)
strcmp will zwei Pointer auf strings haben, argv[1] ist aber nur ein char, daher muss du es wenn schon so aufrufen:

Code: Alles auswählen

if(strcmp(read, &argv[1]) == 0)
MfG cloidnerux.

p.s: Willkomen im Forum

Re: Fehler im Programm ich komm nicht weiter

Verfasst: Di Feb 02, 2010 5:43 pm
von Kerli
Hallo, von mir auch noch ein Willkommen!

Das meiste hat cloidnerux eh schon gesagt, aber
monkey hat geschrieben:Das Programm wird mit ein paar Warnungen kompiliert,
Warnungen sollte man prinzipiell nicht ignorieren, außer man weiß ganz genau was man tut. Und am Besten auch dann nicht ;)
monkey hat geschrieben:P.S. Anscheinend wird der Quellcode nicht bei dem Beitrag angezeigt wenn ich einen Dateianhang hochlade. Also hier ist noch der Quellcode. Hat das Forum kein NOPASTE - Funktion?
Nein, bist jetzt haben die Code Tags immer ausgereicht :P

Re: Fehler im Programm ich komm nicht weiter

Verfasst: Mi Feb 03, 2010 8:51 pm
von monkey
Jetzt habe ich das endlich verstanden das ich für die Funktion getline() erst Speicher anfordern muss. Aber wenn ich mir das Beispiel aus der Manpage von getline() anschaue habe wurde getline mit einem einfachen Zeiger verwendet und bei dem Aufruf wurde einfach die Adresse übergeben. Nichts desto trotz läuft das Programm immer noch nicht wie ich es haben wollte. Habe es durch den gdb gejagt und der sagt mit das ein Fehler bei strcmp auftritt obwohl es doch eigentlich so funktionieren müsste. Ich hoffe könnt mir auch bei diesem Problem weiter helfen.

Code: Alles auswählen

/*------------- Programm um Notizen zu speichern -----------*/
//-------------------------------------------------------------------------------
// Das Programm bietet vier Funktionen um mit den Notizen zu arbeiten.
// 1. Lese Funktion bei dem Trigger -r werden die ganzen Notizen angezeigt.
// 2. Schreibe Funktion bei dem Trigger -w wird die angegebene Notiz gespeichert.
// 3. Lösche Funktion bei dem Trigger -d wird die angegebene Notiz gelöscht.
// 4. Hilfe Funktion bei dem Trigger -h wird eine Übersicht sämtlicher Funktionen angezeigt.
#define _GNU_SOURCE
#include <stdlib.h>
#include <stdio.h>
#include <readline/readline.h>

#define FILE_NAME "/home/crap/.note_maker_save"
#define FILE_NAME_BACKUP "/home/crap/.note_macker_save_backup"

int check_trigger(int argc, char *argv);
void show_help();
void check_file();

int main(int argc, char *argv[])
{
  /*  Deklaration der einzelnen Variablen  */
  int trigger, counter = 1;
  const char var[6] = "Notiz ";
  char **buffer = (char **) malloc(sizeof(char *)); //Speicher anfordern für den Buffer
  *buffer = NULL;
  char *text_input;
  size_t length = 0;
  ssize_t text_output;

  /*  Sicherheitsprüfung   */
  trigger = check_trigger(argc, argv[1]);
  check_file();

  /*  Hauptteil des Programms   */
  if((argc > 0) || (argc < 2))
    {

      FILE *file_deskriptor;

      switch(trigger)
	{
	case 1:
	  /*   ANZEIGEN der Notizen   */
	  file_deskriptor = fopen(FILE_NAME, "r");
	  while(feof(file_deskriptor) == 0)
	    {
	      text_output = getline(buffer,&length, file_deskriptor);
	      fprintf(stdout, "\n%d Notiz: %s", counter, buffer);
	      counter++;
	    }
	  free(buffer);
	  break;
    
	case 2:
	  /*   SCHREIBEN der Notizen  */
	  file_deskriptor = fopen(FILE_NAME, "a");
	  text_input = readline("\nNotiz:\t");
	  fputs(text_input, file_deskriptor);
	  fclose(file_deskriptor);
	  break;
    
	case 3:
	  /*   LÖSCHEN der Notizen    */
	  
	  break;
    
	case 4:
	  /*   HILFE anzeigen         */
	  show_help();
	  break;
    
	default:
	  break;
	}
      fclose(file_deskriptor);
    }
  else
    {
      show_help();
    }
  return 0;
}


int check_trigger(int argc, char* argv)
{
  const char read[] = "-r";
  const char write[] = "-w";
  const char delete[] = "-d";
  const char help[] = "-h";
  if(strcmp(read, &argv[1]) == 0)
    {
      return 1;
    }
  else if(strcmp(write, &argv[1]) == 0)
    {
      return 2;
    }
  else if(strcmp(delete, &argv[1]) == 0)
    {
      return 3;
    }
  else if(strcmp(help, &argv[1]) == 0)
    {
      return 4;
    }
  else
    {
      return 0;
    }
}

void show_help()
{
  printf("\n\n\tnote_maker");
  printf("\n\t-r\t\t\tAnzeigen der Notizen.");
  printf("\n\t-w\t\t\tSpeicher der angegebenen Notiz.");
  printf("\n\t-d\t\t\tLöschen der angegebenen Notiz.");
  printf("\n\t-h\t\t\tDiesen Hilfetext anzeigen.");
}

void check_file()
{
  FILE *var;
  
  /*checke ob FILE_NAME vorhanden ist*/
  var = fopen(FILE_NAME, "r");
  if(var == NULL)
    {
      fclose(var);
      var = fopen(FILE_NAME, "a");
      fclose(var);
    }
  else
    {
      fclose(var);
    }
  
  /*checke ob FILE_NAME_BACKUP vorhanden ist*/
  var = fopen(FILE_NAME_BACKUP, "r");
  if(var == NULL)
    {
      fclose(var);
      var = fopen(FILE_NAME_BACKUP, "a");
      fclose(var);
    }
  else
    {
      fclose(var);
    }
}

Re: Fehler im Programm ich komm nicht weiter

Verfasst: Mi Feb 03, 2010 9:52 pm
von Dirty Oerti
Aaalso. Es wäre auch mal wichtig zu wissen, WAS GENAU nicht geht. Bzw was alles geht.
Dann mal los:

Code: Alles auswählen

  const char var[6] = "Notiz ";
NEIN! Du brauchst Platz für 7 Zeichen. Du darfst '\0' nicht vergessen...
Das

Code: Alles auswählen

const char read[] = "-r";
ist besser. Zeichen zählen kann der Compiler für dich übernehmen.

Code: Alles auswählen

  char **buffer = (char **) malloc(sizeof(char *)); //Speicher anfordern für den Buffer
Was wird das? Soweit ich gesehen habe soll buffer als Speicherplatz für die Eingaben dienen, die du mit getline bekommen willst.
Dazu brauchst du pro einzulesendem Zeichen 1 Byte Speicher, du brauchst also ein Char-Array.

Was du hier tust ist folgendes:
Du definierst einen Zeiger (1) auf einen Zeiger (2) der auf ein CHAR (3) zeigt und forderst Speicher an, um den Zeiger (2) speichern zu können, hast aber keinen Speicher für dein(e) CHARs (3), was du eigentlich bräuchtest. (Zeiger 1 ist auf dem Stack gespeichert, um den musst du dich nicht kümmern)

Was du hier wohl eigentlich vorhattest:

Code: Alles auswählen

char *buffer = (char*) malloc(MAXIMAL_BUFFER_GRÖßE);
Als maximale Größe kannst du z.B. 512 nehmen, dann kann dein Benutzer maximal 511 Zeichen per getline eingeben. Mehr führt zu Problemen..


Weiter im Text:

Code: Alles auswählen

  if(strcmp(read, &argv[1]) == 0)
Das wird so nichts.
Schau dir am besten mal an, was argv hier überhaupt ist (eine andere Bezeichnung wäre klüger).
Das argv in der Funktion nennen wir mal ARGV, während argv in main argv bleibt.

argv (in main) ist ein Pointer auf ein Array von Pointern, die jeweils auf eigene CHAR-Arrays zeigen.
ARGV ist ein (!!!) Pointer auf ein Char-Array. Sprich ein Zeiger auf ein CHAR, dem beliebig viele CHARs folgen können.

Wenn du in deiner Funktion nun also

Code: Alles auswählen

ARGV[1]
schreibst, bekommst du damit den Wert des CHAR-Arrays an Position 1.
Schreibst du

Code: Alles auswählen

&ARGV[1]
dann bekommst du einen Zeiger auf die Position 1 im char-Array. (Also auf einen 32 Bit System einen 32 Bit Integer, dessen Wert nicht von dir beeinflussbar ist)

Wenn du also

Code: Alles auswählen

  if(strcmp(read, &argv[1]) == 0)
aufrufst, versucht strcmp einen Char-Array mit einem 32Bit-Integer zu vergleichen...das geht theoretisch...da ein Integer aber nicht Nullterminiert ist (sein letztes Byte ist nicht '\0'), vergleicht strcmp immer weiter...was zu bösen Fehlern führt.

So, jetzt besser erstmal aus (oder frag weiter), vllcht gehts ja dann?