Pagina 1 di 2
[C] Errori e dubbi vari
Inviato: dom 20 lug 2008, 16:53
da anycolouryoulike
In seguito a questo
viewtopic.php?f=2&t=25445, sto cercando di fare un programmino per convertire una stringa binaria in ASCII.
A dire il vero per adesso mi basterebbe solo riuscire a memorizzare (forse c'è un termine più adatto per dirlo?) le cifre a 8 a 8, ma ottengo solo segmentation fault.
Probabilmente c'è un modo molto migliore per fare quello che sto cercando di fare, inoltre non ho idea di come fare la conversione.
Codice: Seleziona tutto
#include <malloc.h>
#include <stdio.h>
#define MAXLENGTH 1000
main()
{
char **a=malloc(sizeof(char *)*MAXLENGTH/9);
char *s=malloc(sizeof(char)*MAXLENGTH);
int i,j,c;
int k=1;
for(i=j=0;k;i++)
{
*(a+i)=s+j;
while(k&&j<8*(i+1)+i)
{
if(c=getchar()&&(c='0'||c='1'))
*(s+j++)=c;
else
k=0;
}
*(s+j++)='\0';
}
if(k==0)
{
printf("Invalid string");
exit(1);
}
for(j=0;j<=i;j++)
puts(*(a+i));
free(s);
free(a);
}
E poi perché se invece di usare '\0' uso NULL mi dà errore?
Grazie
Re: [C] Errori e dubbi vari
Inviato: dom 20 lug 2008, 17:03
da phobos3576
'\0' è un byte di valore ZERO che corrisponde al codice ASCII NUL (
00h), da non confondere però con
NULL che in C rappresenta un puntatore all'indirizzo del primo byte della RAM; in modalità protetta a 32 bit, quell'indirizzo vale
00000000h
Inoltre, questo qui:
è un modo suicida di programmare!
Quale di queste operazioni viene eseguita per prima?
Ci si affida alle convenzioni sulla precedenza degli operatori, ma nemmeno chi ha scritto il programma poi riesce a capire il codice!
Re: [C] Errori e dubbi vari
Inviato: dom 20 lug 2008, 19:36
da gioco
Concordo con phobos3576.
Aggiungo:
qui
mi sa che ci sono due assegnamenti di troppo.
Re: [C] Errori e dubbi vari
Inviato: dom 20 lug 2008, 19:54
da anycolouryoulike
Grazie ad entrambi.
Ho sistemato un paio di cose e reso leggibile:
Codice: Seleziona tutto
#include <malloc.h>
#include <stdio.h>
#define MAXLENGTH 1000
main ()
{
char **a = malloc (sizeof (char *) * MAXLENGTH / 9);
char *s = malloc (sizeof (char) * MAXLENGTH);
int i, j, c;
int k = 1;
for (i = j = 0; k; i++)
{
*(a + i) = s + j;
while (k && j < (8 * (i + 1) + i))
{
if (c = getchar () && (c == '0' || c == '1'))
*(s + j++) = c;
else
k = 0;
}
*(s + j++) = '\0';
}
for (j = 0; j <= i; j++)
puts (*(a + j));
free (s);
free (a);
}
Ma sempre segmentation fault:
Codice: Seleziona tutto
$ cat prova
0111000001110010011011110111011001100001
$ a.out < prova
zsh: segmentation fault a.out < prova
Re: [C] Errori e dubbi vari
Inviato: dom 20 lug 2008, 21:57
da FireEater
Fai il debug del programma! Ti aiuterà sicuramente ad individuare l'istruzione colpevole.
Re: [C] Errori e dubbi vari
Inviato: dom 20 lug 2008, 22:25
da phobos3576
Salve.
Siamo Brian W. Kernighan e Dennis M. Ritchie; supponendo che i dati binari siano contenuti nel file
binstream.bin, noi suggeriamo di procedere in questo modo:
Codice: Seleziona tutto
#include <stdio.h>
int main (void)
{
FILE *mystream = fopen("binstream.bin", "rb");
int nextbyte;
while ((nextbyte = getc(mystream)) != EOF)
printf("%c", nextbyte);
fclose(mystream);
}
Re: [C] Errori e dubbi vari
Inviato: dom 20 lug 2008, 22:43
da anycolouryoulike
Sto facendo il debug con gdb. Incredibile quante cose si imparano!
Ad esempio, io sapevo che malloc non puliva la memoria, invece sto vedendo che ogni componente di s è uguale a \0. Come mai?
@phobos3576: lo terrò in considerazione, ormai però ho pensato troppo per rinunciare!
Re: [C] Errori e dubbi vari
Inviato: lun 21 lug 2008, 0:59
da Slippery
http://cvsweb.netbsd.org/bsdweb.cgi/~ch ... text/plain
Checchè ne dica la manpage, questa implementazione della malloc sembra fare effettivamente un memset a 0 della memoria
Re: [C] Errori e dubbi vari
Inviato: lun 21 lug 2008, 8:31
da Blizzard
casualità IMHO!
provate questo
Codice: Seleziona tutto
#include <stdio.h>
int main()
{
char *p=malloc(100);
printf("Print p: %s",p);
p[0]=p[1]=p[2]='a';
free(p);
p=malloc(100);
printf("\nPrint p riallocata: %s\n",p);
return 0;
}
E' una sola istruzione! non fate l'errore di non considerare lo zeroing della memoria dopo una malloc. Il programma potrebbe esplodere anche la quinta volta che chiamate una funzione (e la malloc è in quella funzione). Ci sono capitato
ciao
Gio
Re: [C] Errori e dubbi vari
Inviato: lun 21 lug 2008, 14:31
da anycolouryoulike
Grazie.
Altra cosa:
The problem is distinguishing the end of input from valid data. The solution is that getchar
returns a distinctive value when there is no more input, a value that cannot be confused with
any real character. This value is called EOF, for ``end of file''. We must declare c to be a type
big enough to hold any value that getchar returns. We can't use char since c must be big
enough to hold EOF in addition to any possible char. Therefore we use int.
Ma EOF non è un carattere ASCII?
Perché non dovrebbe starci in un char?
@Blizzard:
Correggimi se sbaglio, ma quando stampi p, nel caso la memoria allocata non contenga un \0 prima della sua fine, potrebbe darti anche segmentation fault, giusto?
Re: [C] Errori e dubbi vari
Inviato: lun 21 lug 2008, 15:15
da gioco
Provato:
?
EOF è una macro definita in stdio.h.
In ASCII c'è il carattere non stampabile, quello che si ottiene con CTRL-D, che mi sembra si chiami EOT (end of transmission), e viene normalmente usato per segnalare da linea di comando ad un programma interattivo che l'input è terminato (tipo se in bash si scrive "if [];", si da invio e poi si preme CTRL-D).
Sono però due cose diverse.
Re: [C] Errori e dubbi vari
Inviato: lun 21 lug 2008, 16:06
da Blizzard
@Blizzard:
Correggimi se sbaglio, ma quando stampi p, nel caso la memoria allocata non contenga un \0 prima della sua fine, potrebbe darti anche segmentation fault, giusto?
Nella maggior parte dei casi continua a stampare finchè non incontra un \0 ma penso qualora non ci siano \0 dovrebbe darti una bella segmentation fault.
Avevo scritto un post chilometrico ma l'ho cancellato.
Il fatto che azzeri la memoria mi ha incuriosito e l'ho riscontrato non solo nella malloc ma anche in altre cose.
Le variabili ad esempio non sono soggette a questa cosa ma ho fatto dei test ed ottenuto comportamenti strani (che non so fino a che punto possano essere random).
Ho il presentimento che il gcc si preoccupa per noi e non ce lo dice
ciao
Gio
Re: [C] Errori e dubbi vari
Inviato: lun 21 lug 2008, 16:14
da phobos3576
EOF è un int!
Generalmente vale -1 ma è sempre un grave errore usare -1 al posto di EOF perché così facendo si rende il programma dipendente dal particolare SO usato.
Funzioni come int getchar(void) restituiscono, appunto, un int perchè, oltre a leggere caratteri, possono imbattersi nella fine dell'output indicata da un EOF che è un int e non un char !
Re: [C] Errori e dubbi vari
Inviato: lun 21 lug 2008, 17:20
da 414N
Questo thread mi ha stuzzicato e, per colpa di anycolouryoulike

, mi sono messo sotto ad implementare un programmino per convertire da binario ad ASCII una stringa.
Qui sotto riporto il codice che ne è risultato. Probabilmente conterrà schifezze (sono un po' arrugginito col C), ma a me funziona.
Prendetene spunto tranquillamente:
Codice: Seleziona tutto
/*
bin2dec2ascii
A basic C program to convert a binary number to decimal and ASCII form,
without the use of strtol() like functions.
Made by 414N
*/
# include <stdio.h>
# include <malloc.h>
# include <string.h>
# include <ctype.h>
# include <stdlib.h>
# define MAXLENGTH 100
/*
This function checks that the char* given in input contains only '0' or '1'
Every other character (including newline, so be warned using fgets to read
the string from stdin) makes it fail.
Returns 0 if the given number is a valid binary number, -1 otherwise.
*/
int checkNumber (char *numToCheck);
/*
This function converts the given binary number (as a char sequence) to an unsigned decimal.
It ignores the sign.
*/
long convertToDec (char *numToConvert);
/*
This function converts the given binary number (as a char sequence) to a signed decimal.
*/
long convertToDecSign (char *numToConvert);
/*
This function returns the two's-complement of the binary number given in input.
This procedure is needed whenever you encounter a negative binary number (the
Most Significative Bit is set to '1') and you want to know its absolute value.
*/
char* c2 (char *number);
/*
This function returns the ASCII representation of the given binary string.
*/
char* convertToASCII (char *numToConvert);
/*
This function returns the byte index in input. The index starts at 1.
*/
char *getByte (int byteNum, char* string);
/*
This function adds '0's to the number given in order to align to a
multiple of 8
*/
void adjustBits (char *bits);
int main (int argc, char *argv[])
{
// The pointer to the binary number to be read from stdin.
char *binNumber = malloc ( (sizeof *binNumber) * MAXLENGTH );
if (binNumber == NULL){
fprintf (stderr, "First memory allocation failed. Exiting.\n");
return 1;
}
// Read the number from stdin
fprintf (stdout, "\nPlease enter the binary number.\n");
fscanf (stdin, "%100s", binNumber);
fprintf (stdout, "\nOk, you entered %s.", binNumber);
// Checking that the number consists only of '0' and '1'.
if (checkNumber(binNumber) != 0){
fprintf (stderr, "\nYou entered an invalid binary number.\n");
return 2;
}
fprintf (stdout, "\nDecimal conversion\n");
fprintf (stdout, "\nWithout sign:\n\t%sb = %li\n", binNumber, convertToDec (binNumber));
fprintf (stdout, "\nWith sign:\n\t%sb = %li\n", binNumber, convertToDecSign (binNumber));
fprintf (stdout, "\nASCII conversion\n");
adjustBits (binNumber);
fprintf (stdout, "\n%s : %s\n", binNumber, convertToASCII(binNumber));
free (binNumber);
return 0;
}
int checkNumber (char *numToCheck)
{
int i;
for (i = 0; i < strlen (numToCheck); i++){
if (numToCheck[i] != '0' && numToCheck[i] != '1')
return -1;
}
return 0;
}
long convertToDec (char *numToConvert)
{
int i;
long num = 0;
long exp = 1;
for (i = strlen(numToConvert) - 1; i >= 0; i--){
if (numToConvert[i] == '1')
num += exp;
exp *= 2;
}
return num;
}
long convertToDecSign (char *numToConvert)
{
if (numToConvert[0] == '1'){
// The number is negative.
char *numC2 = c2 (numToConvert);
return -1 * convertToDec(numC2);
}else
return convertToDec (numToConvert);
}
char* c2 (char *number)
{
char *cNumber = NULL;
int i = 0;
int carry = 0;
cNumber = malloc ( (sizeof *cNumber) * (strlen (number) + 1) );
if (cNumber == NULL){
fprintf (stderr, "\nMemory allocation error. Exiting.\n");
exit (3);
}
for (i = 0; i <= strlen(number); i++)
switch (number[i])
{
case '0':
cNumber[i] = '1';
break;
case '1':
cNumber[i] = '0';
break;
default:
cNumber[i] = number[i];
}
for (i = strlen (cNumber) - 1, carry = 1; i >= 0; i--)
switch (cNumber[i])
{
case '0':
if (carry == 1){
cNumber[i] = '1';
carry = 0;
}
break;
case '1':
if (carry == 1)
cNumber[i] = '0';
}
return cNumber;
}
char* convertToASCII (char *numToConvert)
{
char *string = NULL;
char *byte = NULL;
int bytes = 0;
int i = 0;
// long number = 0;
char character = '0';
// First off, we align the bits to be a multiple of 8.
adjustBits (numToConvert);
// Next, we allocate the space to host the ASCII representation
// of the binary number.
bytes = strlen (numToConvert)/8;
string = malloc ((sizeof *string) * bytes + 1);
if (string == NULL){
fprintf (stderr, "\nMemory allocation error. Exiting\n");
exit (4);
}
// Now, for each byte contained inside the string, we
// get its ASCII representation.
for (i = 0; i < bytes; i++){
byte = getByte (i + 1, numToConvert);
if (strcmp (byte, "Error") == 0){
fprintf (stderr, "\nError getting byte number %d out of %s", i + 1, numToConvert);
exit (6);
}
character = (char) convertToDec (byte);
// if (isgraph (character))
string[i] = character;
}
string [i] = '\0';
return string;
}
char* getByte (int byteNum, char* string)
{
char *byte = NULL;
int index1 = 0;
int index2 = 0;
int i = 0;
int j = 0;
if (byteNum > strlen (string) || byteNum <= 0)
return "Error";
index1 = (byteNum - 1) * 8;
index2 = index1 + 7;
byte = malloc ( (sizeof *byte) * 9 );
if (byte == NULL){
fprintf (stderr, "\nMemory allocation error. Exiting\n");
exit (5);
}
for (i = index1, j = 0; i <= index2 || i < strlen (string); i++, j++)
byte[j] = string [i];
if (i != index2)
byte[8] = '\0';
return byte;
}
void adjustBits (char *bits)
{
char *zeroes = NULL;
char *newString = NULL;
int i = 0;
if (strlen (bits) % 8 != 0){
// We need to fill the rest with '0's.
int zerosToAdd = 8 - strlen(bits) % 8;
zeroes = malloc ( (sizeof *zeroes) * zerosToAdd + 1);
if (zeroes == NULL){
fprintf (stderr, "\nMemory allocation error (zeroes). Exiting\n");
exit (6);
}
for (i = 0; i < zerosToAdd; i++)
zeroes[i] = '0';
zeroes[zerosToAdd] = '\0';
newString = malloc ( (sizeof *newString) * ( strlen(bits) + zerosToAdd) + 1);
if (newString == NULL){
fprintf (stderr, "\nMemory allocation error (newString). Exiting\n");
exit (7);
}
strcpy (newString, zeroes);
free (zeroes);
strcat (newString, bits);
strcpy (bits, newString);
}
}
Una compilata con
e vai col lissio

Re: [C] Errori e dubbi vari
Inviato: lun 21 lug 2008, 18:10
da Blizzard
scusate... non ho letto i codici

ma qui si parla di programmi che prendono in input una stringa di char 01 e ne restituiscono il corrispettivo ascii???