Forum: PC-Programmierung C++ zeigt in der Ausgabe nichts an


von Stephan (Gast)


Lesenswert?

Nabend,
ich möchte ein Programm schreiben, in dem ich ermittle, wie oft der 
Montag der 1.,2.,3.,.... Dienstag der1.,2.,... usw. war.
1
#include <stdio.h>
2
#include <time.h>
3
4
5
int main(void) {
6
    char *wday[] = { "Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag", "???" };
7
    struct tm ts;
8
    //int auswertung[7][31];
9
    int year, month, day;
10
 
11
  for(year=2000; year<=2015; year++){
12
    for(month=1; month<=12; month++){
13
      for(day=1; day<=31; day++){
14
        ts.tm_year = year - 1900;
15
        ts.tm_mon  = month - 1;
16
          ts.tm_mday = day;
17
          if ( mktime(&ts) == -1 )
18
            ts.tm_wday = 7;
19
            if(wday[ts.tm_wday]!="???"){
20
              printf("%s, %d, %d\n",wday[ts.tm_wday],ts.tm_wday,day);
21
          }
22
          
23
      }
24
    }
25
  }
26
  return 0;
27
}

bisher lasse ich mir die Tage und Datums in der Konsole ausgeben.
Um mein eigentliches Vorhaben zu machen, wollte ich eine Matrix 
schreiben (7x32)- Damit habe ich jede kombination gegeben und kann in 
jedem Feld den wert erhöhen.

das Problem ist, sobald ich die Zeile
1
int auswertung[7][31];
auskommentiere, wird mir in der Konsole nichts mehr angezeigt.
Woran liegt das? Das macht für mich keinen sinn.

Stephan

von Tom (Gast)


Lesenswert?

blubb.c:19:32: warning: comparison with string literal results in 
unspecified behavior [-Waddress]

von Peter II (Gast)


Lesenswert?

Stephan schrieb:
> Woran liegt das?

kann ich nicht sagen, aber
1
wday[ts.tm_wday]!="???"){

ein vergleich mit char* kann man so nicht machen, prüfe lieber vorher ob 
ts.tm_wday zwischen 0 und 6 liegt.

von Stephan (Gast)


Lesenswert?

Wieso kann ich das nicht machne? ich vergleiche doch nur zwei strings 
miteinander, oder nicht?
Habe es trotzdem geändert. Dennoch bleibt das Problem das selbe.

von Peter II (Gast)


Lesenswert?

Stephan schrieb:
> Wieso kann ich das nicht machne? ich vergleiche doch nur zwei strings
> miteinander, oder nicht?

char* ist aber kein String sondern ein Array und Arrays kann man (so) 
nicht vergleichen.

von Peter II (Gast)


Lesenswert?

Peter II schrieb:
> char* ist aber kein String sondern ein Array und Arrays kann man (so)
> nicht vergleichen.

genauer gesagt ist es ein pointer (nicht das sich jemand an Array stört)

von g457 (Gast)


Lesenswert?

> char* ist aber kein String sondern ein Array und Arrays kann man (so)
> nicht vergleichen.

Nö, char* ist ein Zeiger, und der Compiler warnt zu Recht davor, 
selbigen Zeiger mit der ∗Adresse∗ eines String-Literals zu vergleichen.

von Yalu X. (yalu) (Moderator)


Lesenswert?

Stephan schrieb:
> Habe es trotzdem geändert. Dennoch bleibt das Problem das selbe.

Auch den Elemente tm_hour, tm_min und tm_sec in ts solltest du sinnvolle
Werte zuweisen (im einfachsten Fall 0). Lediglich tm_wday, tm_yday und
tm_isdst kannst du uninitialisiert lassen, da sie von mktime berechnet
werden.

Edit:

tm_isdst musst du ebenfalls initialisieren (s. Man-Page von mktime).

: Bearbeitet durch Moderator
von Stephan (Gast)


Lesenswert?

Schreibe es jetzt in eine textdatei. das funktioniert auch soweit. Das 
Problem was ich jetzt habe, dass ich nicht weiss, wie ich überprüfen 
kann, ob der Tag überhaupt existiert hat. Momentan spuckt er mir aus, 
dass der 29.Februar2014 ein Samstag war und zählt diesen mit. 
(30.Februar2014->Sonntag, 31.Februar2014->Montag).

kann ich auch irgendwie kontrollieren, ob dieser Tag überhaupt existiert 
hat?
1
#include <fstream>
2
#include <iostream>
3
#include <string>
4
#include <stdio.h>
5
#include <time.h>
6
7
using namespace std;
8
9
#define numwdays 7
10
#define numdays 31
11
12
int main(void) {
13
    char *wday[] = { "Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag"};
14
    int x=0;
15
    struct tm ts;
16
    int auswertung[numdays][numwdays];
17
    for(int k=0; k<numdays; k++){
18
      for(int l=0; l<numwdays; l++){
19
        auswertung[k][l] = 0;
20
    }
21
  }
22
  ts.tm_hour = 0;
23
    ts.tm_min  = 0;
24
    ts.tm_sec  = 1;
25
    ts.tm_isdst = -1;
26
    
27
  for(int year=2014; year<2015; year++){
28
    for(int month=2; month<=2; month++){
29
      for(int day=1; day<=31; day++){
30
        ts.tm_year = year-1900;
31
        ts.tm_mon  = month-1;
32
          ts.tm_mday = day;
33
          
34
          if ( mktime(&ts) == -1 ){
35
            ts.tm_wday = 7;
36
        }
37
        printf("Dieser Tag ist ein %s\n", wday[ts.tm_wday]);    
38
        
39
          if(ts.tm_wday>=0 && ts.tm_wday<=6){
40
            auswertung[ts.tm_mday-1][ts.tm_wday] = auswertung[ts.tm_mday-1][ts.tm_wday] + 1;
41
            x = x + 1;
42
          }
43
        }
44
    }
45
  }
46
  
47
  ofstream f("text.txt");
48
  for(int m=0;  m<numdays; m++){
49
    for(int n=0; n<numwdays; n++){
50
      //printf("%-9d", auswertung[m][n]);
51
      f <<  auswertung[m][n];
52
      f << "   ";
53
    }
54
    f << ("\n");
55
  }
56
  f << x;
57
  f.close();
58
  return 0;
59
}

von Dirk B. (dirkb2)


Lesenswert?

Stephan schrieb:
> kann ich auch irgendwie kontrollieren, ob dieser Tag überhaupt existiert
> hat?

Vergleiche nach dem mktime,  ob die Werte in ts dieselben sind, die du 
vorher rein geschrieben hast.

Zu deinem ersten Problem.
Es gibt in C eine feste Adresse, die man für ungültige Adressen 
verwendet: NULL
1
    char *wday[] = { "Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag", NULL};
2
...
3
            if(wday[ts.tm_wday] != NULL){
Allerdings ist in diesem Fall die Version mit dem Vergleich von 
ts.tm_wday < 7 besser.

Und das
1
printf("Dieser Tag ist ein %s\n", wday[ts.tm_wday]);
 muss mit in das nachfolgende if rein.

von Stephan (Gast)


Lesenswert?

mhh,
habe es jetzt so gemacht, dass ich mir die Tage in einem Monat aus einer 
Funktion geben lasse und die for-Schleife für die Tage nur bis dahin 
laufen lass.
1
#include <fstream>
2
#include <iostream>
3
#include <string>
4
#include <stdio.h>
5
#include <time.h>
6
7
using namespace std;
8
9
#define numwdays 7
10
#define numdays 31
11
12
13
int getDaysInMonth(int month, int year);
14
15
16
17
int main(void) {
18
    char *wday[] = { "Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag", NULL};
19
    int x=0;
20
    int daysInMonth=0;
21
    struct tm ts;
22
    int auswertung[numdays][numwdays];
23
    for(int k=0; k<numdays; k++){
24
      for(int l=0; l<numwdays; l++){
25
        auswertung[k][l] = 0;
26
    }
27
  }
28
  ts.tm_hour = 0;
29
    ts.tm_min  = 0;
30
    ts.tm_sec  = 1;
31
    ts.tm_isdst = -1;
32
    
33
  for(int year=2015; year<=2015; year++){
34
    for(int month=2; month<=2; month++){
35
      daysInMonth = getDaysInMonth(month, year);
36
      for(int day=1; day<=daysInMonth; day++){
37
        ts.tm_year = year-1900;
38
        ts.tm_mon  = month-1;
39
          ts.tm_mday = day;
40
          
41
          if (mktime(&ts) == -1 ){  
42
            ts.tm_wday = 7;
43
        }  
44
          if(ts.tm_wday>=0 && ts.tm_wday<=6){
45
            printf("Dieser Tag ist ein %s\n", wday[ts.tm_wday]);  
46
            auswertung[ts.tm_mday-1][ts.tm_wday] = auswertung[ts.tm_mday-1][ts.tm_wday] + 1;
47
            x = x + 1;
48
          }
49
        }
50
    }
51
  }  
52
  ofstream f("text.txt");
53
  for(int m=0;  m<numdays; m++){
54
    for(int n=0; n<numwdays; n++){
55
      f <<  auswertung[m][n];
56
      f << "   ";
57
    }
58
    f << ("\n");
59
  }
60
  printf("%d",x);
61
  f << x;
62
  f.close();
63
  return 0;
64
}
65
66
67
bool leapyear(int year){
68
  if ((year % 400) == 0)
69
    return true;
70
  else if ((year % 100) == 0)
71
    return false;
72
  else if ((year % 4) == 0)
73
    return true;
74
  return false;
75
}  
76
77
int getDaysInMonth(int month, int year){
78
  //                     ungült,Jan,Feb,Mrz,Apr,Mai,Jun,Jul,Aug,Sep,Okt,Nov,Dez
79
  int arrDaysInMonth[13] = {  0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
80
81
  if (month == 2){
82
    if (leapyear(year)) return 29;
83
    else return 28;
84
  }
85
  else return arrDaysInMonth[month];
86
}


das mit dem vergleichen hört sich aber besser an, habe ich aber nicht 
hinbekommen. Da muss ich erst noch mal ein bisschen probieren.

aber danke schon mal für eure Hilfe.

von Jonas B. (jibi)


Lesenswert?

>kann ich auch irgendwie kontrollieren, ob dieser Tag überhaupt existiert
> hat?

Ja, in dem du ermittelst ob das Jahr ein Schaltjahr war (wie man das 
programmiertechnisch macht, das kannst du googlen), in dem Falle gibt es 
halt den 29. Februar - ansonsten nicht.

Gruß J

: Bearbeitet durch User
von Dirk B. (dirkb2)


Lesenswert?

Ich würde nur für den ersten Tag mktime nehmen. den Rest dann selber aus 
der Tabelle, bzw. mit Schleifen errechnen.


Meist macht man  arrDaysInMonth ein 2D-Array:
1
int arrDaysInMonth[][13] = { {  0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
2
                             {  0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
3
                           };

Und das Post/Preincrement geht nicht nur in Schleifen.
Dann ist das
1
auswertung[ts.tm_mday-1][ts.tm_wday]++;
 auch besser lesbar.
1
auswertung[ts.tm_mday-1][ts.tm_wday] += 1;
 geht auch.


Und wenn du Arrays initialisierst, werden die nicht aufgeführten 
Elemente mit 0 besetzt
1
int auswertung[numdays][numwdays] = {0}; // Alles mit 0 besetzt
Sonst ist memset dein Freund.

: Bearbeitet durch User
von Dirk B. (dirkb2)


Lesenswert?

Dirk B. schrieb:
> Ich würde nur für den ersten Tag mktime nehmen.

Mit mktime kommst du (bei 32-Bit time_t) aber nur von ~1902 bis ~2038.

Dann kannst du Freitag, den 15. Oktober 1582 als Startpunkt nehmen. 
Davor war Donnerstag, der 4. Oktober.

von Jay (Gast)


Lesenswert?

Was soll den jetzt dieses Gemisch aus C und C++? Das macht es auch nicht 
besser. Ebensowenig irgendwelche besch... Code dranzukleben.

Oben wurde es schon mal erwähnt: HANDBUCH LESEN!


> The mktime() function modifies the fields of the tm structure as follows:
> tm_wday and tm_yday are set to values determined from the contents of the
> other fields; if structure members are outside their valid interval, they
> will be normalized (so that, for example, 40 October is changed into 9
> November); tm_isdst is set (regardless of its initial value) to a
> positive value or to 0, respectively, to indicate whether DST is or is
> not in effect at the specified time. Calling mktime() also sets the
> external variable tzname with information about the current timezone.

D.h. hat mktime() den Tag verändert, so gibt es das Datum nicht -> 
Ergebnis wegschmeißen.

Einfachster Test, wenn es nur darum geht den 29. (Schaltjahre), 30. und 
31. eines Monats in den Griff zu bekommen:
1
...
2
ts.tm_mday = day;
3
if((mktime(&ts) == -1) || (ts.tm_mday != day)){  
4
    // Den Tag gibt es nicht
5
}

von Eric B. (beric)


Lesenswert?

Jay schrieb:

> Oben wurde es schon mal erwähnt: HANDBUCH LESEN!
>
>> The mktime() function modifies the fields of the tm structure as follows:
>> tm_wday and tm_yday are set to values determined from the contents of the
>> other fields; if structure members are outside their valid interval, they
>> will be normalized (so that, for example, 40 October is changed into 9
>> November);
>
> D.h. hat mktime() den Tag verändert, so gibt es das Datum nicht ->
> Ergebnis wegschmeißen.

Nein, das heisst, eine einfache Schleife genügt:
1
heute = 1. Jan. 2000
2
WHILE heute != 1. Jan 2016
3
  wochentag = wochentag von heute
4
  tag = monatstag von heute
5
  trage (tag, wochentag) in resultat ein
6
  heute = heute + 1
7
  benutze mktime um heute zu normalisieren
8
END WHILE
9
10
zun schluss resultattabelle ausgeben

und damit sind alle Vorrichtungen um Schaltjahre und 28-, 29-, 30 oder 
31-Tagige Monate abzufangen hinfällig, weil mktime das alles 
übernimmt.

: Bearbeitet durch User
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.