- Sony MILC fényképezőgépcsalád
- Apple asztali gépek
- OLED TV topic
- Milyen TV-t vegyek?
- NVIDIA GeForce RTX 5080 / 5090 (GB203 / 202)
- Milyen notebookot vegyek?
- Újra instabilitásba futott a Raptor Lake generációt
- Iszonyatos mennyiségű hulladékkal járhat a Windows 10 terméktámogatásának vége
- Amazon Kindle
- Hobby elektronika
Új hozzászólás Aktív témák
-
Ereshkigal
őstag
Ha már pörög a topik...
Tud valaki ajánlani Windows alá konzolos interface library-t? Olyasmit, mint mondjuk az ncurses Linux alatt. A Win32 konzol apitól valami magasabb szintű cucc kéne. -
kovisoft
őstag
válasz
#90088192 #6095 üzenetére
Szerintem csak annyi a gond, hogy a data_read() egy függvény, aminek a visszatérési értékét (ill. ehhez hozzácsapva még biteket) akarod átadni a send_data_screen()-nek. Viszont hiányzik a "()", így ténylegesen nem hívod meg a data_read-et, hanem a függvény címét adod át. Próbáld meg így:
send_data_screen(data_read() | (BASE_ADDRESS_PIXEL << x%Display_pages));
-
#90088192
törölt tag
Hello Mindenkinek
Segítséget szeretnek kerni, falba ütköztem, de nem értem miért.
../screen.c: In function 'put_pixel':
../screen.c:128:35: error: invalid operands to binary | (have 'int (*)(void)' and 'int')
send_data_screen(data_read | (BASE_ADDRESS_PIXEL << x%Display_pages));Maga a probléma, amit addig értek(?), hogy nem lehet bináris műveletet elvégezni pointeren.
Azt nem értem miért lett az pointer
A program részletek amik relevánsak(Elnézést még nem kommenteltem az új szekciót mert nem működik):
int data_read(void)
{
int data_in;
DISPLAY_RS = 1;
DISPLAY_RW = 1;
DISPLAY_DATA_DIRECTION = 1;
DelayUs(Hardware_delay*2);
data_in = S_DATA_IN;
DelayUs(Hardware_delay*4);
DISPLAY_DATA_DIRECTION = 0;
return(data_in);
}
int send_data_screen (long int Data_out) //Sends Data to the Display hardware
{
if(Data_out<=(Dislpay_height/Display_pages)*(Display_width/2) ) //Checks is the data length is valid
{
DISPLAY_EN = 0; //Turns Display Off
DISPLAY_RS = 1; //Enables Data mode
DelayUs(Hardware_delay);
S_DATA_OUT = Data_out; //Insert Data to the hardware line
strobe_E(); //Turns Display On/off
DISPLAY_RS = 0; //Disables Data mode
}else{
return(1);
}
}
int put_pixel(int x, int y)
{
if(x>=0 && x<=63 && y>=0 && y<=127)
{
goto_xy(x/Display_pages,y);
send_data_screen(data_read | (BASE_ADDRESS_PIXEL << x%Display_pages));
}else{
return(1);
}
} -
kovisoft
őstag
válasz
dabadab #6092 üzenetére
Pont hogy akkor még akár jó is lehetne, mert ugyan a külső do...while-ra nincs szükség, de nem is okoz gondot, ha pontosan 1x lefut. És helyes for esetén egy while (i==999) feltétellel csak 1x futna le, mert mire ideér a vezérlés, az i értéke 1000 lesz, tehát kilép a do...while-ból.
Persze nyilván baromság így, írtam is, hogy fölösleges a do...while, csak arra akartam felhívni a figyelmét, hogy keveri az értékadást (=) és az egyenlőségvizsgálatot (==).
-
dabadab
titán
válasz
kovisoft #6091 üzenetére
amúgy sem jó, mert a feltételben a szimpla = jel nem egyenlőségvizsgálat, ami a dupla ==, hanem értékadás
És az még mindig nem lenne jó, mert a szükségesnek pont a fordítottja lenne - ugyanis az ott nem a kilépés feltétele, hanem az ismétlésés (vagyis akkor hagyja abba a do ... while-t, amikor az NEM igaz)
-
kovisoft
őstag
válasz
Gabesson #6089 üzenetére
1. A külső do...while-ra nincs szükség (amúgy sem jó, mert a feltételben a szimpla = jel értékadás, nem pedig egyenlőségvizsgálat, ami a dupla == lenne).
2. A belső for feltétele nem jó, mert itt is az i=999 feltételben a szimpla = értékadás. Amúgy sem egyenlőség, hanem <= vizsgálat kellene, és ha 3-jegyű számokat akarsz, akkor nem 0-tól, hanem 100-tól kellene indítani:
for (i=100; i<=999; i++)
3. A for után, de még a nyitó { előtt van egy pontosvessző, ez nem kell ide, emiatt üres a for belseje.
4. A végső feltételvizsgálat és a printf a for ciklus belsejében kellene, hiszen minden egyes i-t meg akarsz vizsgálni.
Szerk.: lassan gépeltem
-
axioma
veterán
válasz
Gabesson #6089 üzenetére
1. hasznald a kod formazast
2. a haromjegyu szamok 100-tol vannak nem 0-tol
3. miert van do es for ciklus is?
4. a for ciklus bentmaradasi feltetele sose teljesul, mert ott <= kene legyen, a while meg akilepesit sose eri el,(*) mivel nem noveled az i-t (na jo 1x de aztan visszaall)
+1. ilyenkor elso teszt hogy kiveszed az if-et, es ha me'g mindig nem ir ki semmit, akkor a kiirasig (feltetelig) el se jut -az nem tunt fel hogy nemcsak hogy nem ir ki, hanem nem is allt le? azt is figyeld
Egy picit kene szerintem nezegetned az alapveto vezerlesi szerkezetek helyes hasznalatat a tankonyvben, jegyzetben, vagy a neten. [Beirhatnank ide a megoldast de azzal nem jegyezned meg melyik miert nem volt jo.](*) Re 6092:
Igen, ezen en is gondolkoztam mert nem is neztem elsore hogy pont egy C-s topikban van egy algoritmikus(nak tuno) kerdes, nalam a hatultesztelos ciklus az kilepesi felteteleskent rogzult me'g pascal idokbol. De teny, tudhattam volna a while-bol hogy az is bennmaradasi, bocsanat a hibaert. Tehat kilep, es leall, csak a 0 nem felel meg a feltetelnek... -
Gabesson
csendes újonc
Sziasztok, eddig jutottam el, a program elindul, fut is hibaüzenet nélkül, csak nem ír ki semmit, nem látom hol rontottam el.
#include <stdio.h>
void main()
{
system("CHCP 1250"); system("CLS");
int szazasok, tizesek, egyesek, i, szam;
do {
for (i=0; i=999; i++); {
szazasok=i/100 ;
tizesek= i%100/10 ;
egyesek= i%10 ; }
}
while (i=999) ;
szam=szazasok*100+tizesek*10+egyesek;
if (szam==szazasok*szazasok*szazasok+tizesek*tizesek*tizesek+egyesek*egyesek*egyesek)
printf("%d ", szam);
}
%MCEPASTEBIN% -
-
kovisoft
őstag
válasz
Gabesson #6085 üzenetére
Egy for ciklussal mész i-vel 100-tól 999-ig. A számjegyeket pl. így kapod meg:
- szazasok = i/100, azaz a szám 100-zal maradékosan osztva
- tizesek = (i%100)/10, ahol i%100 levágja a százasokat, majd ezt osztjuk maradékosan 10-zel
- egyesek = i%10, ami levágja az egyesek fölötti részt -
Gabesson
csendes újonc
Sziasztok a mai digitális oktatásban kapott leckémnek egyszerűen nem tudok, hogy nekifogni. Ebben szeretnék segítséget kérni. A feladat így szól:
Készítsen programot, amely megkeresi és kiírja azokat a 10-es számrendszerbeli háromjegyű számokat, amelyeknek a számjegyeit köbre emelve és összeadva eredményül magát a számot kapjuk (Armstrong-féle számok). -
kovisoft
őstag
válasz
nucso02 #6081 üzenetére
Azt írod, 1 szolga - 1 mesterrel már megy. Elmondod, hogy mi a probléma több szolga esetén? Van hely az osztott memóriában mindegyik szolga pid-jének (pl. tömb)? Beírja ide a saját pid-jét induláskor mindegyik szolga (ill. kiveszi innen kilépéskor)? Szöveg beírása után el van küldve a signal az összes ide beregisztrált szolga pid-nek?
-
nucso02
csendes tag
Sziasztok!
C programozás beadandó feladatomban szeretnék egy kis segítséget kérni Tőletek.
A feladat a következő lenne:Irjon egy chat programot! (2 fo"! - kliens/szerver)
Valositsa meg osztott memoria hasznalataval.
Amikor adott signalt kap (pl. SIGHUP), akkor olvassa ki az uzenetet.
Egyebkent varjon a felhasznalotol szoveget.
Ha beir valamit a felhasznalo, akkor irja be az osztott memoriaba, es kuldjon signalt a partner processznek.
Ugyanabban osztott memoria szegmensben tarolja el a szignalozashoz szukseges pid-eket is!
A mester processz legyen az ami hamarabb indul, ez hozza letre az osztott memoria szegmenst, illetve ez fogja megszuntetni is.
A szolga processzek(bármennyi lehet) pedig csak hasznalják az osztott memoriat.1szolga-1mesterrel már született megoldás, viszont a bármennyi szolga kifog rajtunk.
Minden megoldás/tipp sokat segítene, és nem lennék hálátlan
Köszönöm előre is! -
#90088192
törölt tag
válasz
#90088192 #6079 üzenetére
Megvan a probléma, igen érdekes Hardvere jellegű, azt gondoltam valami hülyeséget csináltam a karakter kódolással. Nem
Ez a jó:
int strobe_E(void) //Turns enabling line off/on
{
DelayUs(10);
DISPLAY_EN = 1; //Turns Display On
DelayUs(10);
DISPLAY_EN = 0; //Turns Display Off
DelayUs(10);
}és ez a rossz:
int strobe_E(void) //Turns enabling line off/on
{
DelayUs(10);
DISPLAY_EN = 0; //Turns Display Off
DelayUs(10);
DISPLAY_EN = 1; //Turns Display On
DelayUs(10);
} -
#90088192
törölt tag
válasz
buherton #6075 üzenetére
Koszonom
Remélem erre gondoltálKülönben igen érdekes maga a probléma, a bal oldali képernyő gyakorlatilag túlcsordul(Módosítottam a kodon így is duplázza az oszlopokat, es elkezd a 0. oszlopba írni)
Maga a problémás részlet:
void write_char(int line_select, int y_offset, int charcater_code)
{ int x;
if(y_offset>=(Display_width/2) && y_offset<=Display_width-Font_width) //Check which side of the screen need to be activated
{
lcd_select(1); //if the offset is bigger than 63 than the right side
set_y(y_offset-Display_width/2); //Deducts the the half of the display size Set y
set_x(line_select); //Selects line of writing
for(x=(charcater_code-Font_offset)*Font_width; x<=((charcater_code-Font_offset)*Font_width)+Font_width; x++) //Decodes the character code and make sure the data is sent by 8 bits
{
send_data_screen(font6x8[x]); //Sends out the relevant section of the Array
}
} else if(y_offset<=(Display_width/2)-1 && y_offset>=0) {
lcd_select(0); //selects the left side of the screen
set_y(y_offset); //Set y
set_x(line_select); //Selects line of writing
for(x=(charcater_code-Font_offset)*Font_width; x<((charcater_code-Font_offset)*Font_width)+Font_width; x++) //Decodes the character code and make sure the data is sent by 8 bits
{if(y_offset+(x-(charcater_code-Font_offset)*Font_width)!=(Display_width/2)) //Checks if the character has reached the border of the 2 sides of the screen
{
send_data_screen(font6x8[x]);
}else{ //If the Character is belong to the right side
lcd_select(1); //If yes selects the the right side
set_y(0); // Resets the offset
set_x(line_select); //Selects line of writing
send_data_screen(font6x8[x]); //Sends out the relevant section of the Array
}
}
}
else
{
MEMBRANE_MUTE=1;
}
}Es az egesz en block
#include "font6x8.h"
#include "screen.h"
#include "membrane.h"
#define Font_width 6
#define Font_offset 32
#define Font_height 8
#define Display_width 128
#define Dislpay_height 64
#define Display_rows 8
//#define Font_type font6x8
void InitalizePorts_display(void)
{
S_DATA_OUT=0;
S_DATA_IN=0;
DISPLAY_Dir=0;
DISPLAY_CS1=1;
DISPLAY_CS2=1;
DISPLAY_RS=1;
DISPLAY_RW=0;
DISPLAY_EN=0;
/* Command port direction settings */
DISPLAY_CS1_Direction =0 ;
DISPLAY_CS2_Direction =0 ;
DISPLAY_RS_Direction =0 ;
DISPLAY_RW_Direction =0 ;
DISPLAY_EN_Direction =0 ;
DelayUs(100);
}
void lcd_select(int s)
{
if(s==0)
{
DISPLAY_CS1 = 1; //Selects Left side of the screen
DISPLAY_CS2 = 0; //Deselects Right side of the screen
DelayUs(15);
}else if(s==1)
{
DISPLAY_CS1 = 0; //Deselects Left side of the screen
DISPLAY_CS2 = 1; //Selects Right side of the screen
DelayUs(15);
}else{
DISPLAY_CS1 = 1; //Selects Left side of the screen
DISPLAY_CS2 = 1; //Selects Right side of the screen
DelayUs(15);
}
}
void strobe_E(void) //Turns enabling line off/on
{
DelayUs(5);
DISPLAY_EN = 0; //Turns Display Off
DelayUs(5);
DISPLAY_EN = 1; //Turns Display On
DelayUs(5);
}
void set_y(int y) //Set Y coordinate 0-63 on the active side of the screen
{
DISPLAY_RS = 0; //Sets Instruction mode
DelayUs(5);
S_DATA_OUT = (0b01000000+y); //Set Y coordinate
strobe_E();
}
void set_x(int x) //Select one of the 8 bit line out of the 8
{
if(x<=Display_rows-1 && x>=0) // Verify input parameter is in range
{
DelayUs(5);
DISPLAY_RS = 0; //Sets Instruction mode
DelayUs(5);
S_DATA_OUT = 0b10111000+x; //select the desired line from the 8 X 8bit lines
strobe_E();
}else{
MEMBRANE_MUTE=1;
}
}
void send_data_screen (long int Data) //Sends Data to the Display hardware
{
DISPLAY_RS = 1; //Enables Data mode
DelayUs(5);
S_DATA_OUT = Data; //Insert Data to the hardware line
strobe_E();
}
void dsp_on(void)
{
DISPLAY_RS = 0; //Instruction mode
DelayUs(2);
S_DATA_OUT = 0b00111111; //Turns display controller ON
DelayUs(2);
DISPLAY_EN = 1; //Turns Enable line ON
strobe_E();
}
void clr_scr (int Fill)
{
int x; int y;
lcd_select(2); //Select both side of the display for quicker action
for(y=0;y<=Display_rows-1;y++) //Loop for the rows
{
set_y(0); //Set y to 0
set_x(y); //Selects line of writing
for(x=0; x<(Display_width/2); x++) //Loop for the columns
{
send_data_screen(Fill);
}
}
}
void write_char(int line_select, int y_offset, int charcater_code)
{ int x;
if(y_offset>=(Display_width/2) && y_offset<=Display_width-Font_width) //Check which side of the screen need to be activated
{
lcd_select(1); //if the offset is bigger than 63 than the right side
set_y(y_offset-Display_width/2); //Deducts the the half of the display size Set y
set_x(line_select); //Selects line of writing
for(x=(charcater_code-Font_offset)*Font_width; x<=((charcater_code-Font_offset)*Font_width)+Font_width; x++) //Decodes the character code and make sure the data is sent by 8 bits
{
send_data_screen(font6x8[x]); //Sends out the relevant section of the Array
}
} else if(y_offset<=(Display_width/2)-1 && y_offset>=0) {
lcd_select(0); //selects the left side of the screen
set_y(y_offset); //Set y
set_x(line_select); //Selects line of writing
for(x=(charcater_code-Font_offset)*Font_width; x<((charcater_code-Font_offset)*Font_width)+Font_width; x++) //Decodes the character code and make sure the data is sent by 8 bits
{if(y_offset+(x-(charcater_code-Font_offset)*Font_width)!=(Display_width/2)) //Checks if the character has reached the border of the 2 sides of the screen
{
send_data_screen(font6x8[x]);
}else{ //If the Character is belong to the right side
lcd_select(1); //If yes selects the the right side
set_y(0); // Resets the offset
set_x(line_select); //Selects line of writing
send_data_screen(font6x8[x]); //Sends out the relevant section of the Array
}
}
}
else
{
MEMBRANE_MUTE=1;
}
}
void string_out(char* message, float variable, int line, int y_offset)
{
int Maximum_num_char= Display_width/Font_width; //Maximum number of characters what can be placed in one row
char test[Maximum_num_char],i=0,j;
char a[Maximum_num_char];
sprintf(a, "%s%f", message, variable);
while(a[i]!='\0') {test[i]=a[i]; i++;}
for(j=0;j<=i-1;j++) write_char(line,y_offset+j*Font_width,test[j]);
} -
kovisoft
őstag
válasz
csoki98 #6069 üzenetére
Úgy látom, nem kaptál erre itt választ, szerintem nem is nagyon fogja senki helyetted megírni (én legalábbis nem
), mert az oktatásnak pont az a lényege, hogy magadtól csináld meg, max ha eladkadsz, akkor szívesen segítünk. Ezért inkább csak gondolatébresztőnek felvázolnám egy lehetséges megoldás menetét:
- Létrehozol egy tömböt, ebbe fogod pakolni a fájlból beolvasott számokat. Itt kapásból gond lehet, ha tetszőlegesen nagy fájlod lehet, ekkor ugyanis dinamikusan kell a tömb méretét kezelni és a tömböt allokálni, de gondolom elfogadják azt is, ha szimplán egy fix és elég nagy méretű tömböt definiálsz (pl. int numbers[10000]).
- Megnyitod olvasásra a fájlt (fopen "r" módban), majd egy ciklussal soronként beolvasod a tartalmát. Minden egyes számot a beolvasás után át kell konvertálni egész típusra (a fájlban szövegesen van tárolva), de olvashatod fscanf-fel is (a "%d" formátumvezérlővel), ami rögtön egészre is konvertál. Olvasási módtól függően ügyelni kellhet a sorvége karakterek "lenyelésére". A számokat egyesével belerakod a tömbödbe a soron követhező pozícióba, ehhez kell egy indexváltozó, ami 0-ról indul és amit minden szám beolvasása után megnövelsz 1-gyel, amíg a fájl végére nem értél (azaz hibára fut az olvasás). A legvégén ez a változó mondja meg a tömbben lévő elemek darabszámát.
- A rendezést végezheted egy könyvtári függvénnyel is (qsort), de magad is írhatsz egy egyszerű buborékos rendezést. Ha kell, részletesen elmagyarázom a buborékos rendezés menetét is.
- A rendezés tehát helyben történt a tömbödben, ezt kell kiírni egy másik fájlba. Megnyitod írásra a kimeneti fájlt (fopen "w" módban), majd egy ciklussal mész a tömbbe került elemek darabszámáig, és fprintf-fel kiírod az aktuális számot a fájlba ("%d\n" formátumvezérlővel, ez egy sortörést is a szám után tesz).
- fclose-szal lezárod a megnyitott fájlokat és kész vagy. -
#90088192
törölt tag
Hello Mindenkinek
Lenne itt egy kis fennforgás és segítséget szeretnek kerni hozza, mert nem jutok dűlőre egymagamban.
A karakter kiíratás amikor elérkezik a határhoz(2X64 képpontból áll a kijelző, amiket külön kell kapcsolgatni, és 8 bit magas a "sor") akkor nem csak térfelet vált hanem nem is tudom mit csinál, kihagyja az első karakter, meg mintha csak egy oszlopnyi szemetet zúdítana a határvonalra
Ez lenne a problémás részlet(a font 6 szeles és 8 magas):
for(x=(charcater_code-32)*6; x<((charcater_code-32)*6)+7; x++) //Decodes the character code and make sure the data is sent by 8 bits
{if(y_offset+(x-(charcater_code-32)*6)<63) //Checks if the character has reached the border of the 2 sides of the screen
{
DISPLAY_RS = 1;
S_DATA_OUT = font6x8[x]; //Sends the data to the screen
strobe_E();
}else{ //If the Character is belong to the right side
lcd_select(1); //If yes selects the the right side
set_y(0); // Resets the offset
set_x(line_select);
DISPLAY_RS = 1;
S_DATA_OUT = font6x8[x]; //Sends the data to the screen
strobe_E();Ez lenne az egesz:
#include "font6x8.h"
#include "screen.h"
#include "membrane.h"
void InitalizePorts_display(void)
{
S_DATA_OUT=0;
S_DATA_IN=0;
DISPLAY_Dir=0;
DISPLAY_CS1=1;
DISPLAY_CS2=1;
DISPLAY_RS=1;
DISPLAY_RW=0;
DISPLAY_EN=0;
/* Command port direction settings */
DISPLAY_CS1_Direction =0 ;
DISPLAY_CS2_Direction =0 ;
DISPLAY_RS_Direction =0 ;
DISPLAY_RW_Direction =0 ;
DISPLAY_EN_Direction =0 ;
DelayUs(100);
}
void lcd_select(int s)
{
if(s==0)
{
DISPLAY_CS1 = 1; //Selects Left side of the screen
DISPLAY_CS2 = 0; //Deselects Right side of the screen
DelayUs(15);
}else if(s==1)
{
DISPLAY_CS1 = 0; //Deselects Left side of the screen
DISPLAY_CS2 = 1; //Selects Right side of the screen
DelayUs(15);
}else{
DISPLAY_CS1 = 1; //Selects Left side of the screen
DISPLAY_CS2 = 1; //Selects Right side of the screen
DelayUs(15);
}
}
void strobe_E(void) //Turns enabling line off/on
{
DelayUs(5);
DISPLAY_EN = 0; //Turns Display Off
DelayUs(5);
DISPLAY_EN = 1; //Turns Display On
DelayUs(5);
}
void set_y(int y) //Set Y coordinate 0-63 on the active side of the screen
{
DISPLAY_RS = 0; //Sets Instruction mode
DelayUs(5);
S_DATA_OUT = (0b01000000+y); //Set Y coordinate
strobe_E();
}
void set_x(int x) //Select one of the 8 bit line out of the 8
{
if(x<=7 && x>=0) // Verify input parameter is in range
{
DelayUs(5);
DISPLAY_RS = 0; //Sets Instruction mode
DelayUs(5);
S_DATA_OUT = 0b10111000+x; //select the desired line from the 8 X 8bit lines
strobe_E();
}else{
MEMBRANE_MUTE=1;
}
}
void dsp_on(void)
{
DISPLAY_RS = 0; //Instruction mode
DelayUs(2);
S_DATA_OUT = 0b00111111; //Turns display controller ON
DelayUs(2);
DISPLAY_EN = 1; //Turns Enable line ON
strobe_E();
}
void clr_scr (int Fill_)
{
int x; int y;
lcd_select(2); //Select both side of the display for quicker action
for(y=0;y<=7;y++)
{
set_y(0); //Set y to 0
set_x(y); //Selects line of writing
for(x=0; x<64; x++)
{
DISPLAY_RS = 1; //Turns Data mode ON
DelayUs(2);
S_DATA_OUT = Fill_; //Send data to the selected line
strobe_E();
}
}
}
void write_char(int line_select, int y_offset, int charcater_code)
{ int x;
if(y_offset>=64 && y_offset<=122) //Check which side of the screen need to be activated
{
lcd_select(1); //if the offset is bigger than 63 than the right side
set_y(y_offset-64); //Set y
set_x(line_select); //Selects line of writing
for(x=(charcater_code-32)*6; x<=((charcater_code-32)*6)+6; x++) //Decodes the character code and make sure the data is sent by 8 bits
{
DISPLAY_RS = 1;
S_DATA_OUT = font6x8[x];
strobe_E();
}
} else if(y_offset<=63 && y_offset>=0) {
lcd_select(0); //selects the left side of the screen
set_y(y_offset); //Set y
set_x(line_select); //Selects line of writing
for(x=(charcater_code-32)*6; x<((charcater_code-32)*6)+7; x++) //Decodes the character code and make sure the data is sent by 8 bits
{if(y_offset+(x-(charcater_code-32)*6)<63) //Checks if the character has reached the border of the 2 sides of the screen
{
DISPLAY_RS = 1;
S_DATA_OUT = font6x8[x]; //Sends the data to the screen
strobe_E();
}else{ //If the Character is belong to the right side
lcd_select(1); //If yes selects the the right side
set_y(0); // Resets the offset
set_x(line_select);
DISPLAY_RS = 1;
S_DATA_OUT = font6x8[x]; //Sends the data to the screen
strobe_E();
}
}
}
else
{
MEMBRANE_MUTE=1;
}
}
void string_out(char* message, float variable, char line, char y_offset)
{
char test[21],i=0,j;
char a[21];
sprintf(a, "%s%f", message, variable);
while(a[i]!='\0') {test[i]=a[i]; i++;}
for(j=0;j<=i-1;j++) write_char(line,y_offset+j*6,test[j]);
} -
buherton
őstag
válasz
Ereshkigal #6068 üzenetére
Igaz is meg nem is, mint a mesében. Fájlra lokális vagy globális lesz a függvény a static kulcsszóval. Szerintem jattila48 a lambda és társai gondolt, ami mint nyelvi elem hiányzik a C-ből. Ettől persze implementálható, ahogy az egéz C++-t. Most hirtelen nem találom ezt a könyvet, de arra emlékszem, hogy temérdek void* és -> volt benne
.
-
jattila48
aktív tag
válasz
Ereshkigal #6068 üzenetére
attól az még globális, abban az értelemben, hogy nem lokális. persze nem elérhető más tu-ból. De ha nagyon akarod, tekintsük kivételnek. A c-ben ettől még nincs lokális fv.
-
csoki98
tag
Üdv!
Teljes mértékben vakon vagyok C programozásban(meg ugy alapból is programozásban), viszont az egyik szabadon választható tárgyamban azt kaptuk feladatnak, hogy írjak programot egy fájlban( gondolom sima .txt) megadott számsorozat növekvő sorrendbe rendezésére. A rendezett számsort egy fájlba kell kiíratnom.
Ha esetleg tudna valaki nekem valamennyire elmagyarázva írni egy ilyen programot, azt nagyon meghálálnám! -
jattila48
aktív tag
válasz
borisz1994 #6064 üzenetére
Ahogy többen írták, deklarációra akkor van szükség, ha egy változót, függvényt, vagy típust előbb akarsz használni, mint ahogy definiálnád. Lokális változóknál nincs különbség, ott a deklaráció egyben helyfoglalással is jár. Főleg globális változók és körbe hivatkozások használatakor kell külön deklarálni, és defniálni. Globális változó deklarálása az extern kulcsszóval történik.Valamelyik fordítási egységben ennek definiáltnak kell lenni, a többi, rá hivatkozó TU-ban pedig extern-nel deklaráltnak kell lenni. Függény deklarációjánál extern kulcsszóra nincs szükség (bár megadható). C-ben a függvények mindig globálisak (nincs lokális fv. ellentétben néhány más programozási nyelvvel). Az előre deklarálást nem tudod elkerülni (program szöveg átrendezéssel), ha körbe hivatkozás van (pl. f fv. hívja g-t,ami hívja f-et). Ilyenkor valamelyiket mindenképp előre kell deklarálni (ezt hívják fv. prototipusnak), aminek a tényleges definícióját (a fv. kódját) csak a másik fv. definíciója után tudod megadni. Fontos eset még a struktúrák előre deklarálása. Ezt is a körbehivatkozás teszi szükségessé (pl. rekurzív adatszerkezetek), hasonlóan, ahogy fv.-ek esetén is. A struktúra definíciója hivatkozik B stuktúrára, ami szintén hivatkozik A-ra. Ekkor azonban a csak előre deklarált struktúra típus nem teljes értékű (hiszen még nem ismerjük a szerkezetét), ezért csak rá mutató pointer típus deklarálható a hivatkozó struktúrában. Az ilyen típust incomplete type-nak hívják.
-
#90088192
törölt tag
válasz
borisz1994 #6064 üzenetére
Hello,
Ha PIC32 is érdekel, akkor az alap hülyeségeken mar túl vagyok vele
-
borisz1994
csendes tag
-
kovisoft
őstag
válasz
borisz1994 #6061 üzenetére
Csak akkor kell külön deklarálnod a függvényt, ha hamarabb akarod használni, mint ahogy definiálva lenne vagy ha egy másik modulban van a tényleges definíció. Ellenkező esetben a definíció már maga a deklaráció is.
-
dabadab
titán
válasz
borisz1994 #6061 üzenetére
Igen, az deklaráció és alapvetően nem kell.
-
borisz1994
csendes tag
válasz
dabadab #6059 üzenetére
Köszönöm a válaszokat. Azt hiszem kezdem érteni. Mindenképp beleolvasok az ajánlott könyvbe hátha könnyebb megértenem.
A függvényeket a program elején dekralárni kell? Nekem ez jött még le abból a kevésből amin sikerült átrágnom magam.
Persze csak ha ez függvény deklaráció :)int pelda(int);
-
kovisoft
őstag
válasz
borisz1994 #6057 üzenetére
A többiek már leírták, hogy alapvetően jól fogalmaztad meg a deklaráció és definíció közötti különbséget, de a változóval kapcsolatos következtetésed nem helyes.A példádban az
int pelda=0;
és azint pelda;
egyaránt definíció, mindkettő lefoglal a változónak memóriát, a különbség köztük annyi, hogy az első ad is egy 0 kezdőértéket a változónak. Ennek a változónak a deklarációja ez lenne:extern int pelda;
Ez nem foglal le memóriát a változónak, csak annyit mond, hogy valahol máshol van definiálva egy pelda nevű változó, aminek int a típusa. A deklaráció tehát ahhoz kell, hogy az adott helyen tudj használni egy változót vagy függvényt, de valahol máshol kell majd definiálnod is azt. -
dabadab
titán
válasz
borisz1994 #6057 üzenetére
Benkő Tiborné - Benkő László - Tóth Bertalan : Programozzunk C nyelven! könyvet
Jézusmária
Inkább keress egy jó, érthető könyvet. Szerintem a klasszikus Kernighan-Ritchie "A C programozási nyelv" az elég jó (még ha az apád is lehetne), én annak idején abból tanultam.
Egyébként alapvetően megéretetted: a definíció az egy valaminek (változónak, függvénynek) a pontos leírása és ennek hatására a fordító meg is csinálja az ahhoz tartozó dolgokat (memóriát foglal a változónak, lefordítja a függvény kódját).
A deklaráció meg elmondja a fordítónak, hogy van itt ez az izé és ez tulajdonképpen ilyen típusú, de valahol máshol van leírva.Hogy mire jó?
Azt talán már tudod, hogy a C erősen típusos nyelv, vagyis a fordító mindig megnézi, hogy az a függvény vagy változó, amire hivatkozol, milyen típusú, mennyi és milyen típusú paramétere van - ha pedig olyasmire hivatkozol, amiről még nem hallott, akkor hibát dob.
Amíg az egész programod egy file-ban van, ez általában nem jelent áthidalhatatlan problémát, olyan sorrendbe rakod a definícókat, hogy ha B hivatkozik A-ra, akkor A előbb legyen a file-ban, mint B. De már itt is lehet komplikáció, hiszen mi van, ha az A függvény hívja a B-t a B meg az A-t? Ilyenkor jön jól a deklaráció, hogy az ember leírja a fordítónak, hogy "majd találsz egy B függvényt, ami így fog kinézni, hogy". Ettől a fordító megnyugszik és szépen lefordítja a dolgokat, ha az ellenőrzéseken amúgy átmegy (és majd a linker lesz az, aki kétségbeesik, ha a B definíciója nincs sehol
)
-
buherton
őstag
válasz
borisz1994 #6057 üzenetére
Nem egészen. Vagyis hát nem olyan triviális. Főleg a változóknál.
A deklaráció a fordítónak szól, vagyis ez ahhoz kell, hogy a fordító értelmezni tudja a leírtakat, de nincs közvetlen hatása a processzoron futó kódra. Azaz meg lehet írni a programot ezek nélkül, csak olvashatatlan lesz. A definíció a processzornak szól és enélkül nem futna úgy a programunk, ahogy szeretnék.
Kezdjük az egyszerűbbel a függvénnyel.
Ezek deklarációk:
extern void foo(void);
static int foo(int);
void foo(void);
bar(); // ez most nem függvényhívás, és ez most nagyon gonosz dolog tőlem
A fordítónak ezekkel jelzed, hogy ha talál egy ilyen szignatúrájú függvényhívást, amihez még nem találta meg a definíciót, akkor ne hasaljon el és a keywordnek megfelelően járjon el.Ezek definíciók:
void foo(void)
{}
static int foo(int)
{
return 0;
}
bar()
{
return 0;
}
Leírod, hogy mit csinál a függvény. Ezzel mondod meg, hogy mit csináljon a programod.Változók.
Ez deklaráció (nem is tudok többet ennél):
extern int;
Ugyanaz, mint a függvénynél.Ezek definíciók:
int foo;
static char foo;
Ugyanaz, mint a függvénynél.Egyébként igen, a deklaráció nem jár memóriafoglalással, a definíció jár. Viszont a deklaráció csak a láthatóságot növeli, semmi más plusz dolgot nem tud, nem befolyásolja a típust, élettartamot és a tárolási osztályt sem.
Az
int
mérete architektúra függő és alimits.h
-ban van meg a "mérete". Tipikusan 4 bájt. Ha jól emlékszem, akkor az AVR8 esetén 2 bájt méretűek. -
borisz1994
csendes tag
Sziasztok. Nemrég kezdtem el olvasni a Benkő Tiborné - Benkő László - Tóth Bertalan : Programozzunk C nyelven! könyvet. A könyv az elején felhívja a figyelmet a deklaráció és a definíció közti különbségre és arra is hogy a kezdők könnyen összekeverik a kettőt (teljesen jogosan
) Sajnos nem tudtam teljesen megérteni. Ha jól sejtem a lényegi különbség a memóriafoglalásban van.
Ha jól értem ez definíció:int pelda=0;
Ez értelemszerűen lefoglal valamekkora (2 byte?) memóriát.
Én a deklarációt úgy értelmeztem hogy ezzel adjuk meg egy név tulajdonságait (típus, láthatóság, tárolási osztály, élettartam) és nem jár memóriafoglalással.
Így kellene kinézzen?int pelda;
Kérem valaki világosítson fel hogy hol rontom el az értelmezést. Miért fontos a kettő közötti különbség? -
jattila48
aktív tag
válasz
#90088192 #6053 üzenetére
Alapvetően azzal kell tisztában lenni, hogy az #include-okkal beszúrt fájlok az őket beinklúdoló fájlokkal együtt egy fordítási egységet (translation unit TU) képeznek. Az #include egy direktíva, a C előfordítónak szól, és egyszerűen szöveg-szinten beszúrja az inklúdolt fájlt. Tehát olyam, mintha copy-pastéval bemásolnád a fájlt. Ezért az inklúdokban nem lehet körbe hivatkozás (a.h inklúdolja b.h-t, ami inklúdolja a.h-t), és nem lehet többször inklúdolni ugyanazt a fájlt (mert ekkor keletkezik a többszörös defínició). Az utóbbi elkerülésére az ún. include guard megoldást használjuk:
Pl. egy include file így néz ki:#ifndef __include_guard_h //itt a nev include fájlonként különböző és a fáj nevére utal
#define __include_guard_h
//ide jön az include file tartalma
#endif
Ezzel azt érjük el, hogy egy TU-ban ne lehessen az include fájlt többször beszúrni. Ugyanis először az __include_guard_h makró még nincs definiálva, tehát a fájl tartalma feldolgozásra kerül, miközben a makró definiálttá válik. Következő eseleges beszúráskor a makró már definiálva lesz, de a #ifndef direktíva hamosra lesz kiértékelve, vagyis a feldolgozás az #endif után folytatódik. A körbe hivatkozások ellen az include guard nem véd, arra neked kell odafigyelni.
C forrás fájlokat tényleg nem szoktunk inklúdolni. Ha több forrás fájlból áll a projected, akkor azokat a project létrehozásakor (project fájlban) kell megadni. Ezek külön-külön fordítási egységet fognak képezni (az általuk beinklúdolt header fájlokkal együtt), amikben már újra inklúdolhatod a másik TU-ban beinklúdolt header fájlt. A külön fordítási egységekben definiált függvények és globális változók egymás közötti elérhetőségét a linkelés (linker) fogja biztosítani.
Esetenként előfordul (pl. template-ek használatakor), hogy header fájlban függvény definícót írnak, amik a különböző TU-kba való inklúdolások után a linker számára valóban többszörös defínicók lesznek, de ezt a legtöbb linker kezeli. Ettől még kerülendő ez a gyakorlat, ha nagyon kell akkor inline-ként megadható, bár azt a fordító dönti el, hogy valóban inline módon fordítja-e. -
buherton
őstag
válasz
#90088192 #6051 üzenetére
Minden .c fájlból fordítódik egy .o fájl. A .o fájlokat fogja a linker összeszerkeszteni, aminek a vége egy bináris, amit te is használni fogsz. A .h fájlok, azért kellenek, mert abban vannak deklarálva a .c/.o szempontjából a külső függőségek, amiket a linker old fel a bináris összeállítása során.
Példa: A foo.c-hez kell tartoznia egy foo.h-nak, amiben a foo.c kívülről is elérhető makrók, típusok, változók és függvények vannak felsorolva. A main.c-ben elég a foo.h-t includolni, hogy a main.c leforduljon. Majd a linker összerakja a két .o fájlt.
A fordítást/linkelést az IDE tipikusan megoldja, neked csak a forrás fájlokkal kell bíbelődni.
-
-
buherton
őstag
válasz
#90088192 #6049 üzenetére
screen.h
void delay(unsigned int usec);
void lcd_select(int s);
void strobe_E(void);
void set_y(int y);
void dsp_on(void);
void clr_scr (int t);
void write_char(int line_select, int y_offset, int c);
void string_out(char* message, float variable, char line, char y_offset);A
hardware.h
-ban pedig függvény definíciók vannak a deklarációk helyett. Nem illik ilyet csinálni. De ha nagyon muszáj, akkor azinline
kulcsszót kell elétenni.Kerüld a fölösleges pontosvesszőket. Nem illik ilyet csinálni.
Ha pedig
void
a függvény paramétere, akkor írd ki, mert így variadikus lesz.A register map-re struktúrát és uniont szoktak ráhúzni és akkor nagyon frankón végigkövetehető, hogy ez melyik regiszter. A macro mágiát érdemes elkerülni.
Az include pathért legyen a build környezet felelős és ne hardcode-ld bele a kódba.
-
#90088192
törölt tag
válasz
buherton #6048 üzenetére
Köszönöm
Akkor természetesen jönnek az újabb kérdések, ha nem baj
Akkor a különböző részegységek funkcióit hogyan tudnám szeparálni.
Vagyis a mostani screen.c bol csináltam screen.h, így működik, de ha újabb .h-t hívok meg amiben egy előzőleg meghívott hardware.h benne van akkor megint ugyan az a probléma.
Tudom hülye kérdés, ilyen alap struktúra probléma, de fogalmam sincs ezekre hogyan keressek rá.
Amit el akarok erni: reszegysegenkent kulon fuggveny konyvtar vagy mi a fitty fene.(Nem tudom minek nevezzem)
Azt hogyan kellene strukturalni?Közben kutakodtam, ezt találtam.
ez a hardware.h
#include "stdio.h"
#include <string.h>
#include <math.h>
#include <p32xxxx.h>
#include <D:\Program Files (x86)\Microchip\xc32\v2.30\pic32mx\include\peripheral\legacy\i2c_legacy.h>
#define SYS_FREQ 80000000L
#define FCY SYS_FREQ
#define F_CPU SYS_FREQ
#define DLY_COUNT (F_CPU/4000000)
#define _delay_us( dly ) {unsigned int x=0,y=dly; while(y--){x=DLY_COUNT;while(x--);}}
// DEVCFG3
// USERID = No Setting
#pragma config FSRSSEL = PRIORITY_1 // SRS Select (SRS Priority 1)
#pragma config FCANIO = OFF // CAN I/O Pin Select (Alternate CAN I/O)
#pragma config FUSBIDIO = OFF // USB USID Selection (Controlled by Port Function)
#pragma config FVBUSONIO = OFF // USB VBUS ON Selection (Controlled by Port Function)
// DEVCFG2
#pragma config FPLLIDIV = DIV_2 // PLL Input Divider (2x Divider)
#pragma config FPLLMUL = MUL_20 // PLL Multiplier (20x Multiplier)
#pragma config UPLLIDIV = DIV_2 // USB PLL Input Divider (2x Divider)
#pragma config UPLLEN = ON // USB PLL Enable (Enabled)
#pragma config FPLLODIV = DIV_1 // System PLL Output Clock Divider (PLL Divide by 1)
// DEVCFG1
#pragma config FNOSC = FRCPLL // Oscillator Selection Bits (Fast RC Osc with PLL)
#pragma config FSOSCEN = ON // Secondary Oscillator Enable (Enabled)
#pragma config IESO = ON // Internal/External Switch Over (Enabled)
#pragma config POSCMOD = XT // Primary Oscillator Configuration (XT osc mode)
#pragma config OSCIOFNC = OFF // CLKO Output Signal Active on the OSCO Pin (Disabled)
#pragma config FPBDIV = DIV_2 // Peripheral Clock Divisor (Pb_Clk is Sys_Clk/2)
#pragma config FCKSM = CSDCMD // Clock Switching and Monitor Selection (Clock Switch Disable, FSCM Disabled)
#pragma config WDTPS = PS1048576 // Watchdog Timer Postscaler (1:1048576)
#pragma config FWDTEN = OFF // Watchdog Timer Enable (WDT Disabled (SWDTEN Bit Controls))
// DEVCFG0
#pragma config DEBUG = OFF // Background Debugger Enable (Debugger is disabled)
#pragma config ICESEL = ICS_PGx2 // ICE/ICD Comm Channel Select (ICE EMUC2/EMUD2 pins shared with PGC2/PGD2)
#pragma config PWP = OFF // Program Flash Write Protect (Disable)
#pragma config BWP = OFF // Boot Flash Write Protect bit (Protection Disabled)
#pragma config CP = OFF // Code Protect (Protection Disabled)
//I/O Digital analog selection
#define Analog_digital AD1PCFG
//Screen Hardware Setup
#define DISPLAY_Dir TRISE
#define S_DATA_OUT LATE
#define S_DATA_IN PORTE
#define DISPLAY_CS1 LATGbits.LATG6
#define DISPLAY_CS2 LATDbits.LATD8
#define DISPLAY_RS LATGbits.LATG9
#define DISPLAY_RW LATDbits.LATD7
#define DISPLAY_EN LATDbits.LATD11
#define DISPLAY_CS1_Direction TRISGbits.TRISG6
#define DISPLAY_CS2_Direction TRISDbits.TRISD8
#define DISPLAY_RS_Direction TRISGbits.TRISG9
#define DISPLAY_RW_Direction TRISDbits.TRISD7
#define DISPLAY_EN_Direction TRISDbits.TRISD11
//Membrane
#define JTAGEN DDPCONbits.JTAGEN
#define MEMBRANE_MUTE LATBbits.LATB13
#define MEMBRANE_MAINS LATBbits.LATB14
#define MEMBRANE_ALARM LATBbits.LATB15
#define MEMBRANE_MUTE_Direction TRISBbits.TRISB13
#define MEMBRANE_MAINS_Direction TRISBbits.TRISB14
#define MEMBRANE_ALARM_Direction TRISBbits.TRISB15
//Analog inputs
#define REF2_5 PORTBbits.RB0
#define MUX PORTBbits.RB1
#define BAT1_CURRENT PORTBbits.RB2
#define BAT2_CURRENT PORTBbits.RB3
#define CHARGER_CURRENT PORTBbits.RB4
#define CHARGER_VOLTAGE PORTBbits.RB5
#define LOAD_VOLTAGE PORTBbits.RB8
#define BRIDGE_VOLTAGE PORTBbits.RB9
#define VREQ PORTBbits.RB10
#define IREQ PORTBbits.RB11
#define REF2_5_DIRECTION TRISBbits.TRISB0
#define MUX_DIRECTION TRISBbits.TRISB1
#define BAT1_CURRENT_DIRECTION TRISBbits.TRISB2
#define BAT2_CURRENT_DIRECTION TRISBbits.TRISB3
#define CHARGER_CURRENT_DIRECTION TRISBbits.TRISB4
#define CHARGER_VOLTAGE_DIRECTION TRISBbits.TRISB5
#define LOAD_VOLTAGE_DIRECTION TRISBbits.TRISB8
#define BRIDGE_VOLTAGE_DIRECTION TRISBbits.TRISB9
#define VREQ_DIRECTION TRISBbits.TRISB10
#define IREQ_DIRECTION TRISBbits.TRISB11
void InitalizePorts_membrane()
{
JTAGEN=0;
MEMBRANE_MUTE=1;
MEMBRANE_MAINS=1;
MEMBRANE_ALARM=1;
MEMBRANE_MUTE_Direction =0 ;
MEMBRANE_MAINS_Direction =0 ;
MEMBRANE_ALARM_Direction =0 ;
};
void InitalizePorts_display()
{
S_DATA_OUT=0;
S_DATA_IN=0;
DISPLAY_Dir=0;
DISPLAY_CS1=1;
DISPLAY_CS2=1;
DISPLAY_RS=1;
DISPLAY_RW=0;
DISPLAY_EN=1;
/* Command port direction settings */
DISPLAY_CS1_Direction =0 ;
DISPLAY_CS2_Direction =0 ;
DISPLAY_RS_Direction =0 ;
DISPLAY_RW_Direction =0 ;
DISPLAY_EN_Direction =0 ;
};
void InitalizePorts_ADC()
{
Analog_digital= 0x10C0;
AD1CON2 = 0x0000;
AD1CON3 = 0x0000; // Configure ADC conversion clock
AD1CSSL = 0x0000; // No inputs are scanned. Note: Contents of AD1CSSL are ignored when CSCNA = 0
IFS1CLR = 2; //Clear ADC conversion interrupt
IEC1SET = 2; //Enable ADC conversion interrupt
AD1CON1 = 0x00E0; // SSRC bit = 111 internal counter ends sampling and starts converting
AD1CHS = 0b1111110011110000; // Connect RB2/AN2 as CH0 input in this example RB2/AN2 is the input
AD1CSSL = 0;
AD1CON3 = 0x0F00; // Sample time = 15Tad
AD1CON2 = 0x0004; // Interrupt after every 2 samples
//Analog PORT directions
REF2_5_DIRECTION =1;
MUX_DIRECTION =1;
BAT1_CURRENT_DIRECTION =1;
BAT2_CURRENT_DIRECTION =1;
CHARGER_CURRENT_DIRECTION =1;
CHARGER_VOLTAGE_DIRECTION =1;
LOAD_VOLTAGE_DIRECTION =1;
BRIDGE_VOLTAGE_DIRECTION =1;
VREQ_DIRECTION =1;
IREQ_DIRECTION =1;
};
void I2C1_Init()
{
//***** I2C1 Hardware Init *****/
//-----Set pin drive modes-----
//I2C - drive outputs so we can manually clear lines
LATDbits.LATD9 = 1; //Start with bus in idle mode - both lines high
LATDbits.LATD10 = 1;
ODCDbits.ODCD9 = 1; //Open drain mode
ODCDbits.ODCD10 = 1;
TRISDbits.TRISD9 = 0; //SCL1 output
TRISDbits.TRISD10 = 0; //SDA1 output
/***** I2C1 Module start *****/
I2C1CON = 0x1000; //Set all bits to known state
I2C1CONbits.I2CEN = 0; //Disable until everything set up. Pins will be std IO.
I2C1BRG = 0x00C6; //set up baud rate generator
I2C1CONbits.DISSLW = 0; //Enable slew rate control for 400kHz operation
//IFS1bits.MI2C1IF = 0; //Clear I2C master int flag
I2C1CONbits.I2CEN = 1; //Enable I2C
} ; -
#90088192
törölt tag
Hello Mindenkinek
Igen kezdő vagyok minden szinten, ezert nagyon alap kérdésem, lenne amit nehéz megfogalmazni, számomra, így nem is egyszerű megtalálni a szagirodalomban.
MPLAB-ban készítettem egy működő kódot ami egy kijelzőt vezérel, eddig jó, van két .h fajlom az egyik a hardware deklaráció, a másik maga a font.
Maga a source file screen.c neven futott és tartalmazott egy void main bejegyzést, amit alá írtam az lefutott.Amit csinálni szeretnek, létrehozni egy main.c nevű fájlt, és abba meghívni a screen.c ben összedobott szubrutinokat. Ezt így megpróbáltam, és többszörös definícióra hivatkozik folyamatosan.
Valaki el tudna mondani mit csinálok rosszul?Maga a main.c
#include <stdlib.h>
#include "screen.c"
/*
*
*/
int main()
{
unsigned int x;
InitalizePorts_display();
//Wait for Vcc to settle
delay(100);
// Turn on display
dsp_on();
lcd_select(2);
clr_scr(0x00);
//*************************************************************************
// Test
//*************************************************************************
for(x=0;x<2000;x++)
{
float a=(73.00/5);
string_out("Spotty:", x ,1,0);
delay(10000);
}
return (EXIT_SUCCESS);
}es ez lenne a kijelző vezérlő
#include "hardware.h"
#include "font6x8.h"
void delay(unsigned int usec)
{
_delay_us(usec);
}
void lcd_select(int s)
{
if(s==0)
{
DISPLAY_CS1 = 1; //Selects Left side of the screen
DISPLAY_CS2 = 0; //Deselects Right side of the screen
delay(10);
}else if(s==1)
{
DISPLAY_CS1 = 0; //Deselects Left side of the screen
DISPLAY_CS2 = 1; //Selects Right side of the screen
delay(10);
}else{
DISPLAY_CS1 = 1; //Selects Left side of the screen
DISPLAY_CS2 = 1; //Selects Right side of the screen
delay(10);
}
}
void strobe_E(void) //Turns enabling line off/on
{
DISPLAY_EN = 0;
delay(10);
DISPLAY_EN = 1;
delay(10);
}
void set_y(int y) //Set Y coordinate 0-63 on the active side of the screen
{
//Y address
DISPLAY_RS = 0;
S_DATA_OUT = (0b01000000+y);
strobe_E();
}
void dsp_on(void)
{
DISPLAY_RS = 0; //Instruction mode
S_DATA_OUT = 0b00111111; //Turns display on
//DISPLAY_RS = 1; //Data Mode
delay(10);
strobe_E();
}
void clr_scr (int t)
{
int x; int y;
//line_0();
DISPLAY_RS = 0;
S_DATA_OUT = 0b11111111;
for(y=0b10111111;y>=0b10111000;y--)
{
set_y(0);
DISPLAY_RS = 0;
S_DATA_OUT = y;
strobe_E();
for(x=0; x<64; x++)
{
dsp_on();
DISPLAY_EN = 1;
DISPLAY_RS = 1;
S_DATA_OUT = t;
strobe_E();
};
};
}
void write_char(int line_select, int y_offset, int c)
{ int x; int t;
if(y_offset>63 && y_offset<122) //Check which side of the screen need to be activated
{lcd_select(1); //if the offset is bigger than 63 than the right side
t=(y_offset-64); //correction of the offset for the right side
set_y(t);
DISPLAY_RS = 0;
S_DATA_OUT = 0b10111000+line_select; //select line
strobe_E();
for(x=(c-32)*6; x<((c-32)*6)+6; x++) //Decodes the character code and make sure the data is sent by 8 bits
{
DISPLAY_RS = 1;
S_DATA_OUT = font6x8[x];
strobe_E();
}
}else if(y_offset<64 && y_offset>=0)
{
lcd_select(0); //selects the left side of the screen
t=(y_offset);
set_y(t);
DISPLAY_RS = 0;
delay(10);
S_DATA_OUT = 0b10111000+line_select;
strobe_E();
for(x=(c-32)*6; x<((c-32)*6)+6; x++) //Decodes the character code and make sure the data is sent by 8 bits
{if(t+(x-(c-32)*6)==63) //checks if the character has reached the border of the 2 sides of the screen
{lcd_select(1); //If yes selects the the right side
delay(10);
DISPLAY_RS = 0;
S_DATA_OUT = 0b10111000+line_select; // Select the relevant line
strobe_E();
set_y(0); // Resets the offset
delay(2);
DISPLAY_RS = 1;
S_DATA_OUT = font6x8[x]; //send out the data what belongs to the right side of the screen
strobe_E();
}else{ //If the Character is belong to the left side
DISPLAY_RS = 1;
S_DATA_OUT = font6x8[x]; //Sends the data to the screen
strobe_E();
}
}
}
else
{
lcd_select(2);
clr_scr(0xff);
}
}
void string_out(char* message, float variable, char line, char y_offset)
{
char test[21],i=0,j;
char a[21];
sprintf(a, "%s%f", message, variable);
while(a[i]!='\0') {test[i]=a[i]; i++;}
for(j=0;j<=i-1;j++) write_char(line,y_offset+j*6,test[j]);
} -
jattila48
aktív tag
válasz
kovisoft #6042 üzenetére
Bármelyik kivágott lyuk a forgatások miatt 4 pozíciót határoz meg, amelyek közül csak ezt az egyet lehet kivágni. Hogy egy, forgatások által meghatározott négyes melyik elemét választod ki, az 4-féleképpen lehetséges. Összesen 9 db. négyes van, amelyek mindegyikéből csak egy-egy elemet lehet kiválasztani, ezt pedig összesen 4^9 féleképpen lehet megtenni. Szerintem az én megoldásom a jó!
Egyébként ilyen módon a Cardano rácsot a (rejtjelezés kulcsát) egy 9 hosszú sorozattal lehet reprezentálni, amelynek minden eleme pl. 1,2,3, vagy 4 (pl. 1,3,2,1,2,4,3,2,4), és meg lehetne állapodni, hogy a sorozat elemei rendre az (sor,oszlop)=(1,1),(1,2)(1,3)(1,4),(1,5)(2,2),(2,3),(2,4),(3,3) elemek által reprezentált 4-esek valamelyik elemét jelentik. A fenti példából az (1,1),(6,5),(3,6),(1,4),(5,6),(5,2),(5,4),(4,5),(4,3) Cardano rács adódik, méghozzá úgy, hogy a reprezentáló elemeket helyben hagyjuk (a kulcsban ezt 1 jelöli), vagy 90 fokkal jobbra (2 jelöli), 180 fokkal jobbra (3 jelöli), 270 fokkal jobbra (4 jelöli) forgatjuk.
Lehetne bonyolítani a programot, hogy a kulcsot ilyen tömörebb módon adjuk meg.
Érdemes lenne elgondolkozni azon, hogy hogy lehet egy elég hosszú szöveget a kulcs ismerete nélkül megfejteni. A maga idejében ez elég reménytelen feladatnak látszott, azonban számítógép segítségével ma már nem az. -
kovisoft
őstag
válasz
jattila48 #6041 üzenetére
Egy 6x6-os rács esetén 9 db lyuknak kell lennie, amiknek úgy kell elhelyezkedniük, hogy 90 fokokkal elforgatva ne kerüljön egyik lyuk sem fedésbe bármely másikkal. Tehát minden egyes lyuk hozzáadása kizár (saját magával együtt) 4 pozíciót. Az első lyuk 36 helyen lehet, a következők 32, 28, ... stb. helyen, ami összesen 36*32*28*...*4*1. Viszont a lyukasztási sorrend nem számít, ugyanazt a rácsot kapjuk, bármilyen sorrendben lyukasztjuk ki a kiválasztott 9 pozíciót. Tehát az össz kombinációt el kell osztanunk 9!-sal: 36*32*28*...*4*1/9! = 262144.
Már ha jó a gondolatmenetem...
-
kovisoft
őstag
válasz
elistvan #6038 üzenetére
A kódolandó szöveg 3x36 karakterből áll. Mivel egy 6x6-os rács 36 karaktert tartalmaz, így 3 db rács fog keletkezni a kódolás során. A kódolás menete a következő: Megfordítod a kódolandó szöveget (amely tehát így fog kezdődni: HAZRXT...). Veszed a Cardano-rácsot (amiben 0-k és1-esek vannak), ill. veszed sorban a megfordított szöveg karaktereit. Létrehozol egy újabb 6x6-os tömböt, és belerakod sorban a karaktereket arra az [i][j] pozícióra, ahol a Cardano-rácsban 0 van (pl. első sor 2., 4., 6. eleme, második sor 5. eleme, stb, összesen 9 db). Amikor végigértél a Cardano-rácson, elforgatod jobbra 90 fokot, és megismétled az eljárást a következő 9 db karakterre. Ezt megcsinálod négyszer, és elfogyott a megfordított szöveg első 36 karaktere. A maradék 2x36 karakterhez létrehozol egy-egy újabb 6x6-os tömböt, és kitöltöd ugyanezzel a módszerrel. A végén előáll 3 db 6x6-os tömböd, ezeket kell kiírnod a sandormatyas.txt file-ba (tippre soronként).
-
jattila48
aktív tag
válasz
jattila48 #6035 üzenetére
Közben rájöttem, mikor van értelme a tömbre mutató pointer használatának.
int iia[10][5];
int (*piia)[5];
piia=iia;
Az iia kétdimenziós tömb neve önmagában leírva nem int ** típusú, hanem int (*)[5] típusú. Ezért ha ezt a kétdimenziós tömböt akarjuk átadni az f fv.-nek, akkorvoid f(int (*x)[5]);
prototípusúnak kell lennie. -
jattila48
aktív tag
válasz
kovisoft #6034 üzenetére
A baj csak az, hogy a tömbre mutató pointerhez hozzá van kötve a tömb mérete. Tehát, ha a tömbre mutató ponter egy fv. argumentuma, akkor annak semmilyen más méretű tömböt nem lehet átadni. Így aztán a tömb méretét lekérdezni nem sok értelme van, hiszen ez a fv. csak ilyen méretű tömböt képes fogadni.
Nem vitatkozni akarok, csupán érdekel, hogy miért létezik ez a konstrukció a C nyelvben. Akkor lenne értelme, ha nem lehetne elkerülni a használatát, vagy az elkerülése bonyolultabb lenne. Ehelyett mindig el lehet kerülni, és egyszerűbben, mint használni. Pointereket leggyakrabban azért haználunk, hogy az általuk mutatott memória címen megváltoztassuk a memória tartalmát (vagy mert a stack-en nem lehet nagyméretű objektumokat átadni). Ehhez képest a tömbre mutató pointeren keresztül nem változtatjuk meg a tömböt (ami itt a tömb címét jelenti), hiszen az nem is balérték. Úgy tűnik, hogy igazából semmi értelme nincs, mindössze a C típusdefiníciós szintaxisának egy csökevénye. -
kovisoft
őstag
válasz
jattila48 #6033 üzenetére
Ha pia egy másik függvényben van, akkor ott nem látod az eredeti tömböket. Lehet pl. pia egy függvény paramétere, és fontos, hogy szigorúan egy adott méretű tömb legyen neki átadva.
Egyébként ha ez most már arra megy ki, hogy hogyan lehet elkerülni tömbre mutató pointer használatát, arra én is tudok módszereket mondani, ilyen vitában nem kívánok részt venni. De eredetileg mintha azt kérdezted volna, hogy mire lehet használni. Továbbra is az a válaszom, hogy olyan esetben, amikor számít a megcímzett tömb sizeof-ja.
-
jattila48
aktív tag
válasz
kovisoft #6032 üzenetére
Ha több ugyanolyan típusú tömböt egységesen akarok kezelni, akkor:
int ia1[5],ia2[5];
int *pia;
pia=ia1;
//valamit csinálok a pia pointeren keresztül
pia=ia2;
//stb...Ha a méretükre van szükségem, akkor
ARRAYSIZE(ia1)
,
de még egyszerűbb, ha#define ASIZE 5
int ia1[ASIZE],ia2[ASIZE];
... -
jattila48
aktív tag
válasz
Domonkos #6024 üzenetére
Ha megnézed, a getopt paramétere char *[] típusú, nem pedig (char *)[] típusú. A két típus különböző. Én az utóbbit kérdezem. Az első címeket tartalmazó tömb, vagyis az elemei pointerek. A második pedig tömbre mutató pointer, aminek értéke a tömb címe. Régóta programozok C-ben, tudom mire való az argv, getopt és társai. De ez más.
-
jattila48
aktív tag
Tudnátok a tömbre mutató pointernek valami értelmes alkalmazását mondani?
int ia[2];
int (*pia)[2];
pia=&ia;
pia az ia tömbre mutató pointer, értéke az ia tömb címe. Nade mire jó? -
kovisoft
őstag
válasz
elistvan #6018 üzenetére
A 6x6-os kulcsot (cardano.txt) beolvashatod egy 6x6-os tömbbe (pl. char cardano[6][6]). Ugyanígy beolvasod a titkos.txt szöveget egy másik 6x6-os titkos[6][6] tömbbe. A 90 fokkal való forgatás úgy történik, hogy felcseréled a két koordinátát és az egyiket "megfordítod" (azaz 5-ből kivonod). Attól függően lesz jobbra vagy balra forgatás, hogy melyiket vonod ki 5-ből, pl. jobbra forgatás: [i][j] -> [j][5-i]. A dekódolás úgy történik, hogy mész végig sorfolytonosan egyszerre a cardano tömbön és a titkos tömbön, és ahol a cardano-ban 0 van, a titkos-ból ugyanarról a pozícióról kiolvasol egy karaktert. Ha végigértél a tömbön, akkor veszed a 90 fokkal elforgatott kulcsot, és azza újra végigcsinálod ezt, stb.
-
elistvan
őstag
Sziasztok!
Ebben az I 504-es megoldásának,. hogy kellene nekiállni? Egyetemen ez a beadandó 1/4-e az egyik tárgyhoz, de lövésem sincs, hogy kéne megoldani. Előre is köszi.
-
kovisoft
őstag
válasz
kunzoltan77 #6015 üzenetére
Az az alapvető baj a függvényeddel, hogy anélkül vizsgálod az egyes karaktereket, hogy figyelembe vennéd azt, hogy az adott karakterkombináció milyen pozícióban fordulhat vagy nem fordulhat elő. Pl. mi van, ha az 1:1 kétszer is szerepel a sorban? Akkor el fogod fogadni, holott csak egyszer fordulhatna elő eredmény. Vagy mi van, ha az 1:1 a csapatok neve előtt van? Akkor is elfogadod. De ugyanez igaz a szóközös vagy a kötőjeles vizsgálataidra is.
Olyasmit kellene csinálnod, hogy a string elemzése közben nyilvántartod, hogy éppen milyen állapotban vagy, azaz éppen milyen alkotórészt azonosítasz. Legelőször a hazai csapatot kell azonosítani, addig nem is jöhet pl. kettőspont. A szabályos hazai csapatnév után az elválasztó szóköz-kötőjel-szóköznek kell jönnie. Utána a vendég csapatot kell azonosítani, közben sem jöhet pl. kettőspont. Ha megvan a szabályos vendég csapatnév, akkor a hazai eredményt kell azonosítani, amiben viszont csak számjegy lehet. Aztán kettőspont kell jöjjön. Végül a vendég eredményt kell azonosítanod, abban is csak számjegy lehet. Utána meg már nem lehet más.
Tehát mindig attól függ, miket fogadsz el, hogy éppen melyik mező azonosítása közben vagy.
-
kunzoltan77
friss újonc
Sziasztok, egy kéréssel fordulnék felétek. Adott a következő feladat:
https://progcont.hu/progcont/100041/?pid=200534A kód amit írtam rá:
[link]A problémám az lenne, hogy a feladatnak ezt a részét nem tudom leprogramozni és módosítani a kódot:
"Kettőspont kizárólag az eredményt leíró részben fordulhat elő a sztringben, a két csapat eredményét választja el egymástól, szóköz karakterek nélkül."
A program lefut és megkapom a jó eredményt, de a progcont hiba miatt, ami feltehetően a fentebbi, nem fogadja.
Nagyon szépen megköszönöm nektek ha tudnátok segíteni.
Zoltán
-
sztanozs
veterán
válasz
Domonkos #6009 üzenetére
Nem, mivel 100/j UB, amennyiben nincs ellenőrizve, hogy a j egyenlő-e 0-val.
Tehát, ha az if-et kioptimalizálná, akkor az egész függvényt ki kell, mert a 100/j UB...Szerintem a fordító inkább "beoptimalizál" egy if j !=0-t a kódba, ha nincs ott, hogy ne legyen HW interrupt, csak szoftveres.
-
Domonkos
addikt
válasz
sztanozs #6008 üzenetére
Mert a 0-val valo osztas UB, igy ezzel a lehetoseggel nem is kell a forditonak szamolnia. Mivel ezzel nem kell szamolnia, igy feltetelezheto, hogy j nem 0; am ekkor a feltetel mindig igaz, ezert az NOP-olhato. Ekkor viszont a masik return elerhetetlen, igy az is elhagyhato.
-
Domonkos
addikt
Ha a 0-val valo osztas UB, akkor garantalja-e azt valami, hogy egy ilyen kod eseten az
if
is biztosan belefordul a gepi kodba (es persze hogy areturn 69
is marad)?int
d(int j)
{
if (j != 0)
return 100/j;
return 69;
} -
kovisoft
őstag
válasz
elistvan #6000 üzenetére
Itt egy példa a nyerőszámok húzásának függvénybe való áthelyezésére:
void nyeroszamok_huzasa(int nyeroszamok[], int darab){
for(int i=0;i<darab;i++){
int num = (rand() % (80 - 1 + 1)) + 1;
if(num >= 1 && num <= 80 && !tartalmazza(nyeroszamok,darab,num)){
nyeroszamok[i] = num;
}else{
i--;
}
}
}És így tudod meghívni onnan, ahol korábban maga ciklus volt:
int nyeroszamok[20] = {0};
nyeroszamok_huzasa(nyeroszamok, 20);Hasonlóan mehet a többi blokk is, de lesz köztük olyan függvény, aminek több tömböt is át kell majd adni, mint pl. a találatok meghatározása, ami 3 tömbbel dolgozik: tippeltszamok, nyeroszamok, talalat.
A rand() használatához még annyit, hogy ez alapból mindig ugyanonnan indítja a generálást, tehát minden futásra ugyanazt a szekvenciát kapod. Ezért célszerű seed-elni az első hívás előtt valami futásonként eltérő számmal, pl. az aktuális idővel, hogy mindig más random szekvenciát kapj:
srand(time(0));
Új hozzászólás Aktív témák
Hirdetés
● olvasd el a téma összefoglalót!
● ha kódot szúrsz be, használd a PROGRAMKÓD formázási funkciót!
- Vigneau interaktív lokálblogja
- One otthoni szolgáltatások (TV, internet, telefon)
- PlayStation 5
- Milyen légkondit a lakásba?
- A kínai gyártók 3D arcazonosítással kísérleteznek
- Okos Otthon / Smart Home
- Xiaomi 13T és 13T Pro - nincs tétlenkedés
- Sony MILC fényképezőgépcsalád
- Apple asztali gépek
- Sorozatok
- További aktív témák...
- Bomba ár! HP EliteBook 840 G4 - i5-7GEN I 16GB I 256GB SSD I 14" FHD Touch I Cam I W10 I Garancia!
- Bomba ár! Dell Latitude E7250 - i5-5GEN I 8GB I 256SSD I 12,5" HD I HDMI I Cam I W10 I Garancia!
- AKCIÓ! HP Victus 16-R1002NF Gamer notebook - i7 14700HX 16GB RAM 1TB SSD RTX 4070 8GB WIN11
- 30+ típus!!! Lenovo Thinkpad X1 Carbon, Thinkbook, 2-in-1 Workstation, Yoga, 5-14.gen. Ultra 7!!!
- LG 27GR93U-B - 27" IPS - UHD 4K - 144Hz 1ms - NVIDIA G-Sync - FreeSync Premium - HDR 400
Állásajánlatok
Cég: PCMENTOR SZERVIZ KFT.
Város: Budapest
Cég: Promenade Publishing House Kft.
Város: Budapest